007-双向绑定原理

双向绑定原理

  • 双向绑定
  • 思考:
  • 一句话描述原理
  • DocuemntFragment(碎片化文档)
  • Object.defineProperty(数据劫持)
  • 发布订阅者模式
  • Vue 双向绑定图示
  • Vue 双向绑定完整实现代码

双向绑定

vue中 data定义的数据会添加双向绑定的功能,即数据更新后,页面内容会同步更新;页面内容更新后,数据也会同步更新。

思考:

  1. 初始化,如何将 data 中的数据更新到DOM模板中? - 碎片化文档
  2. 页面更新,如何更新数据? - input事件监听
  3. 数据变了更新页面,那如何知道数据变了呢? - 数据劫持,Object.defineProperty()
  4. 已知数据变了(发布者),如何更新跟这个数据相关的页面内容 {{}}、属性绑定、v-model(订阅者)呢? - 发布订阅者模式

一句话描述原理

Vue 数据双向绑定是通过数据劫持结合发布订阅者模式的方式来实现的。使用 DocuemntFragment(碎片化文档)获取所有子节点,将 v-model {{}} 类似语法的值进行填充,监听页面元素的 input 事件,当 val 变更时,更新 data 中的数据,给 data 通过 object.defineProperty 添加响应监听,当 val 变化时,会触发 set 方法,通过发布订阅模式,触发订阅者的更新方法,更新视图。

DocuemntFragment(碎片化文档)

在这里插入图片描述

function nodeToFragment(node){var fragment = document.createDocumentFragment();var child = null;while(child = node.firstChild){fragment.appendChild(child)}return fragment
}

Object.defineProperty(数据劫持)

在这里插入图片描述

var obj = {};  // 定义一个空对象
Object.defineProperty(obj, 'val', { // 定义要修改对象的属性get: function () {console.log('获取对象的值')},set: function (newVal) { console.log('设置对象的值:最新的值是'+newVal);}
});
obj.hello = 'hello world'

