Skip to content

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 最终执行的。 如下查看编译过程:

插值

javascript
const compiler = require('vue-template-compiler')

const template = `<p>{{message}}</p>`

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

// with(this){return _c('p',[_v(_s(message))])}

// 相当于执行这个函数,例如下面:
// function(){with(this){return _c('p',[_v(_s(message))])}}
// with(this){return createElement('p',[createTextVNode(toString(message))])}
// h -> vnode
// createElement -> vnode
// const vm = new Vue({...})
// this -> vm

表达式

javascript
const compiler = require('vue-template-compiler')

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

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

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

属性和动态属性

javascript
const compiler = require('vue-template-compiler')

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

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

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

条件

javascript
const compiler = require('vue-template-compiler')

const template = `
  <div>
    <p v-if="flag === 'a'">A</p>
    <p v-else>B</p>
  </div>
`

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

// with(this){return _c('div',[(flag === 'a')?_c('p',[_v("A")]):_c('p',[_v("B")])])}

循环

javascript
const compiler = require('vue-template-compiler')

const template = `
  <ul>
    <li v-for="item in list" :key="item.id">{{item.title}}</li>
  </ul>
`

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

// with(this){return _c('ul',_l((list),function(item){return _c('li',{key:item.id},[_v(_s(item.title))])}),0)}

事件

javascript
const compiler = require('vue-template-compiler')

const template = `<button @click="handlerClick">submit</button>`

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

// with(this){return _c('button',{on:{"click":handlerClick}},[_v("submit")])}

v-model

javascript
const compiler = require('vue-template-compiler')

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

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

// 主要看 input 事件
// 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