VUE2双向绑定的原理

文章目录

  • VUE2双向绑定的原理
  • 1. 什么是双向绑定
  • 2. 双向绑定的原理
    • 2.1 ViewModel的重要作用
    • 2.2 双向绑定的流程
  • 3. 双向绑定的实现
    • 3.1 data响应化处理
    • 3.2 Compile编译
    • 3.3 依赖收集

VUE2双向绑定的原理

1. 什么是双向绑定

  • 讲双向绑定先讲单项绑定,啥叫单项绑定,就是一句话就是通过Model去改变View,再直白点,就是通过js代码把数据改变后,html视图也跟着变化
  • 那双项绑定就很好理解了,在单项绑定的基础上,如果view改变了,Model也能同步变化
  • 一句话概括就是,Model变化View跟着跟新,View跟新,Model跟着变化,这就是双向绑定

2. 双向绑定的原理

  • 其实我们可以很容易想到一点就是,如果A变化了想要B跟着变化,最简单的方式就是,A变化的时候通知一下B就行,这就是基本思路
  • 在VUE2 中,双向绑定由三个重要部分构成
  1. 数据层(Model),应用的数据及业务逻辑
  2. 视图层(View),应用的展示效果,理解为UI组件
  3. 业务逻辑层(ViewModel),框架封装的核心,他主要负责把数据层和视图层关联起来,这就是MVVM模型

2.1 ViewModel的重要作用

  • ViewModel主要干两件事
  1. 数据变化后,更新视图
  2. 视图变化后,更新数据
  • 那么问题来了,怎么通知呢,我们怎么知道数据变化后,通知哪些视图呢
  • 这要依赖ViewModel的两个重要部件
  1. 监听器(Observer),对所有数据的属性进行监听
  2. 解析器(Compiler),对元素节点的指令进行扫描跟解析,根据指令模板替换数据,以及绑定相应的更新函数

2.2 双向绑定的流程

  • 双向绑定的流程
  1. 我们在new Vue()时,执行初始化,对data执行相应化处理,这个过程发生在Observer中
  2. 同时对模板执行编译,找到其中动态绑定的数据,从data中获取并初始化视图,这个过程发生在Compiler中
  3. 同时定义一个更新函数和Watcher,将来对应数据变化时,Watcher会调用更新函数
  4. 由于data中的数据的某个key可能出现在视图的多处,所以每个key都需要一个管家Dep来管理多个Watcher
  5. 将来数据一旦发生变化,会首先找到对应的Dep,通过Dep李曼的所有Watcher执行更新函数
    在这里插入图片描述

3. 双向绑定的实现

3.1 data响应化处理

  • 我们来创建一个构造函数,执行初始化,对data数据执行响应化处理