js通过Object.defineProperty方法简单的实现双向绑定:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input type="text" id="app"><span id="childSpan"></span>
</body>
<script>var obj = {}var initValue='初始值'Object.defineProperty(obj,'initValue',{get(){console.log('获取obj最新的值');return initValue},set(newVal){initValue = newValconsole.log('设置最新的值');// 获取到最新的值  然后将最新的值赋值给我们的spandocument.getElementById('childSpan').innerHTML = initValueconsole.log(obj.initValue);}})document.addEventListener('keyup', function (e) {obj.initValue = e.target.value; //监听文本框里面的值 获取最新的值 然后赋值给obj })</script>
</html>

发布订阅者模式

发布订阅者模式又叫 观察者模式,他定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得将得到通知。

// 实现发布订阅模式// 事件容器:
let handlers = {}// 添加事件:
handlers['onmsg'].push(fn1)// 触发事件:
this.handlers['onmsg'].forEach(handler => { handler(...params) })

学习参考:JavaScript设计模式 -发布订阅者模式

Vue 双向绑定图示

在这里插入图片描述

Vue 双向绑定完整实现代码

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title></head><body><div id="app">测试双向绑定demo<input type="text" v-model="text" /> {{text}}</div></body><script type="text/javascript">//编译函数function compile(node, vm) {var reg = /\{\{(.*)\}\}/; // 来匹配{{xxx}}中的xxx//如果是元素节点if(node.nodeType === 1) {var attr = node.attributes;//解析元素节点的所有属性for(let i = 0; i < attr.length; i++) {if(attr[i].nodeName == 'v-model') {var name = attr[i].nodeValue //看看是与哪一个数据相关node.addEventListener('input', function(e) { //将与其相关的数据改为最新值vm[name] = e.target.value})node.value = vm.data[name]; //将data中的值赋予给该nodenode.removeAttribute('v-model')}}}//如果是文本节点if(node.nodeType === 3) {if(reg.test(node.nodeValue)) {var name = RegExp.$1; //获取到匹配的字符串name = name.trim();node.nodeValue = vm[name]; //将data中的值赋予给该nodenew Watcher(vm, node, name) //绑定一个订阅者}}}// 在向碎片化文档中添加节点时,每个节点都处理一下function nodeToFragment(node, vm) {var fragment = document.createDocumentFragment();var child;while(child = node.firstChild) {compile(child, vm);fragment.appendChild(child);}return fragment}//  Vue构造函数     //   观察data中的所有属性值,注意增添了observefunction Vue(options) {this.data = options.data;observe(this.data, this)var id = options.el;var dom = nodeToFragment(document.getElementById(id), this)//处理完所有节点后,重新把内容添加回去document.getElementById(id).appendChild(dom)}//实现一个响应式监听属性的函数。一旦有赋新值就发生变化 function defineReactive(obj, key, val) {var dep = new Dep(); //观察者实例Object.defineProperty(obj, key, {get: function() {if(Dep.target) { //每一个观察着都是唯一的dep.addSub(Dep.target)}return val},set: function(newVal) {if(newVal === val) {return}val = newVal;console.log('新值' + val);//一旦更新立马通知dep.notify();}})}//实现一个观察者,对于一个实例 每一个属性值都进行观察。function observe(obj, vm) {for(let key of Object.keys(obj)) {defineReactive(vm, key, obj[key]);}}// Watcher监听者function Watcher(vm, node, name) {Dep.target = this;this.vm = vm;this.node = node;this.name = name;this.update();Dep.target = null;}Watcher.prototype = {update() {this.get();this.node.nodeValue = this.value //更改节点内容的关键},get() {this.value = this.vm[this.name] //触发相应的get}}//dep构造函数function Dep() {this.subs = [] // 观察主题添加订阅者}Dep.prototype = {// 添加订阅者addSub(sub) {this.subs.push(sub)},// 发布通知notify() {this.subs.forEach(function(sub) {sub.update();})}}var vm = new Vue({el: 'app',data: {text: '赵刚'}})</script></html>

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

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

相关文章

照片坐标 | 使用EXCEL批量读取照片GPS坐标并标注拍摄地图

一 前言 7、8月是旅游的季节&#xff0c;旅途过程我们经常使用手机拍摄记录美好的瞬间&#xff0c;整个旅途使用手机拍摄已成为用户高频的出行习惯&#xff0c;无论是小孩、年轻人、老年人&#xff0c;只要手机在手&#xff0c;都会频频举起手机进行拍摄&#xff0c;贯穿整个旅…

数据中心制冷系统设计40个问题

1、制冷系统安全运行的三个必要条件是什么&#xff1f; 答: &#xff08;1&#xff09;系统内的制冷剂压力不得出现异常高压&#xff0c;以免设备破裂。 &#xff08;2&#xff09;不得发生&#xff08;可能导致&#xff09;湿冲程、液爆、液击等误操作&#xff0c;以免设备破…

网工内推 | 网络工程师,IE认证优先,最高15K,有项目绩效奖金

01 重庆并联网络科技有限公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、负责集成项目的相关实施工作&#xff08;设备上架安装、网络设备配置、服务器相关系统配置安装、相关软件环境搭建及配置等&#xff09; 2、负责项目现场技术维护与技术支持&#xff1b;…

透视B站财报:从前景看“钱景”

3月7日晚&#xff0c;哔哩哔哩发布了2023年度及第四季度财报。 财报显示&#xff0c;哔哩哔哩2023年总营收225亿元&#xff0c;净亏损同比大幅收窄49%&#xff0c;其中第四季度总营收达63.5亿元。 在后续电话会议上&#xff0c;哔哩哔哩管理层对市场上重点关注的“B站2024年能…

ubuntu追加path环境变量

要在 bash shell 中追加 PATH 环境变量&#xff0c;你可以编辑用户的 .bashrc 文件&#xff08;对单个用户生效&#xff09;或者 .bash_profile 文件&#xff08;在某些系统上&#xff09;&#xff0c;或是系统级的配置文件&#xff08;例如 /etc/profile 或 /etc/environment&…

史上最全AP/mAP通用代码实现(yolov5 txt版本)-下

提示&#xff1a;通用map指标框架代码介绍&#xff0c;直接使用yolov5数据格式&#xff0c;实现论文map指标计算代码解读 文章目录 前言该版本是直接使用yolo数据格式实现map计算&#xff0c;集成txt转json格式内容。 一、map模块整体认识二、map计算应用代码解读三、通用map计…

项目实践《微信自动回复》

文章目录 一、前置接口一、打开微信二、监听微信信息三、截取聊天区域并提取关键字四、根据关键字自动回复五、基础版六、完整版 在我们的生活中&#xff0c;微信无疑是一个重要的社交工具。无论是工作还是社交&#xff0c;我们都离不开它。但是&#xff0c;随着繁忙的生活节奏…

egg如何写单元测试

优秀的代码需要有单元测试进行质量保证&#xff0c;每个测试用例都给应用的稳定性提供了一层保障。 测试目录结构 我们约定 test 目录为存放所有测试脚本的目录&#xff0c;测试所使用到的 fixtures 和相关辅助脚本都应该放在此目录下。 测试文件的目录和我们需要测试的文件目…

Redis进阶(三):主从复制

为了解决单点问题&#xff0c;实现多服务器部署redis&#xff0c;有几种解决方案可以实现&#xff1a;主从复制&#xff0c;主从哨兵还有集群。 何为主从复制 简单来说有三个服务器分别部署了redis-server程序&#xff0c;选中一个服务器当作主节点&#xff0c;其他的就是从节…

机器学习笔记 计算机视觉中的测距任务常见技术路线

一、计算机视觉中的测距任务 测距是计算机视觉中的一项关键任务,涉及测量物体和相机之间的距离。这些信息可用于多种应用,包括机器人、自动驾驶汽车和增强现实。测距技术有很多种,包括主动式和被动式,每种技术都有自己的优点和局限性。主动测距技术,例如飞行时间、结构光和…

动态规划DP之背包问题3---多重背包问题

目录 DP分析&#xff1a; 优化&#xff1a; 二进制优化 例题&#xff1a; 01背包是每个物品只有一个&#xff0c;完全背包问题是每个物品有无限个。 那么多重背包问题就是 每个物品有有限个。 有 N 种物品和一个容量是 V 的背包。 第 i 种物品最多有 si 件&#xff0c;每件体…

Softmax 回归 + 损失函数 + 图片分类数据集【动手学深度学习v2】李沐动手学深度学习课程笔记

目录 Softmax回归 损失函数 图片分类数据集 Softmax回归从零开始实现 Softmax回归简洁实现 Softmax回归 回归和分类的区别 回归问题举例上节课的预测房价问题&#xff0c;分类问题就是对样本进行分类 回归和分类的具体区别 假设真实的类别为第i个类别&#xff08;值为1&#x…

Restful风格接口简介

参考资料&#xff1a; 个人感觉最实用的Restful风格简介 Restful简介&#xff1a; Restful风格具有如下特点&#xff1a; URL要面向资源&#xff0c;使用和资源相关的名词要在URL中体现版本号根据Http不同的方法&#xff0c;进行不同类型的资源操作&#xff08;如用Get表示查…

js【详解】event loop(事件循环/事件轮询)

event loop 是异步回调的实现原理 js 代码的执行过程 从前到后&#xff0c;一行一行执行如果某一行执行报错&#xff0c;则停止下面代码的执行先把同步代码执行完&#xff0c;再执行异步 event loop 图解 以下方代码为例&#xff1a; 第1步 将第 1 行代码放入调用栈 将要执行第…

python数据分析numpy基础之布尔数组方法sum和any和all

1 python数据分析numpy基础之布尔数组方法sum和any和all 在前面文章介绍的sum、mean、std等统计方法中&#xff0c;布尔值True被转为1&#xff0c;False被转为0。而any和all&#xff0c;则将非0转为True&#xff0c;0转为False。 1.1 sum() python的numpy库的sum()函数&…

vue element plus Icon 图标

Element Plus 提供了一套常用的图标集合。 使用图标# 如果你想像用例一样直接使用&#xff0c;你需要全局注册组件&#xff0c;才能够直接在项目里使用。 如若需要查看所有可用的 SVG 图标请查阅 element-plus/icons-vue1.xelement-plus/icons-vuelatest 和有关 Icon Collect…

C# 生成有序Guid

C# 生成有序Guid public enum SequentialGuidType {/// <summary>/// 用于 MySql 和 PostgreSql./// 当使用 <see cref"Guid.ToString()" /> 方法进行格式化时连续./// </summary>AsString,/// <summary>/// 用于 Oracle./// 当使用 <s…

JavaScript极速入门(2)

JQuery W3C标准给我们提供了一系列函数,让我们可以操作: 网页内容 网页结构 网页样式 但是原生的JavaScript提供的API操作DOM元素时,代码比较繁琐,冗长.我们学习使用JQuery来操作页面对象. JQuery是一个快速,简洁且功能丰富的JavaScript框架,于2006年发布.它封装JavaScript常…

Linux运维:实现光盘开机自动挂载、配置本地yum源教程

Linux运维&#xff1a;实现光盘开机自动挂载、配置本地yum源教程 一、光盘开机自动挂载1、检查光驱设备2、创建挂载点3、编辑/etc/fstab文件4、测试挂载 二、配置本地yum源(挂载光盘或ISO文件)1、挂载ISO文件2、创建YUM仓库配置文件3、清理YUM缓存并测试 &#x1f496;The Begi…

【netty系列-02】深入理解socket本质和BIO底层实现

Netty系列整体栏目 内容链接地址【一】深入理解网络通信基本原理和tcp/ip协议https://zhenghuisheng.blog.csdn.net/article/details/136359640【二】深入理解Socket本质和BIOhttps://zhenghuisheng.blog.csdn.net/article/details/136549478 深入理解socket本质和bio底层实现 …