MVVM与Vue响应式的实现

news2024/9/22 11:24:58

Vue的响应式实现原理

MVVM

M:模型 ==》data中的数据

V:视图 ==》模板

VM:视图模型 ==》Vue实例对象

在这里插入图片描述

ViewModel是一个中间的桥梁将视图View与模型Model连接起来,ViewModel内部通过数据绑定,实现数据变化,视图发生更新变化,通过数据劫持实现的数据绑定;通过dom监听,实现事件触发,调用对应的回调函数,比如更新数据(数据变化了,视图就会更新–数据绑定)

Vue 的设计也受到了MVVM的启发,View对应的是dom,它的ViewModel对应的式Vue实例,,Model对应的是data对象;通过数据劫持来实现数据绑定;编译(事件指令)的时候添加事件监听

Vue的响应式原理

主要是:数据代理、数据绑定、模板编译

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iKZWJxqy-1670162086242)(C:\Users\lucas\Desktop\学习\图片\reactive.jpg)]

绿线是初始化时执行的,红线是数据更新时触发的

一、初始化的时候:

1》数据代理

数据代理就是通过一个对象代理对另一个对象中属性的操作(读/写);vue中通过vm代理data对象(vm代理vm._data)中所有属性的操作,更方便的操作data中的数据

vue中数据代理:将vue文件中的data保存一份到vm._data; 然后对将vue文件中data中的每个属性添加到vm实例上,通过Object.defineProperty实现数据的代理;当我们读取vm上的属性时,他会到vm._data中找到对应的属性返回当,我们修改vue实例对象的属性后,对应的setter就会监听到变化,然后去修改实例对象上vm._data对应的属性

    Object.defineProperty(me, key, {
      configurable: false, // 不可以重新定义
      enumerable: true, // 可枚举遍历
      // 当执行vm.name获取属性值时自动调用返回属性值
      get: function proxyGetter() {
        // 读取data中对应的属性值返回
        return me._data[key];
      },
      // 当执行vm.name = "xxx"时自动调用
      set: function proxySetter(newVal) {
        // 将最新的值保存给data对应的属性上
        me._data[key] = newVal;
      }
    });

2》数据绑定:

数据绑定

初始化显示:页面(表达式、指令)能从data读取数据希纳是(编译、解析)

更新显示:更新data中的属性数据,能够更新页面

数据劫持

1》数据劫持是vue实现数据绑定的一种技术

2》基本思想:通过defineProperty()来监视data中所有属性(任意层次)数据的变化,一旦变化就更新界面

具体实现:

采用递归的方式为data中的每个层级的属性创建dep(实例对象),并通过defineProperty对data进行重新定义,实现数据劫持;在set中判断数据是否发生了变化,如果发生改变,一方面他会更新值,新的值是需要重新劫持监听;另一方面会通知所有相关订阅者watcher去更新界面;在get中不仅返回值,还需要建立watcher与dep的关系(这个get会在模板解析大括号表达式和指令时触发);给Watcher添加Dep,给watch的subs中push对应dep

dep对象:

{
id;0,
subs:[]
}

dep的id从0开始递增,每个属性对应一个dep,劫持

watcher对象:

{
  vm:MVVM
  exp:"name",
  depIds:{depId:dep}  // depId就是上面dep的id,是个数字
  cb: textUpdater,
  value:"luca"
}

watcher与dep的关系

多对多的关系

一个dep可能对应多个watcher; eg:一个属性在多个标签中使用

一个watcher可能的对应多个dep; eg: {{a.b.c}}

什么时候建立关系:编译、解析模板(大括号表达式和非事件指令)时建立

怎么建立关系:创建watcher时会读取data中的值,defineProperty中get会建立双方关系;在dep的subs中push了watcher,且在watcher的depIds中添加了对应dep

劫持的部分代码:

  defineReactive: function (data, key, val) {
    // 创建对应的dep对象
    var dep = new Dep();
    // 通过隐式递归调用, 实现对所有层次属性的劫持
    var childObj = observe(val);
    // 给data中指定属性进行重新定义
    Object.defineProperty(data, key, {
      enumerable: true, // 可枚举
      configurable: false, // 不能再define
      // 返回属性值, 同建立dep与watcher之间的关系
      get: function () {
        if (Dep.target) {
          dep.depend();
        }
        return val;
      },
      // 监视属性值的变化, 一旦变化去更新对应的界面
      set: function (newVal) {
        if (newVal === val) {
          return;
        }
        val = newVal;
        // 是object的新的值话,进行监听
        childObj = observe(newVal);
        // 通知订阅者
        dep.notify();
      },
   });
  },