class Vue{constrcutor(options){this.$options=options;this.$data=options.data;//对data选项做响应式处理Observe(this.$data)//代理data到vm上proxy(this)// 执行编译new Compile(options.el,this)}
}
function Observe(obj){if(typeof obj!=='object' || obj===null){return;}new Observer(obj)
}
class Observer{constructor(value){this.value=value;this.walk(value)}walk(obj){Object.keys(obj).forEach((key)=>{defineReactive(obj,key,obj[key])//内部是Object.defineProperty实现,后面会讲})}
}

3.2 Compile编译

  • 对元素节点的指令机型扫描跟解析,根据指令模板替换数据,以及绑定相应的更新函数
class Compile{constructor(el,vm){this.$vm=vm;this.$el=document.querySelector(el);//获取DOMif(this.$el)this.compile(this.#el)}compile(el){const childNodes=el.ChildNodes;Array.from(childNodes).forEach((node)=>{//遍历子元素if(this.isElement(node)){//判断是否为节点/*编译元素*/}else if(this.inInterpolation(node)){//是否为差值文本/*编译差值文本*/}if(node.childNodes && node.childNodes.length>0){this.compile(node)}})}isElement(node){return node.nodeType===1}isInterpolation(node){return node.nodeType===3 && /\{\{(.*)\}\}/.test(node.textContent)}
}

3.3 依赖收集

  • 视图中会用到data中的某个key,这被称为依赖,一个key可能出现在视图中的多个位置,每次都需要收集出来用一个Watcher来维护他们,这个过程被称为依赖收集,很多歌Watcher需要一个Dep来管理,需要更新时由Dep统一通知
    在这里插入图片描述

  • 基本思路

  1. defineReactive为每一个key创建一个Dep,比如data1创建Dep1
  2. 初始化视图时,读取某个key,例如data1,就创建一个watcher1
  3. 由于读取key时触发getter方法,边疆watcher1天假到data1的Dep1中份
  4. 当data1更新时,触发setter,通过Dep1通知所有的watcher更新
class Wacther{constructor(vm,key,updater){this.$vm=vm;this.$key=key;this.updaterFn=updater;//创建实例时,把当前实例指定到Dep.target静态属性上Dep.target=this;vm[key]//读一下key,触发getDep.target=nullupdate(){this.updaterFn.call(this.$vm,this.$vm[this.$key])}}
}
class Dep{constructor(){this.deps=[];//依赖管理 }addDep(dep){this.deps.push(dep)}notify(){this.deps.forEach((dep)=>{dep.update()})}
}
// 创建Watcher时触发getter
function defineReactive(obj,key,val){this.observe(val)const dep=new Dep()Object.defineProperty(obj,key,{get (){Dep.target && dep.addDep(Dep.target)//Dep.target就是Watcher实例return val},set(newVal){if(newVal===val)returndep.notify()//通知dep执行更新方法  }})
}

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

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

相关文章

4G核心网的演变与创新:从传统到虚拟化的跨越

4G核心网 随着移动通信技术的不断发展,4G核心网已经经历了从传统的硬件密集型架构到现代化、虚拟化网络架构的重大转型。这一演变不仅提升了网络的灵活性和可扩展性,也为未来的5G、物联网(LOT)和边缘计算等技术的发展奠定了基础。…

HTML排版标签、语义化标签、块级和行内元素详解

目录 前言 一、HTML中的排版标签 1. 文本相关标签 1.1 标题标签 ~ 1.2 段落标签 1.3 强调和加粗 1.4 换行标签 1.5 水平线标签 二、HTML中的语义化标签 2.1 语义化标签概述 2.2 常见的语义化标签 示例(核心代码部分): 三、HTM…

【字节青训营-7】:初探 Kitex 字节微服务框架(使用ETCD进行服务注册与发现)

本文目录 一、Kitex概述二、第一个Kitex应用三、IDL四、服务注册与发现 一、Kitex概述 长话短说,就是字节跳动内部的 Golang 微服务 RPC 框架,具有高性能、强可扩展的特点,在字节内部已广泛使用。 如果对微服务性能有要求,又希望…

【数学】矩阵、向量(内含矩阵乘法C++)

目录 一、前置知识:向量(一列或一行的矩阵)、矩阵1. 行向量2. 列向量3. 向量其余基本概念4. 矩阵基本概念5. 关于它们的细节 二、运算1. 转置(1)定义(2)性质 2. 矩阵(向量&#xff0…

浅尝yolo11全程记录1-准备环境+官网模型推理(个人备份)

准备工作(虚拟环境、导入项目) 安装Anaconda 主要是为了创建和管理虚拟环境,在pycharm里按照项目里的requirments.txt安装依赖的时候,使用虚拟环境会好很多(我记得不用Anaconda也可以直接在pycharm的terminal里头创建…

5.攻防世界 fileinclude

进入题目页面如下 提示flag在flag.php ctrlu&#xff0c;查看源码 给出了一段PHP代码&#xff0c;进行代码审计 <?php // 检查是否开启了错误显示功能 if( !ini_get(display_errors) ) {// 如果没有开启&#xff0c;则将错误显示功能设置为开启状态ini_set(display_error…

红包雨项目前端部分

创建项目 pnpm i -g vue/cli vue create red_pakage pnpm i sass sass-locader -D pnpm i --save normalize.css pnpm i --save-dev postcss-px-to-viewportpnpm i vantlatest-v2 -S pnpm i babel-plugin-import -Dhttps://vant.pro/vant/v2/#/zh-CN/<van-button click&…

蓝桥杯嵌入式备赛(三)—— LED +按键 + LCD

目录 一、LED1、原理图介绍2、程序代码 二、按键1、原理图介绍2、程序代码 三、LCD1、原理图介绍2、程序代码 一、LED 1、原理图介绍 如果所示&#xff0c;STM32G431RBT6中有八个LED&#xff0c;由八个GPIO控制&#xff0c;分别为PC8-15&#xff0c;当输出为低电平时点亮。其中…

[Java基础]函数式编程

Lambda函数 JDK8新增的语法形式, 使用Lambda函数替代某些匿名内部类对象&#xff0c;从而让程序代码更简洁&#xff0c;可读性更好。 基本使用 lambda表达式只能简化函数式接口的匿名内部类写法 // 1.定义抽象类 abstract class Animal {public abstract void crt(); }publi…

Vim 多窗口编辑及文件对比

水平分割 :split 默认使用水平分割的方式。 :split :sp 垂直分割 :vsplit :vs 带文件的分割 :split 文件名 :sp 文件名 在光标所在的窗口&#xff0c;输入分割窗口命令就会对那个窗口进行分割。 切换窗口 Ctrlw 切换正在编辑的窗口 快速分割窗口 Ctrlwn 快速分割当前…

二级C语言题解:十进制转其他进制、非素数求和、重复数统计

目录 一、程序填空&#x1f4dd; --- 十进制转其他进制 题目&#x1f4c3; 分析&#x1f9d0; 二、程序修改&#x1f6e0;️ --- 非素数求和 题目&#x1f4c3; 分析&#x1f9d0; 三、程序设计&#x1f4bb; --- 重复数统计 题目&#x1f4c3; 分析&#x1f9d0; 前言…

使用服务器部署DeepSeek-R1模型【详细版】

文章目录 引言deepseek-r1IDE或者终端工具算力平台体验deepseek-r1模型总结 引言 在现代的机器学习和深度学习应用中&#xff0c;模型部署和服务化是每个开发者面临的重要任务。无论是用于智能推荐、自然语言处理还是图像识别&#xff0c;如何高效、稳定地将深度学习模型部署到…

央行发布《贸易金融分布式账本技术要求》,参考架构包括5部分

《银行科技研究社》(作者 木子剑):2024年12月11日,中国人民银行发布金融行业标准《贸易金融分布式账本技术要求》(JR/T 0308-2024)(以下简称“《要求》”),当日实施。据悉,该文件的起草单位包括6大行和多家股份制银行等。 《要求》规定了分布式账本技术在贸易金融领域…

Python aiortc API

本研究的主要目的是基于Python aiortc api实现抓取本地设备媒体流&#xff08;摄像机、麦克风&#xff09;并与Web端实现P2P通话。本文章仅仅描述实现思路&#xff0c;索要源码请私信我。 1 demo-server解耦 1.1 原始代码解析 1.1.1 http服务器端 import argparse import …

记录 | WPF基础学习Style局部和全局调用

目录 前言一、Style1.1 例子1.2 为样式起名字1.3 BasedOn 继承上一个样式 二、外部StyleStep1 创建资源字典BaseButtonStyle.xamlStep2 在资源字典中写入StyleStep3 App.xaml中写引用路径【全局】Step4 调用三、代码提供四、x:Key和x:Name区别 更新时间 前言 参考文章&#xff…

吴恩达深度学习——卷积神经网络实例分析

内容来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 文章目录 LeNet-5AlexNetVGG-16ResNets残差块 1*1卷积 LeNet-5 输入层&#xff1a;输入为一张尺寸是 32 32 1 32321 32321的图像&#xff0c;其中 32 32 3232 3232是图像的长和宽&…

【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据

一、下载z-paing插件 注意下载下载量最多的这个 进入Hbuilder以后点击“确定” 插件的官方文档地址&#xff1a; https://z-paging.zxlee.cn 二、z-paging插件的使用 在文档中向下滑动&#xff0c;会有使用方法。 使用z-paging标签将所有的内容包起来 配置标签中的属性 在s…

【B站保姆级视频教程:Jetson配置YOLOv11环境(七)Ultralytics YOLOv11配置】

Jetson配置YOLOv11环境&#xff08;7&#xff09;Ultralytics YOLOv11环境配置 文章目录 1. 下载YOLOv11 github项目2. 安装ultralytics包3. 验证ultralytics安装3.1 下载yolo11n.pt权重文件3.2 推理 1. 下载YOLOv11 github项目 创建一个目录&#xff0c;用于存放YOLOv11的项目…

第二天:系统从BIOS/UEFI到GRUB/bootloader的启动过程

目录 **一、BIOS/UEFI初始化阶段****二、引导加载程序&#xff08;GRUB&#xff09;的启动过程****1. BIOS模式下的GRUB分阶段加载****2. UEFI模式下的GRUB加载** **三、操作系统内核加载与初始化****四、关键组件与配置文件****五、故障排查与恢复****总结**常见问题如何在UEF…

【容器技术01】使用 busybox 构建 Mini Linux FS

使用 busybox 构建 Mini Linux FS 构建目标 在 Linux 文件系统下构建一个 Mini 的文件系统&#xff0c;构建目标如下&#xff1a; minilinux ├── bin │ ├── ls │ ├── top │ ├── ps │ ├── sh │ └── … ├── dev ├── etc │ ├── g…