经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
手撕Vue-数据驱动界面改变下
来源:cnblogs  作者:BNTang  时间:2023/10/20 8:45:12  对本文有异议

经过上一篇的介绍,数据驱动界面改变 v-model 的双向绑定已告一段落, 剩余的就以这篇文章来完成。

首先完成我们的 v-html,v-text, 其实很简单,就是将我们之前的 v-model 创建观察者的方法,在 v-html 和 v-text 中再写一次即可,创建属于 v-html 和 v-text 的观察者。

v-html:

  1. html: function (node, value, vm) {
  2. new Watcher(vm, value, (newValue, oldValue) => {
  3. node.innerHTML = newValue;
  4. });
  5. node.innerHTML = this.getValue(vm, value);
  6. },

v-text:

  1. text: function (node, value, vm) {
  2. new Watcher(vm, value, (newValue, oldValue) => {
  3. node.innerText = newValue;
  4. });
  5. node.innerText = this.getValue(vm, value);
  6. },

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

image-20231019224801735

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

image-20231019224912964

好了到此为止,指令的数据驱动界面改变已经完成了,接下来我们来完成模板语法的数据驱动界面改变。

这个就与之前的指令的数据驱动界面改变不同了,好了先不说问题,我们先直接来看代码一步一步分析。

我看了下之前处理 content 的代码发现,获取不到对应的属性名称叫什么,因为是直接调用 this.getContent(vm, value); 获取的,所以会出现一个问题就是给 content 创建观察者对象的时候不能直接告诉他我要监听的是哪个属性,所以我就想到了一个办法。

首先将之前的代码注释掉,再然后我编写一个正则表达式,关于这个正则表达式在之前的文章中有讲到,大概意思就是匹配 {{}} 中的内容,这里就不再赘述了。

  1. let reg = /\{\{(.+?)\}\}/gi;

继续往下看,我利用 value 调用了 replace 方法,传递了两个参数,第一个参数是刚刚编写的正则表达式,第二个参数是一个函数,这个函数的作用就是将匹配到的内容替换成对应的值,我先将其返回值打印出来,看看是什么,我们的代码就可以写成这样。

  1. content: function (node, value, vm) {
  2. // console.log(value); // {{ name }} -> name -> $data[name]
  3. // node.textContent = this.getContent(vm, value);
  4. let reg = /\{\{(.+?)\}\}/gi;
  5. value.replace(reg, (...args) => {
  6. console.log(args[1].trim());
  7. });
  8. }

image-20231019230456960

是的,我们的确获取到了对应的属性名称,接下来我们就可以利用这个属性名称来创建观察者对象了,我们的代码就可以写成这样。

  1. content: function (node, value, vm) {
  2. // console.log(value); // {{ name }} -> name -> $data[name]
  3. // node.textContent = this.getContent(vm, value);
  4. let reg = /\{\{(.+?)\}\}/gi;
  5. node.textContent = value.replace(reg, (...args) => {
  6. const attr = args[1].trim();
  7. new Watcher(vm, attr, (newValue, oldValue) => {
  8. node.textContent = this.getContent(vm, value);
  9. });
  10. return this.getValue(vm, args[1]);
  11. });
  12. }

好了,我们来测试一下,打开浏览器控制台,输入 vue.$data.name = '我是测试 {{ name }}',可以看到界面上的内容已经改变了。

image-20231019230944283

一切看起来都很完美,最终版代码其实是我没有将坑点说出来,现在我们来看看这个坑点是什么,再看之前,我来讲述一下为什么是又调用了 this.getContent 方法而不是直接将 newValue 赋值给 node.textContent。

假如我们的数据结构是这样的 {{ name }} - {{ age }} 如果是通过直接将 newValue 赋值给 node.textContent 的话,这个时候呢,我假设 name 的值是 BNTang, age 的值是 33,那么界面上第一次加载的内容会是 BNTang - 33,但是如果我将 name 的值改成了 xhh,那么界面上的内容就会变成 xhh,这个时候 age 的值就丢掉了,如下图是我的测试结果。

image-20231019233644556

原因就是直接替换掉了,所以在动态更改 name 属性或者 age 属性其中一个的情况下,还需要将 {{ name }} - {{ age }} 这样的内容替换成 BNTang - 33,这样的话,我们就需要调用 this.getContent 方法,这个方法就会利用正则挨个匹配 {{}} 中的内容,然后再将其替换成对应的值,这样就不会出现上面的问题了。

?> 最后总结一下 content 函数的 value.replace 在外层是为了拿到属性名称,内层是为了保证数据完整性。

原文链接:https://www.cnblogs.com/BNTang/p/17776030.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号