Vue 模板编译(笔记自用)

目录

1.JS 的 width 语法

2.模板编译成 js 代码(使用with)

3.编译模板总结

4.补充:Vue组件中使用 render 代替 templete

5.总结


1.JS 的 width 语法

  • 改变 { } 内自由变量的查找规则,当做 obj 属性来查找
  • 如果找不到匹配的 obj 属性,就会报错
  • with 要慎用,它打破了作用域规则,易读性变差
const obj = {a: 100, b: 200}
console.log(obj.a) // 100
console.log(obj.b) // 200
console.log(obj.c) // undefined

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

2.模板编译成 js 代码(使用with)

// 从 vue 源码中找到缩写函数的含义
function installRenderHelpers (target) {
    target._o = markOnce;
    target._n = toNumber;
    target._s = toString;
    target._l = renderList;
    target._t = renderSlot;
    target._q = looseEqual;
    target._i = looseIndexOf;
    target._m = renderStatic;
    target._f = resolveFilter;
    target._k = checkKeyCodes;
    target._b = bindObjectProps;
    target._v = createTextVNode;
    target._e = createEmptyVNode;
    target._u = resolveScopedSlots;
    target._g = bindObjectListeners;
    target._d = bindDynamicKeys;
    target._p = prependModifier;
}

_c = createTextVNode
// 1.插值
const template = `<p>{{message}}</p>`
// 编译后
with(this){
  return createElement('p',[createTextVNode(toString(message))])
}

// 2.表达式
const template = `<p>{{flag ? message : 'no message found'}}</p>`
// 编译后
with(this){
  return _c('p',[_v(_s(flag ? message : 'no message found'))])
}

// 3.属性和动态属性
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}})
     ]
  )
}

// 4.条件
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")])])
}

// 5.循环
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)
}

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

// 7.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 函数
// 返回 vnode
// patch

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

3.编译模板总结

  • 模板编译为 render 函数,执行 render 函数返回 vnode
  • 基于 vnode 再执行 patch 和 diff
  • 使用 webpack vue-loader,会在开发环境下编译模板,打包后显示编译后的js代码

4.补充:Vue组件中使用 render 代替 templete

Vue.component('heading', {
  // templete: '<h1><a name="headerId" href="#headerId">this is a tag</a></h1>'
  render: function (createElement) {
    return createElement(
      'h' + this.level,
      [
        createElement('a',{
          attrs: {
            name: 'headerId',
            href: '#' + 'headerId'
          }
        }, 'this is a tag')
      ]
    )
  }
})

5.总结

  • width 语法
  • 模板到 render 函数,再到 vnode,再到渲染和更新
  • vue 组件可以用 render 代替 template
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值