手撕Vue-数据驱动界面改变下
经过上一篇的介绍,数据驱动界面改变 v-model 的双向绑定已告一段落, 剩余的就以这篇文章来完成。
首先完成我们的 v-html,v-text, 其实很简单,就是将我们之前的 v-model 创建观察者的方法,在 v-html 和 v-text 中再写一次即可,创建属于 v-html 和 v-text 的观察者。
v-html:
html: function (node, value, vm) {
new Watcher(vm, value, (newValue, oldValue) => {
node.innerHTML = newValue;
});
node.innerHTML = this.getValue(vm, value);
},
v-text:
text: function (node, value, vm) {
new Watcher(vm, value, (newValue, oldValue) => {
node.innerText = newValue;
});
node.innerText = this.getValue(vm, value);
},
测试一下 v-html,打开浏览器控制台,输入 vue.$data.html = '<p>我是测试v-html<p/>',可以看到界面上的内容已经改变了。

测试一下 v-text,打开浏览器控制台,输入 vue.$data.text = '<p>我是测试v-text<p/>',可以看到界面上的内容已经改变了。

好了到此为止,指令的数据驱动界面改变已经完成了,接下来我们来完成模板语法的数据驱动界面改变。
这个就与之前的指令的数据驱动界面改变不同了,好了先不说问题,我们先直接来看代码一步一步分析。
我看了下之前处理 content 的代码发现,获取不到对应的属性名称叫什么,因为是直接调用 this.getContent(vm, value); 获取的,所以会出现一个问题就是给 content 创建观察者对象的时候不能直接告诉他我要监听的是哪个属性,所以我就想到了一个办法。
首先将之前的代码注释掉,再然后我编写一个正则表达式,关于这个正则表达式在之前的文章中有讲到,大概意思就是匹配 {{}} 中的内容,这里就不再赘述了。
let reg = /\{\{(.+?)\}\}/gi;
继续往下看,我利用 value 调用了 replace 方法,传递了两个参数,第一个参数是刚刚编写的正则表达式,第二个参数是一个函数,这个函数的作用就是将匹配到的内容替换成对应的值,我先将其返回值打印出来,看看是什么,我们的代码就可以写成这样。
content: function (node, value, vm) {
// console.log(value); // {{ name }} -> name -> $data[name]
// node.textContent = this.getContent(vm, value);
let reg = /\{\{(.+?)\}\}/gi;
value.replace(reg, (...args) => {
console.log(args[1].trim());
});
}

是的,我们的确获取到了对应的属性名称,接下来我们就可以利用这个属性名称来创建观察者对象了,我们的代码就可以写成这样。
content: function (node, value, vm) {
// console.log(value); // {{ name }} -> name -> $data[name]
// node.textContent = this.getContent(vm, value);
let reg = /\{\{(.+?)\}\}/gi;
node.textContent = value.replace(reg, (...args) => {
const attr = args[1].trim();
new Watcher(vm, attr, (newValue, oldValue) => {
node.textContent = this.getContent(vm, value);
});
return this.getValue(vm, args[1]);
});
}
好了,我们来测试一下,打开浏览器控制台,输入 vue.$data.name = '我是测试 {{ name }}',可以看到界面上的内容已经改变了。

一切看起来都很完美,最终版代码其实是我没有将坑点说出来,现在我们来看看这个坑点是什么,再看之前,我来讲述一下为什么是又调用了 this.getContent 方法而不是直接将 newValue 赋值给 node.textContent。
假如我们的数据结构是这样的 {{ name }} - {{ age }} 如果是通过直接将 newValue 赋值给 node.textContent 的话,这个时候呢,我假设 name 的值是 BNTang, age 的值是 33,那么界面上第一次加载的内容会是 BNTang - 33,但是如果我将 name 的值改成了 xhh,那么界面上的内容就会变成 xhh,这个时候 age 的值就丢掉了,如下图是我的测试结果。

