0

0

解析vue中observer数据双向绑定原理(代码分享)

奋力向前

奋力向前

发布时间:2021-08-23 09:45:50

|

2308人浏览过

|

来源于禅境花园

转载

之前的文章《浅析JS中Array对象一些操作方法(附代码)》中,给大家了解了JS中Array对象一些操作方法。下面本篇文章给大家了解vue中observer数据双向绑定原理,伙伴们来看看一下。

解析vue中observer数据双向绑定原理(代码分享)

vue数据双向绑定原理和简单的实现

微信截图_20210823091733.jpg

1)vue数据双向绑定原理-observer

2)vue数据双向绑定原理-wather

立即学习前端免费学习笔记(深入)”;

3)vue数据双向绑定原理-解析器 Complie

vue数据双向绑定原理, 和简单的实现

去他喵的底层原理,框架内核,老夫写代码只用Jquery

个人觉得,不论是否是长期与之交集,还是应该看下核心的东西。多多了解高人是如何实现的,这样才能学到更多的知识,才能成长进步。倘若某天被人问起,某种框架内裤,其实现原理,那么只能是一脸懵逼了。

实现数据绑定的做法有大致如下几种:

  • 发布者-订阅者模式(backbone.js

  • 脏值检查(angular.js

  • 数据劫持(vue.js

vue.js则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

假如写过C#winform自定义控件的,我想更好理解之后的逻辑和实现原理

C#中当控件的某个属性发生了变化,就刷新视图

priveate int  a ;
public  int A
{
   get { return a; }
   set { if(a!=value){a = value; Invalidate(); } }
}

# 当a的值发生变化, 就重绘视图

再来看看Object.defineProperty(obj, prop, descriptor) 方法

地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。

  • obj需要被操作的目标对象

  • prop目标对象需要定义或修改的属性的名称。

    Meku
    Meku

    AI应用和网页开发工具

    下载
  • descriptor将被定义或修改的属性的描述符

descriptor

  • configurable当且仅当该属性的configurabletrue时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为false

  • enumerable当且仅当该属性的enumerabletrue时,该属性才能够出现在对象的枚举属性中。默认为false。数据描述符同时具有以下可选键值:

  • value该属性对应的值。可以是任何有效的JavaScript值(数值,对象,函数等)。默认为undefined

  • writable当且仅当该属性的writabletrue时,该属性才能被赋值运算符改变。默认为false。 存取描述符同时具有以下可选键值:

  • get一个给属性提供getter的方法,如果没有getter则为undefined。该方法返回值被用作属性值。默认为undefined

  • set一个给属性提供setter的方法,如果没有setter则为undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为undefined

先来实现一个简单数据劫持

var A = {};
var a = "";
Object.defineProperty(A, "a", {
  set: function (value) {
    a = value;
  },
  get: function () {
    return "My name is " + a;
  },
});

A.a = "chuchur";
console.log(A.a); // My name is chuchur

不光是这么简单,来看下vue的代码

{{word}}

已经实现的简单的数据劫持,那么有多个属性,就要实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,还需要一个订阅器Dep来收集这些属性的变动来通知订阅者

元素节点的v-model,v-on:click,就需要实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数

最后实现一个订阅者Watcher,作为连接ObserverCompile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

大概的流程图如下: 

微信截图_20210823093103.jpg

实现Observer

将需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上settergetter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

// observe
function observe(data) {
  if (data && typeof data === "object") {
    // 取出所有属性遍历
    Object.keys(data).forEach(function (key) {
      defineReactive(data, key, data[key]);
    });
  }
  return;
}

function defineReactive(data, key, val) {
  observe(val); // 监听子属性
  Object.defineProperty(data, key, {
    enumerable: true, // 可枚举
    configurable: false, // 不能再define
    get: function () {
      return val;
    },
    set: function (value) {
      console.log("监听到值变化了: ", val, "==>", value);
      val = value;
    },
  });
}
var A = {
  fristName: "chuchur",
  age: 29,
};
observe(A);

A.fristName = "nana"; //监听到值变化了:  chuchur ==> nana
A.age = 30; //监听到值变化了:  29 ==> 30

这样就实现了多个属性的监听,接下来就是实现订阅器Dep,当这些属性变化的时候,触发通知notify,告诉执行订阅者执行更新函数

//Dep
function Dep() {
  this.subs = [];
}
Dep.prototype = {
  addSub: function (sub) {
    this.subs.push(sub);
  },
  notify: function () {
    this.subs.forEach(function (sub) {
      sub.update();
    });
  },
};

把订阅器植入到监听器里

function defineReactive(data, key, val) {

  var dep = new Dep()
  observe(val); //监听子属性
  Object.defineProperty(data, key, {
    set: function(value) {
      dep.notify() //发出通知, 我被改变了
    }
  });

}

至此,简陋的监听器就实现完成了,接下来继续完成Watcher

推荐学习:vue.js教程

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

22

2026.01.27

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

119

2026.01.26

edge浏览器怎样设置主页 edge浏览器自定义设置教程
edge浏览器怎样设置主页 edge浏览器自定义设置教程

在Edge浏览器中设置主页,请依次点击右上角“...”图标 > 设置 > 开始、主页和新建标签页。在“Microsoft Edge 启动时”选择“打开以下页面”,点击“添加新页面”并输入网址。若要使用主页按钮,需在“外观”设置中开启“显示主页按钮”并设定网址。

48

2026.01.26

苹果官方查询网站 苹果手机正品激活查询入口
苹果官方查询网站 苹果手机正品激活查询入口

苹果官方查询网站主要通过 checkcoverage.apple.com/cn/zh/ 进行,可用于查询序列号(SN)对应的保修状态、激活日期及技术支持服务。此外,查找丢失设备请使用 iCloud.com/find,购买信息与物流可访问 Apple (中国大陆) 订单状态页面。

184

2026.01.26

npd人格什么意思 npd人格有什么特征
npd人格什么意思 npd人格有什么特征

NPD(Narcissistic Personality Disorder)即自恋型人格障碍,是一种心理健康问题,特点是极度夸大自我重要性、需要过度赞美与关注,同时极度缺乏共情能力,背后常掩藏着低自尊和不安全感,影响人际关系、工作和生活,通常在青少年时期开始显现,需由专业人士诊断。

7

2026.01.26

windows安全中心怎么关闭 windows安全中心怎么执行操作
windows安全中心怎么关闭 windows安全中心怎么执行操作

关闭Windows安全中心(Windows Defender)可通过系统设置暂时关闭,或使用组策略/注册表永久关闭。最简单的方法是:进入设置 > 隐私和安全性 > Windows安全中心 > 病毒和威胁防护 > 管理设置,将实时保护等选项关闭。

7

2026.01.26

2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】
2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】

铁路12306提供起售时间查询、起售提醒、购票预填、候补购票及误购限时免费退票五项服务,并强调官方渠道唯一性与信息安全。

178

2026.01.26

个人所得税税率表2026 个人所得税率最新税率表
个人所得税税率表2026 个人所得税率最新税率表

以工资薪金所得为例,应纳税额 = 应纳税所得额 × 税率 - 速算扣除数。应纳税所得额 = 月度收入 - 5000 元 - 专项扣除 - 专项附加扣除 - 依法确定的其他扣除。假设某员工月工资 10000 元,专项扣除 1000 元,专项附加扣除 2000 元,当月应纳税所得额为 10000 - 5000 - 1000 - 2000 = 2000 元,对应税率为 3%,速算扣除数为 0,则当月应纳税额为 2000×3% = 60 元。

39

2026.01.26

oppo云服务官网登录入口 oppo云服务登录手机版
oppo云服务官网登录入口 oppo云服务登录手机版

oppo云服务https://cloud.oppo.com/可以在云端安全存储您的照片、视频、联系人、便签等重要数据。当您的手机数据意外丢失或者需要更换手机时,可以随时将这些存储在云端的数据快速恢复到手机中。

172

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue 教程
Vue 教程

共42课时 | 7.2万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 1.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号