3》编译模板

1、将el所有的子节点去除,添加到加到一个新建的文档 fragment 对象中

2、对 fragment中所有层次子节点递归进行编译解析处理

编译大括号表达式和一般指令时创建watcher;创建watcher时指定了更新函数(因为要更新的可能是a.b.c这种,所以要遍历,取值是从_data中取的);这是初始化需要读取_data中的数据,就会走对应属性的get,从而建立dep与watcher的关系,给dep的subs中push了对应的watcher,并且在watcher中的depIds添加了对应的dep

1》对表达式文本进行解析

​ a、根据正则对象匹配的表达式字符串( 匹配eg:{{obj.age}} ):子匹配

​ b、将属性值设置为文本节点的 textContent

​ c、从data中去除表达式对应的属性(通过.来分割成数组后遍历,因为可能由多层 a.b.c)

2》对元素节点的指令属性进行解析

a》 事件指令的解析

​ a.1、从指令中取出事件名

​ a2、根据指令的值从methods中得到对应的事件处理函数对象

​ a3、给当前元素节点绑定事件名和事件回调函数的事件监听

​ a4、指令解析完成后,移除次指令属性

b》一般指令的解析

​ b.1、从表达式中取出指令名和指令值

​ b.2、从data中根据表达式得到对应的值

​ b.3、根据指令名确定需要操作的元素节点的什么属性

​ b.4 、将表达式的值设置到对应的属性上(v-text:textContent;;v-html:innerHtml; v-class :className)

​ b5、移除元素的指令属性

3、将解析后的 fragment 添加到el中显示

fragment修改并不会引起页面的更新

二、数据变化的时候

监听到_data的变化,set首先判断值有没有变化,发生变化而且是个对象的话会重新调用observe函数进行监听;通知所有相关的订阅者更新界面(通过遍历subs,调用watcher中的回调函数函数来更新界面)

双向数据绑定的实现

双向绑定是建立在单项数据绑定的基础上;只是在解析v-model指令时,给当前元素添加了input监听;当input的value发生改变时,修改对应的_data中的属性

v-model 是动态属性绑定 v-bind 与 input事件的语法糖

关的订阅者更新界面(通过遍历subs,调用watcher中的回调函数函数来更新界面)

双向数据绑定的实现

双向绑定是建立在单项数据绑定的基础上;只是在解析v-model指令时,给当前元素添加了input监听;当input的value发生改变时,修改对应的_data中的属性

v-model 是动态属性绑定 v-bind 与 input事件的语法糖

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/61389.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

链接装载(一)虚拟地址与物理地址

文章目录一、基本概念二、一个基本问题三、程序的执行四、从堆中分配的数据的逻辑地址一、基本概念 当我们写出一个程序,即便是最基本的 Hello World,都需要经过 预处理、编译、汇编、链接才能生成最终的可执行文件。 预处理: 预处理过程主…

spring ioc的循环依赖问题

spring ioc的循环依赖问题什么是循环依赖spring中循环依赖的场景通过构造函数注入时的循环依赖通过setter或Autowired注入时的循环依赖循环依赖的处理机制原型bean循环依赖单例bean通过构造函数注入循环依赖单例bean通过setter或者Autowired注入的循环依赖三级缓存对象的创建分…

Metasploit 操作及内网 Pivot图文教程

目录 一、metasploit 简介 二、 基本使用 三、 使用 encoders 四、pivot 技术 一、metasploit 简介 Metasploit 是一款开源的安全漏洞检测工具,集成了丰富的渗透测试工具,深受安 全工作者喜爱。官方网站:www.metasploit.com 本案例将以图…

OS-调度

调度 多个程序在并发的情况下执行,最大化CPU利用率,同时要保证一定的公平性 调度的时机 五种情况: Running -> Waiting:例如等待I/ORunning -> Ready: interupt,计时器到时间了Running -> TerminatedWait…

我把Idea给改了,看看有没有你常用的功能,没有,你告诉我,我来改

改造的目标 时隔2个多月的研发,11月25日,终于把Idea插件BG-BOOM的1.1.0版本搞上线了,本次更新勇哥也是百忙之中挤时间,加班加点开发为粉丝,目的也主要是帮助大家提升开发效率,有更多摸鱼和内卷时间&#x…

