zoukankan      html  css  js  c++  java
  • Vue2.0原理-指令

    指令是 模板解析 的续章,本文会尝试从源码的角度来理解 指令 是如何被提取和应用的。

    指令的提取

    指令的提取过程是在parse阶段进行的,在 parseHTML 方法中,会解析字符串模板为如下的单个ast对象

      <div class="app">
        hello {{ a }}
        <span v-for='i in 5'>{{i}}</span>
      </div>
      
    被解析为如下文本
    
    {
      "type": 1,
      "tag": "div",
      "attrsList": [
        {
          "name": "class",
          "value": "app"
        }
      ],
      "attrsMap": {
        "class": "app"
      },
      "children": []
    }
    
    其中的 <span v-for='i in 5'>{{i}}</span> 被解析为如下文本
    
    {
      "type": 1,
      "tag": "span",
      "attrsList": [
        {
          "name": "v-for",
          "value": "i in 5"
        }
      ],
      "attrsMap": {
        "v-for": "i in 5"
      },
      "parent": {
        "type": 1,
        "tag": "div",
        "attrsList": [],
        "attrsMap": {
          "class": "app"
        },
        "children": [
          {
            "type": 2,
            "expression": ""\n    hello "+_s(a)+"\n    "",
            "tokens": [
              "
        hello ",
              {
                "@binding": "a"
              },
              "
        "
            ],
            "text": "
        hello {{ a }}
        "
          }
        ],
        "plain": false,
        "staticClass": ""app""
      },
      "children": []
    }
    

    通过提取为格式化的对象,就可以对单个的节点进行解析了

    指令的解析

    首先对 v-for , v-if , v-once 三个指令进行解析

    // processFor 调用 parseFor,
    // 通过 /([^]*?)s+(?:in|of)s+([^]*)/ 正则表达式match后,
    // 将 v-for='i in 5' 解析为 {for: "5", alias: "i"} 对象
    // 再把 {for: "5", alias: "i"} 与 element 对象合并
    processFor(element)
    
    processIf(element) // 同上 
    
    processOnce(element) // 同上 
    
    // processElement 是一个比较大的方法,
    // 里面对 key ref slot component attrs进行了提取和解析
    // 其中的 processAttrs 方法,会提取attrs里面的 v-bind(:) v-on(@)
    // 构造成props, attrsMap, events, directives等对象
    // 然后与 element 对象合并
    // 值得一提的是 v-model 会被当做props,然后再次进入directives中处理
    processElement(element) 
    

    指令的处理

    通过上面的步骤,Vue 提取出了 props, events, attrsMap , for 等指令对象,那么 Vue 又是如何去处理这些指令的呢? codegen/index.js 中有这样一些代码:

      ...
      if (el.key) {
        data += `key:${el.key},`
      }
      // ref
      if (el.ref) {
        data += `ref:${el.ref},`
      }
      ...
      if (el.attrs) {
        data += `attrs:{${genProps(el.attrs)}},`
      }
      if (el.props) {
        data += `domProps:{${genProps(el.props)}},`
      }
      if (el.events) {
        data += `${genHandlers(el.events, false, state.warn)},`
      }
      ...
    

    上面这些代码会对每个属性进行处理,然后拼接为字符串

     比如这段代码
     <div class="app">
       hello {{ a }}
       <span v-for='i in 5' @click='a'>{{i}}</span>
       <input type="text"  v-model='a'>
     </div>
     
     会被处理为
     _c('div',{staticClass:"app"},[_v("
        hello "+_s(a)+"
        "),_l((5),function(i){return _c('span',{on:{"click":a}},[_v(_s(i))])}),_v(" "),_c('input',{directives:[{name:"model",rawName:"v-model",value:(a),expression:"a"}],attrs:{"type":"text"},domProps:{"value":(a)},on:{"input":function($event){if($event.target.composing)return;a=$event.target.value}}})],2)
     
     这段代码在 to-function.js 中,会被 createFunction 处理为一个匿名函数
    

    剩下的事情,就交给 vm.$createElement 去生成vNode了。

  • 相关阅读:
    MySQL批量UPDATE多行记录
    qt 标准对话框
    qt creator 源代码中含有中文编译报错
    qt编译mysql插件
    win7自动登录桌面
    编译QtAV工程库
    Qt Creator 中关于调试器的设置
    QtCreator 添加第三方头文件库文件路径
    Qt 安装一个Service
    Qt 添加启动项
  • 原文地址:https://www.cnblogs.com/small-coder/p/9188448.html
Copyright © 2011-2022 走看看