with 语法

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/with

vue 模版编译

  • 模板编译为 render 函数,执行 render 函数返回 vnode
  • 基于 vnode 在执行 patchdiff
  • 使用 webpack vue-loader,会在开发环境下编译模板

本质:template 最终也会被 vue-template-compiler 编译为 render 函数,执行 render 函数生成 vnode,之后才是 Vue 最终执行的。
如下查看编译过程:

插值

  1. const compiler = require('vue-template-compiler')
  2. const template = `<p>{{message}}</p>`
  3. // 编译
  4. const { render } = compiler.compile(template)
  5. console.log(render)
  6. // with(this){return _c('p',[_v(_s(message))])}
  7. // 相当于执行这个函数,例如下面:
  8. // function(){with(this){return _c('p',[_v(_s(message))])}}
  9. // with(this){return createElement('p',[createTextVNode(toString(message))])}
  10. // h -> vnode
  11. // createElement -> vnode
  12. // const vm = new Vue({...})
  13. // this -> vm

表达式

  1. const compiler = require('vue-template-compiler')
  2. const template = `<p>{{flag ? message : 'no message found'}}</p>`
  3. // 编译
  4. const { render } = compiler.compile(template)
  5. console.log(render)
  6. // with(this){return _c('p',[_v(_s(flag ? message : 'no message found'))])}

属性和动态属性

  1. const compiler = require('vue-template-compiler')
  2. const template = `
  3. <div id="div1" class="container">
  4. <img :src="imgUrl"/>
  5. </div>
  6. `
  7. // 编译
  8. const { render } = compiler.compile(template)
  9. console.log(render)
  10. // with(this){return _c('div',{staticClass:"container",attrs:{"id":"div1"}},[_c('img',{attrs:{"src":imgUrl}})])}

条件

  1. const compiler = require('vue-template-compiler')
  2. const template = `
  3. <div>
  4. <p v-if="flag === 'a'">A</p>
  5. <p v-else>B</p>
  6. </div>
  7. `
  8. // 编译
  9. const { render } = compiler.compile(template)
  10. console.log(render)
  11. // with(this){return _c('div',[(flag === 'a')?_c('p',[_v("A")]):_c('p',[_v("B")])])}

循环

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

事件

  1. const compiler = require('vue-template-compiler')
  2. const template = `<button @click="handlerClick">submit</button>`
  3. // 编译
  4. const { render } = compiler.compile(template)
  5. console.log(render)
  6. // with(this){return _c('button',{on:{"click":handlerClick}},[_v("submit")])}

v-model

  1. const compiler = require('vue-template-compiler')
  2. // v-model
  3. const template = `<input type="text" v-model="name">`
  4. // 编译
  5. const { render } = compiler.compile(template)
  6. console.log(render)
  7. // 主要看 input 事件
  8. // 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,在到渲染和更新
  • vue 组件可以使用 render 代替 template
  • 在有些复杂情况中,不能用 template ,可以考虑使用 render
  • react 一直都在使用 render(没有模板)

vue template explorer

Vue2:https://template-explorer.vuejs.org Vue3:https://vue-next-template-explorer.netlify.app