with 语法

  1. const obj = {a:100, b: 200}
  2. console.log(obj.a) // 100
  3. console.log(obj.b) // 200
  4. console.log(obj.c) // undefined
  5. // 使用width,能改变 {} 内自由变量的查找方式
  6. // 将 {} 内自由变量当做 obj 的属性来查找
  7. with(obj) {
  8. console.log(a) // 100
  9. console.log(b) // 200
  10. console.log(c) // ReferenceError: c is not defined
  11. }
  • 改变 {} 内自由变量的查找规则,当做 obj 属性来查找
  • 如果找不到匹配的 obj 属性,就会报错
  • with 要慎用,它打破了作用域规则,易读性变差

模板编译

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

    Vue模板被编译成什么?

    1. # 安装这个npm包
    2. yarn add vue-template-compiler --save
    3. # 或者
    4. npm install vue-template-compiler --save
    截屏2020-10-20 下午7.16.51.png

    插值

    ``javascript const compiler = require('vue-template-compiler') // 插值 const template =

    {{message}}

    `

// 编译 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,则能转换为字符串 / /*/

  1. <a name="rqugn"></a>
  2. ## 表达式
  3. ```javascript
  4. // 表达式
  5. const template = `<p>{{flag ? message : 'no message found'}}</p>`
  6. with(this){return _c('p',[_v(_s(flag ? message : 'no message found'))])}

属性和动态属性

  1. const template = `
  2. <div id="div1" class="container">
  3. <img :src="imgurl" />
  4. </div>
  5. `
  6. with(this){return _c('div',
  7. {staticClass:"container",attrs:{"id":"div1"}},
  8. [
  9. _c('img',{attrs:{"src":imgurl}})])}

条件

  1. const template = `
  2. <div>
  3. <p v-if="flag === 'a'">A</p>
  4. <p v-else>B</p>
  5. </div>
  6. `
  7. with(this){return
  8. _c('div',[(flag === 'a')?_c('p',[_v("A")]):_c('p',[_v("B")])])}

循环

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

事件

 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;

this is a tag

小结

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

直接script引入,然后写vue模板,编译过程会在浏览器里执行,整体效率不如使用打包工具来的高