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 ...
随机推荐
- 我做SAP CRM One Order redesign的一些心得体会
框架开发和应用程序的开发完全不一样. 举个具体的最近折腾我的例子: 创建新的service order,维护header的shipping data,此时order和shipping data的mod ...
- php 访问控制和重载
一 php 类中定义的private/protected属性,类外部是无法访问的,但是 我们可以通过public方法来访问设置这些属性 如下 <?php class test{ priv ...
- 嵌套的ng-repeat双层循环,内层如何获取外层的$index?
html代码: <div> <ul ng-repeat="row in table track by $index"> <li ng-repeat=& ...
- 3192: [JLOI2013]删除物品
3192: [JLOI2013]删除物品 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1366 Solved: 794 [Submit][Statu ...
- 最易懂的layui分页
该篇文章是在layui前端框架之分页基础上简洁化和详细化. 首先该示例采用的是Spring+MyBatis Plus+SpringMVC(常规的SSM框架),持久层换成MyBatis也行. 至于lay ...
- JavaScript实现计时器
var myVar=setInterval(function(){myTimer()},1000); function myTimer() { var d = new Date(); document ...
- MySQL(四)执行计划
转载自:Oo若离oO,原文链接 在MySQL中使用explain查询SQL的执行计划 目录 一.什么是执行计划 二.如何分析执行计划 一.什么是执行计划 要对执行计划有个比较好的理解,需要先对MySQ ...
- 【原型图】Mockplus
Mockplus 原型设计工具
- CCF认证201712-1最小差值
问题描述 给定n个数,请找出其中相差(差的绝对值)最小的两个数,输出它们的差值的绝对值. 输入格式 输入第一行包含一个整数n. 第二行包含n个正整数,相邻整数之间使用一个空格分隔. 输出格式 输出一个 ...
- Linux中定时删除超过指定大小的文件夹
背景: 开发环境总是动不动就没有空间了, 大部分都是debug日志.所以有必要在日志很疯狂的时候,删除不必要的日志. 思路:一. 书写删除日志文件脚本: 定时任务执行. 但是有时候的日志是需要保存用 ...