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

指令的提取

指令的提取过程是在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": [
"\n hello ",
{
"@binding": "a"
},
"\n "
],
"text": "\n hello {{ a }}\n "
}
],
"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("\n hello "+_s(a)+"\n "),_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了。

Vue2.0原理-指令的更多相关文章

  1. vue2.0自定义指令

    前面一片文章说了vue2.0过滤器,其实自定义指令跟过滤器非常相似,单就定义方式而言,其与过滤器完全一致,分为局部指令,和全局指令.不过就是filter改为directive的区别. 过滤器一般用于对 ...

  2. vue2.0 v-model指令

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. vue2.0自定义指令的使用方法

    感觉2.0好坑啊,自定义指令和1.0完全不一样,并且文档写得也不太清晰,下面是我写得一个demo,希望帮助大家更好地理解自定义指令 <!DOCTYPE html> <html lan ...

  4. Vue2.0原理-模板解析

    下面这段代码,vue内部做了什么操作?我去源码里面找找看 new Vue({ el: '#app' }) 入口 vue 的入口文件在 src/core/instance/index.js, 里面一进来 ...

  5. vue2.0 自定义指令详解

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. vue2.0版本指令v-if与v-show的区别

    v-if: 判断是否加载,可以减轻服务器的压力,在需要时加载. v-show:调整css dispaly属性,可以使客户端操作更加流畅. v-if示例: <!DOCTYPE html> & ...

  7. 基于vue2.0原理-自己实现MVVM框架之computed计算属性

    基于上一篇data的双向绑定,这一篇来聊聊computed的实现原理及自己实现计算属性. 一.先聊下Computed的用法 写一个最简单的小demo,展示用户的名字和年龄,代码如下: <body ...

  8. Vue2.0 - 自定义指令 vue-directive

    Vue.directive('指令',function(el,binding,vnode){ el.style='color:'+binding.value;}); el : 指令所绑定的元素,可以用 ...

  9. vue2.0 自定义指令

    Vue指令 Vue的指令以v-开头,作用在HTML元素上,将指令绑定在元素上,给绑定的元素添加一些特殊行为. 例如: <h1 v-if="yes">Yes</h1 ...

随机推荐

  1. Python的网络编程 Socket编程

    Socket是进程间通信的一种方式,与其他进程间通信的一个主要不同是:能实现不同主机间的进程间通信,网络上各种各样的服务大多都是基于Socket来完成通信的,要解决网络上两台主机间的通信问题,首先要唯 ...

  2. 浅析JS中的堆内存与栈内存

    最近跟着组里的大佬面试碰到这么一个问题, Q:说说var.let.const的区别 A:balabalabalabla... Q:const定义的值能改么? A:你逗我?不能吧 不知道各位看官怎么想? ...

  3. 问题:win10防火墙不能自动启动

    问题:win10防火墙不能自动启动 描述:Windows防火墙不能自动启动,每次开机要手动启动,打开service.msc,里面防火墙的启动类型为手动,按钮为灰色,不能更改为自动,怎么办? 解决方法: ...

  4. [Java多线程] LinkedBlockingQueue

    java.util.concurrent包下的新类.LinkedBlockingQueue就是其中之一,是一个阻塞的线程安全的队列,底层采用链表实现. LinkedBlockingQueue Link ...

  5. 4698. [SDOI2008]Sandy的卡片【后缀数组】

    Description Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积 攒卡片兑换超炫的人物模型.每一张卡片都由一些数字进行标记, ...

  6. ASP.NET web api 跨域请求

    1.学习文章:AJAX 跨域请求 - JSONP获取JSON数据 1.asp.net代码 参考文章:http://www.sxt.cn/info-2790-u-756.html (1).增加CorsH ...

  7. 利用Zookeeper实现分布式锁及服务注册中心

    对于Zookeeper的定义以及原理,网上已经有很多的优秀文章对其进行了详细的介绍,所以本文不再进行这方面的阐述. 本文主要介绍一些基本的准备工作以及zookeeper.net的使用. 本文源代码gi ...

  8. 论mysql主从复制里面的那些坑

    1.找好配置文件,修改对的配置文件,有的时候会有多个配置文件,要搞清楚加载的哪个配置文件. 2.主库备份钱的操作除了设置 只读状态外,还要设置全局只读=1. 3.mysqldump备份sql很方便,恢 ...

  9. ZOJ 3983 Crusaders Quest(思维题)

    C - Crusaders Quest Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu S ...

  10. MapReduce -- 好友推荐

    MapReduce实现好友推荐: 张三的好友有王五.小红.赵六; 同样王五.小红.赵六的共同好友是张三; 在王五和小红不认识的前提下,可以通过张三互相认识,给王五推荐的好友为小红, 给小红推荐的好友是 ...