原因就是直接替换掉了,所以在动态更改 name 属性或者 age 属性其中一个的情况下,还需要将 {{ name }} - {{ age }} 这样的内容替换成 BNTang - 33,这样的话,我们就需要调用 this.getContent 方法,这个方法就会利用正则挨个匹配 {{}} 中的内容,然后再将其替换成对应的值,这样就不会出现上面的问题了。
?> 最后总结一下 content 函数的 value.replace 在外层是为了拿到属性名称,内层是为了保证数据完整性。
手撕Vue-数据驱动界面改变下的更多相关文章
- 手撕公司SSO登陆原理
Single Sign-on SSO是老生常谈的话题了,但部分同学对SSO可能掌握的也是云里雾里,一知半解.本次手撕公司的SSO登陆原理,试图以一种简单,流畅的形式为你提供 有用的SSO登陆原理. 按 ...
- Netty实现高性能IOT服务器(Groza)之手撕MQTT协议篇上
前言 诞生及优势 MQTT由Andy Stanford-Clark(IBM)和Arlen Nipper(Eurotech,现为Cirrus Link)于1999年开发,用于监测穿越沙漠的石油管道.目标 ...
- 模拟源码深入理解Vue数据驱动原理(1)
Vue有一核心就是数据驱动(Data Driven),允许我们采用简洁的模板语法来声明式的将数据渲染进DOM,且数据与DOM是绑定在一起的,这样当我们改变Vue实例的数据时,对应的DOM元素也就会改变 ...
- NN入门,手把手教你用Numpy手撕NN(一)
前言 这是一篇包含极少数学推导的NN入门文章 大概从今年4月份起就想着学一学NN,但是无奈平时时间不多,而且空闲时间都拿去做比赛或是看动漫去了,所以一拖再拖,直到这8月份才正式开始NN的学习. 这篇文 ...
- 理解vue数据驱动
vue是双向数据绑定的框架,数据驱动是他的灵魂,他的实现原理众所周知是Object.defineProperty方法实现的get.set重写,但是这样说太牵强外门了.本文将宏观介绍他的实现 使用vue ...
- 编译原理--05 用C++手撕PL/0
前言 目录 01 文法和语言.词法分析复习 02 自顶向下.自底向上的LR分析复习 03 语法制导翻译和中间代码生成复习 04 符号表.运行时存储组织和代码优化复习 05 用C++手撕PL/0 在之前 ...
- 优雅手撕bind函数(面试官常问)
优雅手撕bind函数 前言: 为什么面试官总爱让实现一个bind函数? 他想从bind中知道些什么? 一个小小的bind里面内有玄机? 今天来刨析一下实现一个bind要懂多少相关知识点,也方便我们将零 ...
- (面试题)面试官为啥总是让我们手撕call、apply、bind?
引言 上一篇关于<面试官为啥总是喜欢问前端路由实现方式>的文章发布后,发现还是挺受欢迎的.这就给我造成了一定的困惑 之前花了很长时间,实现了一个自认为创意还不错的关于前端如何利用node+ ...
- NN入门,手把手教你用Numpy手撕NN(2)
这是一篇包含较少数学推导的NN入门文章 上篇文章中简单介绍了如何手撕一个NN,但其中仍有可以改进的地方,将在这篇文章中进行完善. 误差反向传播 之前的NN计算梯度是利用数值微分法,虽容易实现,但是计算 ...
- NN入门,手把手教你用Numpy手撕NN(三)
NN入门,手把手教你用Numpy手撕NN(3) 这是一篇包含极少数学的CNN入门文章 上篇文章中简单介绍了NN的反向传播,并利用反向传播实现了一个简单的NN,在这篇文章中将介绍一下CNN. CNN C ...
随机推荐
- PostgreSQL 12 文档: 部分 VI. 参考
部分 VI. 参考 这份参考中的条目意欲提供关于相应主题的权威.完整和正式的总结.关于使用PostgreSQL的更多信息(以叙述.教程或例子的形式)可以在本书的其他部分找到.见每个参考页面上列出的交叉 ...
- BLOB-CLOB 处理成String (*)
实体类中的写法: --实体类对应的类型为byte[] (clob为char[]). /* byte[] blob = commonService.getPersonImage(bean.getIdCa ...
- 基于百度AI平台的人脸识别评分小程序
face-recognition-scoring-applet 开放源代码,遵循Apache License 2.0 效果展示 可切换摄像头.拍照.从相册选择 效果预览 小程序账号注册及配置 地址:h ...
- Flutter ncnn 使用
Flutter 实现手机端 App,如果想利用 AI 模型添加新颖的功能,那么 ncnn 就是一种可考虑的手机端推理模型的框架. 本文即是 Flutter 上使用 ncnn 做模型推理的实践分享.有如 ...
- PlayWright(二十一)- Pytest插件报告
1.下载 pytest框架有官方的报告pip install pytest-html 下载成功,那我们怎么使用呢? 2.使用 可以直接在配置文件里使用 在 pytest 配置文件中, 增加 ...
- nf_conntrack: table full, dropping packet
参考:linux 路由跟踪表满错误 nf_conntrack: table full, dropping packet 原理解决方法 说明 ping,dmesg 或者 /var/log/message ...
- VueX报错:Cannot read property 'commit' of undefined
原因 main.js文件中没有引入store 解决方案 添加如下代码即可 import store from "./store"; new Vue({ el: '#app', ro ...
- 王道oj/problem21
网址:oj.lgwenda.problem/21 思路:先序遍历,中序遍历,后序遍历用递归实现:层序遍历用一个链队实现,出队一个元素,顺序入队他的左孩子和右孩子 代码: #define _CRT_SE ...
- Notepad正则表达式用法
https://blog.csdn.net/cuckoo1/article/details/52165449
- protoc-gen-doc 自定义模板规则详解
protoc-gen-doc 自定义模板规则详解 配套演示工程 此项目中所用 proto 文件位于 ./proto 目录下,来源于 官方proto示例 此项目中所列所有模板case文件位于 ./tmp ...