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模板被编译成什么?
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模板,编译过程会在浏览器里执行,整体效率不如使用打包工具来的高
|