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": [
"\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原理-指令的更多相关文章
- vue2.0自定义指令
前面一片文章说了vue2.0过滤器,其实自定义指令跟过滤器非常相似,单就定义方式而言,其与过滤器完全一致,分为局部指令,和全局指令.不过就是filter改为directive的区别. 过滤器一般用于对 ...
- vue2.0 v-model指令
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- vue2.0自定义指令的使用方法
感觉2.0好坑啊,自定义指令和1.0完全不一样,并且文档写得也不太清晰,下面是我写得一个demo,希望帮助大家更好地理解自定义指令 <!DOCTYPE html> <html lan ...
- Vue2.0原理-模板解析
下面这段代码,vue内部做了什么操作?我去源码里面找找看 new Vue({ el: '#app' }) 入口 vue 的入口文件在 src/core/instance/index.js, 里面一进来 ...
- vue2.0 自定义指令详解
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- vue2.0版本指令v-if与v-show的区别
v-if: 判断是否加载,可以减轻服务器的压力,在需要时加载. v-show:调整css dispaly属性,可以使客户端操作更加流畅. v-if示例: <!DOCTYPE html> & ...
- 基于vue2.0原理-自己实现MVVM框架之computed计算属性
基于上一篇data的双向绑定,这一篇来聊聊computed的实现原理及自己实现计算属性. 一.先聊下Computed的用法 写一个最简单的小demo,展示用户的名字和年龄,代码如下: <body ...
- Vue2.0 - 自定义指令 vue-directive
Vue.directive('指令',function(el,binding,vnode){ el.style='color:'+binding.value;}); el : 指令所绑定的元素,可以用 ...
- vue2.0 自定义指令
Vue指令 Vue的指令以v-开头,作用在HTML元素上,将指令绑定在元素上,给绑定的元素添加一些特殊行为. 例如: <h1 v-if="yes">Yes</h1 ...
随机推荐
- 【转】爬虫的一般方法、异步、并发与框架scrapy的效率比较
该文非原创文字,文字转载至 jclian91 链接:https://www.cnblogs.com/jclian91/p/9799697.html Python爬虫的N种姿势 问题的由来 ...
- php 实现hash表
hash表又称散列表,通过把关键字key经过hash函数映射到hash表中某个位置获取记录. 存放记录的数组又称为hash表,映射函数称为hash函数 下面是php中实现hash表的方法 <?p ...
- jQuery实现简易轮播图的效果
(图片素材取自于小米官网) 刚开始接触jQuery的学习,个人觉得如果为了实现多数的动态效果,jQuery的确很简易方便. 下面简易的轮播图效果,还请前辈多多指教~ (努力学习react vue an ...
- SGU---104 DP
题目链接: https://cn.vjudge.net/problem/SGU-104 题目大意: 假设你想以最美观的方式布置花店的橱窗,你有F束花,每束花的品种都不一样,同时,你至少有同样数量的花瓶 ...
- Jupyter Notebook的使用
命令模式 (按键 Esc 开启) Enter : 转入编辑模式 Shift-Enter : 运行本单元,选中下个单元 Ctrl-Enter : 运行本单元 Alt-Enter : 运行本单元,在其下插 ...
- Linux进程地址空间与虚拟内存
http://blog.csdn.net/xu3737284/article/details/12710217 32位机器上linux操作系统中的进程的地址空间大小是4G,其中0-3G是用户空间,3G ...
- Mysql索引详解及优化(key和index区别)
MySQL索引的概念 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针.更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库 ...
- 【洛谷】【动态规划/二维背包】P1855 榨取kkksc03
[题目描述:] ... (宣传luogu2的内容被自动省略) 洛谷的运营组决定,如果...,那么他可以浪费掉kkksc03的一些时间的同时消耗掉kkksc03的一些金钱以满足自己的一个愿望. Kkks ...
- c++——对象的动态建立和释放(new 和delete)
3.8 对象的动态建立和释放 1 new和delete基本语法 1)在软件开发过程中,常常需要动态地分配和撤销内存空间,例如对动态链表中结点的插入与删除.在C语言中是利用库函数malloc和free来 ...
- [NOIp2009] $Hankson$の趣味题
\(23333\)这是最近第二份在时间上吊打\(yjk\)的代码--啊哈哈哈哈哈哈哈 嗯,其实遇到这种单纯的\(gcd \ \ or \ \ lcm\)的题,我们都可以用一种比较简单的方法分析:唯一分 ...