本篇文章,我们简单的介绍几个Vue内置指令的实现。

v-text

v-text的用法很简单,以下两个表达式的作用相同。

<span v-text="msg"></span>
<span>{{msg}}</span>

和所有普通指令一样,在生成ast时,v-text会被解析到el.directives中。

但在生成render函数的过程中,在解析属性时,

我们会首先解析指令。genDirectives方法中有如下一段代码:

const gen: DirectiveFunction = platformDirectives[dir.name] || baseDirectives[dir.name]
if (gen) {
// compile-time directive that manipulates AST.
// returns true if it also needs a runtime counterpart.
needRuntime = !!gen(el, dir, warn)
}
if (needRuntime) {
hasRuntime = true
res += `...`
}

directives概述中我们也提到过,platformDirectivesbaseDirectives会对部分内置指令进行处理。v-text就是其中之一。

最终的gen函数如下所示:

export default function text (el: ASTElement, dir: ASTDirective) {
if (dir.value) {
addProp(el, 'textContent', `_s(${dir.value})`)
}
}

该函数返回的是undefined,所以needRuntime最终是false,所以该结果不会添加到res上。

addProp的定义如下:

export function addProp (el: ASTElement, name: string, value: string) {
(el.props || (el.props = [])).push({ name, value })
}

它会给el.props数组中添加一个对象,对象里保存的namevalue

// DOM props
if (el.props) {
data += `domProps:{${genProps(el.props)}},`
}

最终,会添加到domProps对应的数组中。上面例子中的span,最终生成的render函数如下:

_c('span',{domProps:{"textContent":_s(msg)}})

patch过程中的处理,和其他data中的数据一样,是通过钩子函数处理的。

function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
if (!oldVnode.data.domProps && !vnode.data.domProps) {
return
}
let key, cur
const elm: any = vnode.elm
const oldProps = oldVnode.data.domProps || {}
let props = vnode.data.domProps || {}
// clone observed objects, as the user probably wants to mutate it
if (props.__ob__) {
props = vnode.data.domProps = extend({}, props)
} for (key in oldProps) {
if (props[key] == null) {
elm[key] = ''
}
}
for (key in props) {
cur = props[key]
if (key === 'textContent' || key === 'innerHTML') {
if (vnode.children) vnode.children.length = 0
if (cur === oldProps[key]) continue
} if (key === 'value') {
// store value as _value as well since
// non-string values will be stringified
elm._value = cur
// avoid resetting cursor position when value is the same
const strCur = cur == null ? '' : String(cur)
if (shouldUpdateValue(elm, vnode, strCur)) {
elm.value = strCur
}
} else {
elm[key] = cur
}
}
}

首先会重置oldPropsprops上不存在的属性。然后遍历props中的属性,如果keytextContentinnerHTML,则清除children的内容。

如果key === 'value'这里应该对inputselect等标签的特殊处理。否则,直接设置elm.textContent = cur,以此来改变文本内容。

v-html

v-htmlv-text的用法和处理流程基本完全一样,唯一的区别就是最终v-html设置的elm.innerHTML = cur

用法示例如下:

<span v-html="msg"></span>

v-cloak

这个指令用的比较少,不懂的人看完官方文档的说明可能还是稀里糊涂的。它的ast生成和上面讲的普通指令一样,在genDirectives时,baseDirectives中包含了cloak,但最终返回的gen是一个空函数。最终它也不会添加到directives数组中,之后也就没有了对它的处理。

因为我们的模板再编译的过程中,页面中是会显示Mustache 标签的。该指令就是在模板编译之后,被删除。我们可以添加[v-cloak] { display: none },来防止用户感知到Mustache 标签 出现。

v-pre

v-pre表示该会跳过该标签及其子元素的编译。

在编译模板时的start回调函数中,有如下片段:

if (!inVPre) {
processPre(element)
if (element.pre) {
inVPre = true
}
}
if (inVPre) {
processRawAttrs(element)
} else {
...
}

processPre函数会获取element上的v-pre属性,如果有则设置element.pre = true,同时设置inVPre = true

接下来的处理,会走进processRawAttrs函数。else块内对各种指令、属性等的处理,都不会执行。

function processRawAttrs (el) {
const l = el.attrsList.length
if (l) {
const attrs = el.attrs = new Array(l)
for (let i = 0; i < l; i++) {
attrs[i] = {
name: el.attrsList[i].name,
value: JSON.stringify(el.attrsList[i].value)
}
}
} else if (!el.pre) {
// non root node in pre blocks with no attributes
el.plain = true
}
}

这里是对属性的处理,如果el.attrsList不为空数组,则直接循环el.attrsList上的属性添加到el.attrs上。否则,如果当前元素没有设置v-pre指令(是设置v-pre元素的子元素),则设置el.plain = true

因为我们不编译的是整个子树,而不是单个元素。Vue中就是通过inVPre来标示的,我们parse的整个过程就是入栈出栈,当子元素都编译完,会走到当前元素的end处理,此时再设置inVPre = false,来结束不编译的内容。

