首页 > 其他分享 >手撕Vue-数据驱动界面改变下

手撕Vue-数据驱动界面改变下

时间:2023-10-15 23:11:59浏览次数:36  
标签:Vue 界面 get 对象 观察者 value Dep 驱动 属性

经过上一篇的介绍,已经实现了观察者模式的基本内容,接下来要完成的就是将上一篇的发布订阅模式运用到 Nue 中,实现数据驱动界面改变。

在监听数据变化的章节当中,根据指定的区域和数据去编译渲染界面 这个步骤处,我写了一个注释,这个注释是这样的:第一步:给外界传入的所有数据都添加get/set方法,第二步就是在第一步的基础上,给所有属性都添加观察者对象,当数据发生变化时,发布订阅触发观察者对象的回调函数重新渲染界面。

先处理下 v-model 的情况,找到 CompilerUtil 中的 model 方法,将其修改添加观察者对象代码:

model: function (node, value, vm) {
    // 第二部:在第一次渲染的时候, 就给所有的属性添加观察者
    new Watcher(vm, value, (newValue, oldValue) => {
        node.value = newValue;
    });

    node.value = this.getValue(vm, value);
},

这样就完成了第二步,接下来第三步就是将当前属性的所有观察者对象都放到当前属性的发布订阅对象中管理起来

在创建观察者对象的时候,在构造函数当中,会调用 getOldValue 方法,会调用 CompilerUtil.getValue 方法,这个方法就是用于获取属性值的,在编译模板之前已经给所有属性添加了 get/set 方法,所以在获取属性值的时候,就会触发 get 方法,我们就可以在 get 方法中将当前属性的观察者对象添加到当前属性的发布订阅对象中管理起来。

在 Observer 类中的 defineRecative 方法中添加如下代码:

defineReactive(obj, attr, value) {
    this.observer(value);

    // 第三步:将当前属性的所有观察者对象都放到当前属性的发布订阅对象中管理起来
    // 创建属于当前属性的发布订阅对象
    let dep = new Dep();

    Object.defineProperty(obj, attr, {
        get() {
            Dep.target && dep.addSub(Dep.target);
            return value;
        },
        set: (newValue) => {
            if (value !== newValue) {
                this.observer(newValue);
                value = newValue;
                dep.notify();
                console.log('监听到数据的变化, 需要去更新UI');
            }
        }
    })
}

在上述代码中,创建了一个属于当前属性的发布订阅对象,然后在 get 方法中,判断 Dep.target 是否存在,如果存在,就将当前属性的观察者对象添加到当前属性的发布订阅对象中管理起来。Dep.target 就是当前属性的观察者对象,这里该需要在改造一下观察者的类,将观察者对象添加到 Dep.target 中,放在全局中管理起来。等到所有的属性都添加完观察者对象之后,就将 Dep.target 置为 null。

改造观察者类中的 getOldValue 方法, 这样在 get 方法中就可以将当前属性的观察者对象添加到当前属性的发布订阅对象中管理起来了:

getOldValue() {
    Dep.target = this;
    let oldValue = CompilerUtil.getValue(this.vm, this.attr);
    Dep.target = null;
    return oldValue;
}

这样就完成了数据驱动界面改变的功能,接下来我们就来测试一下,打开浏览器控制台,更改下数据,看看是否会触发界面的重新渲染,如下图所示:

image-20231015225532652

好了到此为止,我们已经完成了 v-model 数据驱动界面改变的功能。

下面我将以 debugger 的形式来讲解一下整个数据驱动界面改变的过程, 在 defineReactive get 方法中打上断点,如下图所示:

image-20231015225930152

返回浏览器,主要关注调用栈,如下图所示:

image-20231015230019559

自己从下依次往上看,就可以看到整个数据驱动界面改变的过程了,这里我就不一一截图了,大家可以自己去看一下。

image-20231015230130758

如上是 get 方法代码的执行流程,那么 set 的我也可以说明一下,set 方法的 debugger 不是打在 defineReactive 中,而是打在 Watcher 类中的 update 方法中,所执行的回调函数当中,如下图所示:

image-20231015230405011

返回浏览器,打开控制台更改数据触发 set 方法,发布订阅触发 update 方法:

image-20231015230617621

