模板编译 with 语法

本文深入探讨了Vue中的模板编译,解析了`with`关键字如何改变作用域规则,以及模板如何被编译成`render`函数。通过示例展示了模板中的插值、表达式、属性、条件、循环、事件和`v-model`的编译结果。最后,讨论了模板编译的过程,包括基于`vnode`的`patch`和`diff`操作,并强调了在开发环境中使用`webpack`和`vue-loader`进行模板编译的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

with 语法

const obj = {a:100, b: 200}

console.log(obj.a) // 100
console.log(obj.b) // 200
console.log(obj.c) // undefined

// 使用width,能改变 {} 内自由变量的查找方式
// 将 {} 内自由变量当做 obj 的属性来查找
with(obj) {
	console.log(a) // 100
  console.log(b) // 200
  console.log(c) // ReferenceError: c is not defined
}

● 改变 {} 内自由变量的查找规则,当做 obj 属性来查找
● 如果找不到匹配的 obj 属性,就会报错
● with 要慎用,它打破了作用域规则,易读性变差

模板编译

● 模板不是html,有指令、插值、JS表达式,能实现判断、循环
● html是标签语言,只有 JS 才能实现判断、循环(图灵完备的)
● 因此,模板是转换为某种JS代码,即模板编译

Vue模板被编译成什么?

# 安装这个npm包
yarn add vue-template-compiler --save
# 或者
npm install vue-template-compiler --save

在这里插入图片描述
插值

const compiler = require('vue-template-compiler')
// 插值
const template = `<p>{{message}}</p>`

// 编译
const res = compiler.compile(template)
console.log(res.render)

/*****/
with(this){return _c('p',[_v(_s(message))])}
/* 在vue源码中可以搜到各种函数的名称
	这个 this 就是 vm = new Vue()  实例
  很类似于 h('p', {}, [...]) 函数
  _c 是 createElement 用于生成vnode
  _v 是 createTextVNode 用于生成文本的vnode
  _s 是 toString,以防message是true,则能转换为字符串
*/
/*****/

表达式

// 表达式
const template = `<p>{{flag ? message : 'no message found'}}</p>`

with(this){return _c('p',[_v(_s(flag ? message : 'no message found'))])}

属性和动态属性

const template = `
   <div id="div1" class="container">
     <img :src="imgurl" />
   </div>
 `

with(this){return _c('div',
    {staticClass:"container",attrs:{"id":"div1"}},
    [
      _c('img',{attrs:{"src":imgurl}})])}

条件

 const template = `
   <div>
       <p v-if="flag === 'a'">A</p>
       <p v-else>B</p>
   </div>
 `
 
 with(this){return 
        _c('div',[(flag === 'a')?_c('p',[_v("A")]):_c('p',[_v("B")])])}

循环

 const template = `  
   <ul>
     <li v-for="item in list" :key="item.id">{{item.title}}</li>
   </ul>
 `
 
 with (this) {
    return
      _c('ul', _l((list), function (item) { return _c('li', { key: item.id }, [_v(_s(item.title))]) }), 0)
  }

事件

 const template = `
   <button @click="clickHandler">submit</button>
`
 
 with(this){return 
    _c('button',{on:{"click":clickHandler}},[_v("submit")])}

v-model

const template = `<input type="text" v-model="name" />`

with(this){return 
      _c('input',{directives:[{name:"model",rawName:"v-model",
      value:(name),expression:"name"}],attrs:{"type":"text"},domProps:{"value":(name)},
      on:{"input":function($event){if($event.target.composing)return;
        name=$event.target.value}}})}

● 模板编译为render函数,执行render函数返回vnode
● 基于vnode再执行patch和diff
● 使用webpack vue-loader,会在开发环境下编译模板(重要)

vue组件中使用render代替template

Vue.component('heading', {
  // template: ``
	render: function (createElement) {
  	return createElement(
    	'h' + this.level,
      [
      	createElement('a', {
        	attrs: {
          	name: 'headerId',
            href: '#' + 'headerId'
          }
        }, 'this is a tag')
      ]
    )
  }
})
相当于渲染 this.level = 1; <h1><a name="headerId" href="#headerId">this is a tag</a></h1>

小结

● 模板编译为rander函数,执行render函数返回vnode
● 基于vnode再执行patch和diff
● 使用webpack vue-loader,会在开发环境下编译模板(重要)
直接script引入,然后写vue模板,编译过程会在浏览器里执行,整体效率不如使用打包工具来的高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值