v-text、v-html、v-cloak、v-pre.md的更多相关文章

  1. Sublime text代码补全插件(支持Javascript、JQuery、Bootstrap框架)

    Sublime text代码补全插件(支持Javascript.JQuery.Bootstrap框架)   插件名称:javascript-API-Completions 支持Javascript.J ...

  2. CF E. Vasya and a Tree】 dfs+树状数组(给你一棵n个节点的树,每个点有一个权值,初始全为0,m次操作,每次三个数(v, d, x)表示只考虑以v为根的子树,将所有与v点距离小于等于d的点权值全部加上x,求所有操作完毕后,所有节点的值)

    题意: 给你一棵n个节点的树,每个点有一个权值,初始全为0,m次操作,每次三个数(v, d, x)表示只考虑以v为根的子树,将所有与v点距离小于等于d的点权值全部加上x,求所有操作完毕后,所有节点的值 ...

  3. 【工具篇】Sublime Text 2/3 安装汉化破解、插件包安装教程详解

    Sublime Text概述: Sublime Text是一个代码编辑器,也是HTML和散文先进的文本编辑器. 漂亮的用户界面和非凡的功能,例如:迷你地图,多选择,Python插件,代码段等等. 完全 ...

  4. Corporative Network (有n个节点,然后执行I u,v(把u的父节点设为v)和E u(询问u到根节点的距离))并查集

    A very big corporation is developing its corporative network. In the beginning each of the N enterpr ...

  5. 运维ps语法---》ps、pstree、top、htop、nice、renice、kill、ulimit、w 和 who 和 whoami、pgrep、fg 和 bg、ipcs

    Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...

  6. Android 获得本地IP地址、外网IP地址、本设备网络状态信息、本地Mac地址

    本地内网IP和外网IP的区别: 根据我的经验一台电脑需要两个ip才可以上网,一个是本地的内网ip 一个是外网的ip 本地的ip 一般是192.168.1.2这种样子  只要在不同的路由器上可以重复 外 ...

  7. OSPF的特征、术语、包类型、邻居关系的建立、RID的选择、DR和BDR的选举、度量值的计算、默认路由、验证

    链路状态路由协议OSPF的特征.术语.包类型.邻居关系的建立.RID的选择.DR和BDR的选举.度量值的计算.默认路由.验证等. 文章目录 [*1*].链路状态路由协议概述 工作过程 优缺点 [*2* ...

  8. 微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇

    一.独立验证器 我上篇中我将AndCompositeValidator和OrCompositeValidator归为独立验证器,这2个验证器主要是为了第一类验证服务,可以进行多种验证组合在一起进行复杂 ...

  9. Hive 文件格式 & Hive操作(外部表、内部表、区、桶、视图、索引、join用法、内置操作符与函数、复合类型、用户自定义函数UDF、查询优化和权限控制)

    本博文的主要内容如下: Hive文件存储格式 Hive 操作之表操作:创建外.内部表 Hive操作之表操作:表查询 Hive操作之表操作:数据加载 Hive操作之表操作:插入单表.插入多表 Hive语 ...

  10. 鸟哥的linux私房菜 - 第5/6/7/9章(在线求助 man page、Linux档案权限与目录配置、Linux档案与目录管理、压缩与打包)

    第五章.在线求助 man page X window与文本模式的切换 Ctrl+Alt+F1~F6:文字接口登入tty1~tty6终端机: Ctrl+Alt+F7:图形接口桌面. 注销当前用户:exi ...

随机推荐

  1. [Linux] - Linux安装JDK

    https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html  <官方JDK下载 之后 ...

  2. codevs 1082 线段树练习 3 区间更新+延迟标记

    题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下 ...

  3. vue-cli 组件运用

    // components ----- helloworld.vue <script> export default { name: 'Hellowworld', props: { //接 ...

  4. 机器学习 MLIA学习笔记(二)之 KNN算法(一)原理入门实例

    KNN=K-Nearest Neighbour 原理:我们取前K个相似的数据(排序过的)中概率最大的种类,作为预测的种类.通常,K不会大于20. 下边是一个简单的实例,具体的含义在注释中: impor ...

  5. Sublime Text 3.1.1 Build 3176 注册码破解

    在hosts(C:\Windows\System32\drivers\etc)加入如下内容: 127.0.0.1       www.sublimetext.com127.0.0.1       li ...

  6. 《剑指offer》第三十一题(栈的压入、弹出序列)

    // 面试题31:栈的压入.弹出序列 // 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是 // 否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1.2.3.4. / ...

  7. 3-15 《元编程》第6章 3-16 hook method

    Code That Writes Code 6.1 Coding your way to the weekend 6.2 Kernel#eval, Binding#eval Binding: Obje ...

  8. Android之侧滑菜单DrawerLayout的使用

    在android support.v4 中有一个抽屉视图控件DrawerLayout.使用这个控件,可以生成通过在屏幕上水平滑动打开或者关闭菜单,能给用户一个不错的体验效果. DrawerLayout ...

  9. Tree Cutting (Hard Version) CodeForces - 1118F2 (树形DP,计数)

    大意:给定树, 每个点有颜色, 一个合法的边集要满足删除这些边后, 每个连通块内颜色仅有一种, 求所有合法边集的个数 $f[x][0/1]$表示子树$x$中是否还有与$x$连通的颜色 对于每种颜色已经 ...

  10. Oracle性能诊断艺术-相关脚本说明

    第二章 bind_variables.sql     展示怎样绑定变量及何时绑定变量会导致游标共享 bind_variables_peeking.sql  展示绑定变量窥测的优缺点 selectivi ...