手撕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 ...
随机推荐
- XTTS系列之二:不可忽略的BCT
重要系统Oracle数据库U2L迁移场景中,如果客户来问我建议,我都会回复说首选就是XTTS,除非XTTS经测试实在是无法满足停机窗口,否则就不要考虑OGG这类方案. 换句话说,选择OGG做迁移的场景 ...
- PostgreSQL 12 文档: SQL 语法
SQL 命令 这部分包含PostgreSQL支持的SQL命令的参考信息.每条命令的标准符合和兼容的信息可以在相关的参考页中找到. 目录 ABORT - 中止当前事务 ALTER AGGREGATE ...
- AI重塑千行百业,华为云发布盘古大模型3.0和昇腾AI云服务
[中国,东莞,2023年7月7日]华为开发者大会2023(Cloud)7月7日在中国东莞正式揭开帷幕,并同时在全球10余个国家.中国30多个城市设有分会场,邀请全球开发者共聚一堂,就AI浪潮之下的产业 ...
- Asp-Net-Core学习笔记:gRPC快速入门
前言 此前,我在做跨语言调用时,用的是 Facebook 的 Thrift,挺轻量的,还不错. Thrift是一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言的服务.它被当作一个远程过程调用 ...
- 【阅读笔记】低照度图像增强-《An Integrated Neighborhood Dependent...
本文介绍的是一种比较实用的低照度图像增强算法,选自2004年Tao的一篇论文,名称是<An Integrated Neighborhood Dependent Approach for Nonl ...
- 【MAUI Blazor踩坑日记】2.关于Windows上的相机问题
前言 本系列文章,默认你已经踏上了MAUI Blazor的贼船,并且对MAUI Blazor有了一些了解,知道MAUI是什么,知道Blazor是什么. 不会教你怎么写MAUI Blazor的项目,只是 ...
- 【Oracle】 instr函数与substr函数以及自制分割函数
Oracle instr函数与substr函数以及自制分割函数 instr通常被用来作为判断某个字符串中是否含有执行字符串和将返回结果作为一些数据分割的数据,即有模糊查询like的作用,当返回的查询结 ...
- 2022-1-20 Wpf绑定属性
使用UpdateSourceTrigger绑定属性 后台绑定 通过后台代码绑定 UpdateSourceTrigger
- Go语言中指针详解
指针在 Go 语言中是一个重要的特性,它允许你引用和操作变量的内存地址.下面是指针的主要作用和相关示例代码: 1. 引用传递 在 Go 中,所有的变量传递都是值传递,即复制变量的值.如果你想在一个函数 ...
- Proxmox VE软件防火墙的配置
1 软件防火墙的基本概念 防火墙是计算机网络中用于保护网络安全的关键技术.防火墙可以是硬件设备部署在网络出口,也可以是软件部署在终端设备出口.本文主要介绍软件防火墙. 软件防火墙可以根据网络流量的方向 ...