手撕Vue-编译指令数据
经过上一篇的分析,完成了查找指令和模板的功能,接下来就是编译指令的数据了。
所以本章节主要处理的方法则是 buildElement 方法,我们先分析一下我们所拿到的数据在进行编码,这样会更加清晰一些。
我将 name, value 打印出来,分别对应的值是 name: v-model, value: name,在今后我们的命令中可不止只有 v-model,还有 v-text、v-html、v-on 等等,所以我们需要对这些指令进行分类,然后再进行编译。
所以我这里特意定义了一个工具类叫 CompilerUtil,用来处理指令的分类,代码如下:
let CompilerUtil = {
/**
* 处理 v-model 指令
* @param node 当前元素
* @param value 指令的值
* @param vm Nue 的实例对象
*/
model: function (node, value, vm) {
},
html: function (node, value, vm) {
},
text: function (node, value, vm) {
}
}
然后我们在 buildElement 方法中调用这个方法,代码如下:
// 解构 name
let [, directive] = name.split('-');
// v-model -> [v, model]
// 2.根据指令名称, 调用不同的处理函数
CompilerUtil[directive](node, value, this.vm);
这样我们就可以根据指令的名称,调用不同的处理函数了。
接下来我们就来处理 v-model 指令,代码如下:
/**
* 处理 model 指令
* @param node 当前元素
* @param value 指令的值
* @param vm Nue 的实例对象
*/
model: function (node, value, vm) {
node.value = vm.$data[value];
},
这样我们就可以将数据渲染到页面上了,打开浏览器,可以看到效果如下:
v-model 指令已经可以正常使用了,但是还有问题,就是我们的数据结构目前是比较简单的,那么如果我们的数据是一个对象呢,例如:
time: {
h: 10,
m: 10,
s: 10
}
在用 input 绑定 v-model 进行渲染发现,只有第一个 input 能够正常渲染,其他的 input 都是 undefined,这是为什么呢?
<input type="text" v-model="time.h">
<input type="text" v-model="time.m">
<input type="text" v-model="time.s">
那么这里就要去看一下我们 model 方法的实现了,如果是 time.h,value 等于的值为 time.h, 然后我们在执行 vm.$data[value]
就变为了 vm.$data[time.h]
, 正常的获取这种数据结构的方式应该是先 vm.$data[time]
拿到 time 对象,然后再 time[h]
拿到 h 的值,所以我们需要对这种数据结构进行处理,为了已维护,我这里单独抽离了一个方法出来进行处理获取 value,方法名字叫做 getValue,代码如下:
getValue(vm, value) {
// time.h --> [time, h]
return value.split('.').reduce((data, currentKey) => {
// 第一次执行: data=$data, currentKey=time
// 第二次执行: data=time, currentKey=h
return data[currentKey];
}, vm.$data);
},
reduce
方法被用于迭代这个字符串数组。它接受一个回调函数,这个回调函数在每次迭代中被调用。在这个回调函数中,data 是上一次迭代的结果,而 currentKey 是当前迭代的数组元素(键路径中的一个部分)在每次迭代中,回调函数通过 data[currentKey]
的方式访问嵌套对象的属性,然后将这个属性的值作为下一次迭代的 data, 最终,reduce 方法将遍历整个键路径,直到达到最深层的属性,然后返回该属性的值。这样我们就可以正常的获取到数据了,最后在改造一下之前 model 方法获取值的地方,调用下刚刚编写的 getValue 方法即可:
model: function (node, value, vm) {
node.value = this.getValue(vm, value);
},
再次打开浏览器,可以看到效果如下:
这个搞定之后,我们紧接着把 v-html 和 v-text 也搞定,代码基本上都是一样的,只是渲染的方式不一样,代码如下:
/**
* 处理 html 指令
* @param node 当前元素
* @param value 指令的值
* @param vm Nue 的实例对象
*/
html: function (node, value, vm) {
node.innerHTML = this.getValue(vm, value);
},
/**
* 处理 text 指令
* @param node 当前元素
* @param value 指令的值
* @param vm Nue 的实例对象
*/
text: function (node, value, vm) {
node.innerText = this.getValue(vm, value);
}
编写测试代码:
html: `<div>我是div</div>`,
text: `<div>我是div</div>`
编写HTML代码:
<div v-html="html">abc</div>
<div v-text="text">123</div>
打开浏览器,可以看到效果如下:
手撕Vue-编译指令数据的更多相关文章
- Vue自定义指令 数据传递
在项目开发过程中,难免会遇到各种功能需要使用Vue自定义指令--directive 去实现 .关于directive的使用方式这里就不做过多的介绍了,Vue官方文档中说的还是听明白的.今天讲讲在使用V ...
- 手写vue双向绑定数据
来一张原理图: 实现思路: (1)绑定data 种的数据,为每个数据添加指令.通过Object,defineProperty() 来通知属性是否更改 (2) 找到每个DOM节点的指令.绑定事件.并绑定 ...
- 编译原理--05 用C++手撕PL/0
前言 目录 01 文法和语言.词法分析复习 02 自顶向下.自底向上的LR分析复习 03 语法制导翻译和中间代码生成复习 04 符号表.运行时存储组织和代码优化复习 05 用C++手撕PL/0 在之前 ...
- MySQL通过bin log日志恢复数据|手撕MySQL|对线面试官
关注微信公众号[程序员白泽],进入白泽的知识分享星球 前言 作为<手撕MySQL>系列的第二篇文章,今天介绍一下MySQL的二进制日志(bin log),注意不要和MySQL的InnoDB ...
- 剖析手写Vue,你也可以手写一个MVVM框架
剖析手写Vue,你也可以手写一个MVVM框架# 邮箱:563995050@qq.com github: https://github.com/xiaoqiuxiong 作者:肖秋雄(eddy) 温馨提 ...
- 用C/C++手撕CPlus语言的集成开发环境(1)—— 语言规范 + 词法分析器
序言 之所以叫做CPlus语言,是因为原本是想起名为CMinus的,结果发现GitHub和Gitee上一堆的CMinus的编译器(想必都是开过编译原理课程并且写了个玩具级的语言编译器的大佬们吧).但是 ...
- 手写 Vue 系列 之 Vue1.x
前言 前面我们用 12 篇文章详细讲解了 Vue2 的框架源码.接下来我们就开始手写 Vue 系列,写一个自己的 Vue 框架,用最简单的代码实现 Vue 的核心功能,进一步理解 Vue 核心原理. ...
- Vue之九数据劫持实现MVVM的数据双向绑定
vue是通过数据劫持的方式来做数据绑定的,其中最核心的方法便是通过Object.defineProperty()来实现对属性的劫持,达到监听数据变动的目的. 如果不熟悉defineProperty,猛 ...
- vue的指令
我之前学了学angular 发现angular和vue的指令有点类似 先说一下 new Vue({ el: "#box", // element(元素) 当前作 ...
- 第3章-Vue.js 指令扩展 和 todoList练习
一.学习目标 了解Vue.js指令的实现原理 理解v-model指令的高级用法 能够使用Vue.js 指令完成 todoList 练习(重点+难点) 二.todoList练习效果展示 2.1.效果图展 ...
随机推荐
- 图扑 AR 技术应用与管理:施工建造、机柜扫描、办公室导航解决方案
随着科技的不断革新和创新,越来越多的行业开始迎来数字化时代的变革.建筑行业作为人类历史上最重要的产业之一,在数字化转型方面同样也在不断推进.图扑软件结合 AR 技术的应用,为建筑行业带来了更加便捷高效 ...
- (一)centos7下如何搭建Nginx和FastDFS文件管理-环境搭建
一.关于FastDFS 1.FastDFS简介 FastDFS(Fast Distributed File System)是一个开源的分布式文件系统,旨在解决大规模文件存储和访问的问题,例如图片.音视 ...
- 消灭非稳态噪音的利器 - AI 降噪
摘要:轻量级神经网络降噪方法,解析 ZegoAIDenoise 的算法实现! 文|即构引擎开发团队 一.轻量级神经网络降噪--ZegoAIDenoise 当下,用户在进行音频通话时常常置身于各种不同的 ...
- 说说 Linux 的 curl 命令
cURL,熟悉 Linux 的同学,没有人不知道这个命令吧:) 它有非常非常多的参数,我这里就不复制粘贴了,有需要可以 -h 或者谷歌搜索看看. 我从实用性的角度,说下我比较常用的几个参数: -v:啰 ...
- 青少年CTF平台 Web签到
题目说明 Web一星简单题,Web签到. 直接启动环境,等待30秒左右访问题目链接. 做题过程 进入后,题目好像没有告诉我们什么有用的信息, F12,看遍了题目源码,也没有发现flag,正当我怀疑这个 ...
- 从javascript代码解析过程理解执行上下文与作用域提升
javascript代码解析过程 执行上下文和作用域是javascript中非常重要的部分,要弄清楚它们首先就要说到javascript的运行机制,javascript代码被解析经过了以下几个步骤 P ...
- [linux]搭建nfs
环境 说明 IP 系统版本 服务端 192.168.137.7 centos 7 客户端 192.168.137.8 centos 7 步骤 配置服务端 安装 nfs 服务 yum install - ...
- [golang]推送钉钉机器人消息
前言 通过钉钉群机器人的webhook,实现消息推送. 本文代码仅示例markdown格式的消息. 示例代码 注意修改钉钉机器人的webhook package main import ( " ...
- 【动画进阶】神奇的 3D 磨砂玻璃透视效果
最近,群友分享了一个很有意思的效果: 原效果的网址:frosted-glass.该效果的几个核心点: 毛玻璃磨砂效果 卡片的 3D 旋转跟随效果 整体透明度和磨砂感.以及卡片的 3D 形态会随着用户移 ...
- TensorRT 模型加密杂谈
在大多数项目交付场景中,经常需要对部署模型进行加密.模型加密一方面可以防止泄密,一方面可以便于模型跟踪管理,防止混淆. 由于博主使用的部署模型多为TensorRT格式,这里以TensorRT模型为例, ...