这次也是主要关注调用栈,自己从下依次往上看,就可以看到整个数据驱动界面改变的过程了,这里我就不一一截图了,大家可以自己去看一下,如下图所示:

image-20231015230547888

标签:Vue,界面,get,对象,观察者,value,Dep,驱动,属性
From: https://www.cnblogs.com/BNTang/p/17766432.html

相关文章

  • Vue源码学习(十一):计算属性computed初步学习
    好家伙,  1.Computed实现原理if(opts.computed){initComputed(vm,opts.computed);}functioninitComputed(vm,computed){//存放计算属性的watcherconstwatchers=vm._computedWatchers={};for(constkeyincomputed){constuser......
  • UE4 C++关联蓝图界面(仅显示)
    使用的自带第三人称c++模板,UE4.27实现教程参考:UE5虚幻引擎C++【第六期】实现UMG控件_哔哩哔哩_bilibili1.创建一个蓝图界面控件,设置好布局2.找到项目代码xx(项目名称).build.cs文件1)添加UMG及后续部分,使得可以调用蓝图模块相关内容PublicDependencyModuleNames.AddRange(news......
  • 开源项目 | 一款基于NodeJs+Vue3的强大的在线设计图片工具
     一、项目概述一款漂亮且功能强大的在线海报图片设计器,仿稿定设计。适用于海报图片生成、电商分享图、文章长图、视频/公众号封面等多种场景。二、技术特性丝滑的操作体验,丰富的交互细节,基础功能完善采用服务端生成图片,确保多端出图统一性,支持各种CSS特性简易AI......
  • vue3中setup
    和vue2不同的是vue3中的script中带有setup标签里面的setup相当于vue2中的data和methds空间可以放置函数,也可以执行函数在写时需要有return返回值<scriptsetup></script>setup执行发生在页面之前所以不能使用this函数,一般通过ref绑定组件上的值进行修改 使用函数例子......
  • 手撕Vue-数据驱动界面改变上
    经过上一篇的介绍,已经实现了监听数据的变化,接下来就是要实现数据变化后,界面也跟着变化,这就是数据驱动界面改变。想要实现数据变化之后更新UI界面,我们可以使用发布订阅模式来实现,先定义一个观察者类,再定义一个发布订阅类,然后再通过发布订阅的类来管理观察者类。接下来我们就......
  • 金蝶云星空调用《其他入库单》的新增界面给序列号子单据体数据赋值
     金蝶云星空调用《其他入库单》的新增界面给序列号子单据体数据赋值 金蝶云星空平台,业务对象的实体层级关系,表头,表头下可以有多个单据体,各单据体之间无关联,单据体下可以有子单单据体。另外各个实体都可以设置拆分表。比如,《其他入库单》表头有客户、日期、单据编号等,有拆分表......
  • 车辆车型识别系统python+TensorFlow+Django网页界面+算法模型
    一、介绍车辆车型识别系统。本系统使用Python作为主要开发编程语言,通过TensorFlow搭建算法模型网络对收集到的多种车辆车型图片数据集进行训练,最后得到一个识别精度较高的模型文件。并基于该模型搭建Django框架的WEB网页端可视化操作界面。实现用户上传一张车辆车型图片识别其名称......
  • 车辆车型识别系统python+TensorFlow+Django网页界面+算法模型
    一、介绍车辆车型识别系统。本系统使用Python作为主要开发编程语言,通过TensorFlow搭建算法模型网络对收集到的多种车辆车型图片数据集进行训练,最后得到一个识别精度较高的模型文件。并基于该模型搭建Django框架的WEB网页端可视化操作界面。实现用户上传一张车辆车型图片识别其名......
  • 手撕Vue-监听数据变化
    经过上一篇的介绍,已经实现了将模板编译成具体数据,接下来要介绍的是如何监听数据的变化,本章主要完成这个需求即可。在我们文章的开始,我写了一个Vue双向数据绑定原理的文章当中封装了一个Observer类,这个类的作用就是监听数据的变化,当数据发生变化的时候,会通知订阅者,订阅者会去......
  • 【gdb】进入和退出图形化调试界面
    进入和退出图形化调试界面1.例子#include<stdio.h>voidfun1(void){inti=0;i++;i=i*2;printf("%d\n",i);}voidfun2(void){intj=0;fun1();j++;j=j*2;print......