[附源码]Python计算机毕业设计SSM晋中学院教室管理系统(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

QT中怎么设置定时器/周期任务/定时触发任务

Qt中定时器的使用有两种方法,一种是使用QObject类提供的定时器,还有一种就是使用QTimer类。 其精确度一般依赖于操作系统和硬件,但一般支持20ms。下面将分别介绍两种方法来使用定时器。 QObject类提供的定时器 QObject中的定时器的使用&am…

Makefile 详解

文章目录1.什么是Makefile2.Makefile文件命名规则3.编写Makefile4.Makefile 的工作原理5.Makefile中的变量6.模式匹配7.函数1.什么是Makefile 一个工程中的源文件不计其数,按期类型、功能、模块分别放在若干个文件中,MakeFile文件定义了一系列的规则来制…

HIN应用调研总结

文章目录1. 代码安全iDev: enhancing social coding security by cross-platform user identification between GitHub and stack overflow【A】2. API推荐Group preference based API recommendation via heterogeneous information network【A】3.Andorid恶意软件检测Out-of-…

SSM甜品店系统计算机毕业论文java毕业设计选题源代码

💖💖更多项目资源,最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 计算机毕业设计java毕设之SSM甜品店系统-IT实战营_哔哩哔哩_bilibili项目资料网址: http://itzygogogo.com软件下载地址:http://itzygogogo.com/i…

中英双语多语言外贸企业网站源码系统 - HanCMS - 安装部署教程

随着跨境独立站的流行,中英双语的公司官网越来越受到重视。 此项目是基于开源CMS开发出的中英文双语外贸企业网站内容管理系统,命名HanCMS HanCMS 汉CMS中英双语多语种外贸网站系统,是一个轻量级的网站系统,访问速度极快&#xff…

[附源码]计算机毕业设计小太阳幼儿园学生管理系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

威伦触摸屏TK6060IP简单例子

详情见以下链接 https://download.csdn.net/download/weixin_39926429/87242438

[附源码]Python计算机毕业设计SSM教务管理系统(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

基于连续小波变换的厄尔尼诺海平面周期变化数据集分析

基于连续小波变换的厄尔尼诺海平面周期变化数据集分析1. 厄尔尼诺海平面周期变化数据集介绍2. 基于连续小波变换的信号分析2.1 原始信号读取可视化2.2 傅里叶变换结果可视化2.3 小波变换结果可视化参考资料后记1. 厄尔尼诺海平面周期变化数据集介绍 这些数据是通过国际热带海洋…

文件上传的multipart/form-data属性,你理解了吗

form表单经常用于前端发送请求,比如:用户填写信息、选择数据、上传文件,对于不同的场景,上传数据的格式也会有些区别。 action action 表示该请求的 url 地址,定义在form上,请求的URI,可以写完…

【Python自然语言处理】文本向量化的六种常见模型讲解(独热编码、词袋模型、词频-逆文档频率模型、N元模型、单词-向量模型、文档-向量模型)

觉得有帮助请点赞关注收藏~~~ 一、文本向量化 文本向量化:将文本信息表示成能够表达文本语义的向量,是用数值向量来表示文本的语义。 词嵌入(Word Embedding):一种将文本中的词转换成数字向量的方法,属于文本向量化处理的范畴。 …

Linux操作系统~基于systemV共享内存的进程间通信

目录 一.进程间通信有哪些方式 二.什么是systemV 三.共享内存-双向通信-大致实现思路 四.4个函数about共享内存 1.shmget函数-创建 ftok函数 ​编辑 e.g. ipcs/ipcrm指令(ipc资源会被回收吗) 2.shmctl函数-删除/释放 3.shmat函数-挂接 4.shmdt…

汽车以太网简史

一、为啥需要新车载总线 在一个行业中,当一种新技术被开发和启用时,影响该技术成功的因素有很多。其中最重要的是该技术带来的益处以及自身成本。 第一个吃螃蟹的 2004年宝马决定从2008年起在其开始量产(SOP)的汽车中引入一个中…

c++ 指针

目录 1.指针的基本概念 2.定义指针,使用指针 3.指针所占的内存空间 4.空指针和野指针 4.1空指针 4.2野指针 5.const修饰指针 5.1常量指针 5.2指针常量 5.3const既修饰指针又修饰常量 6.指针和数组,利用指针访问数组 6.1概述 6.2使用数组名和下表访问 6.3使用…