实现一个简单得数据响应系统


Posted in Javascript onNovember 11, 2021

1、Dep

其实,这就是一个依赖收集的容器, depend 收集依赖, notify 触发依赖

class Dep{
  constructor() {
    this._subs = [];
  }
  depend () {
    this._subs.push(Dep.target)
  }
  notify() {
    this._subs.forEach(item => {
      item.fn();
    })
  }
}

// 其实就是 dep 和 watcher 基情满满的开始,watcher 中用到
// 通过一个全局属性来存 watcher
Dep.target = null;

function pushTarget(watch) {
  Dep.target = watch;
}

function popTarget() {
  Dep.target = null;
}

2、了解 obverser

递归,将 data 对象所有属性转化为访问器属性

// 转为访问器属性
function defineReactive (obj, key, val, shallow) {

  // 创建一个依赖收集容器
  let dep = new Dep();
  let childOb = !shallow && observe(val)

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      if(Dep.target) {
        // 收集依赖
        dep.depend();
      }
      return val;
      // ...
    },
    set: function reactiveSetter (newVal) {
      if(newVal === val) return;
      // 继续递归遍历
      observe(newVal);
      // 触发依赖
      dep.notify();
      // ...
    }
  })
}

class Observer{
  constructor(data) {
    this.walk(data);
  }

  walk(data) {
    const keys = Object.keys(data)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(data, keys[i], data[keys[i]])
    }
  }
}

// 递归,将 data 对象所有属性转化为访问器属性
function observe (data) {
  if(Object.prototype.toString.call(data) !== '[object Object]') return;
  new Observer(data);
}

此时就可以把任意一个对象的全部属性转为访问器

3、了解 watch 和 observer

const data = {
  a: 1,
  b: 2
}

// 首先监控一个对象
observe(data);

watcher 的主要功能是检测某个属性,当属性变化时触发一个回调

class Watcher{
  /**
  * @params {Function} exp 一个属性表达式
  * @params {Function} fn 回调
  */
  constructor(exp, fn) {
    this.exp = exp;
    this.fn = fn;

    // 存 watcher
    // Dep.target = this;
    pushTarget(this);

    // 先执行一次表达式函数,会在调用过程中,
    // 触发到 data.a 的访问器, data.a 的 get 被执行,
    // 触发 dep.depend() 开始收集依赖
    this.exp();

    // 释放 Dep.target
    popTarget();
  }
}

// new Watcher 这样一个依赖就被收集了
new Watcher(() => {
  return data.a + data.b;
}, () => {
  console.log('change')
})

4、触发依赖

data.a = 3; // change
data.b = 3; // change

5、总结一下流程

  • 把一个对象的全部属性转化为访问器
  • 当为某一个属性增加 watcher 时,会触发改属性的 getget 函数中会把该 watcher 存到该属性的 dep 依赖容器中
  • 当这个属性发生变化时,会出发改属性的 set 的方法,set 函数中会把 dep 存的依赖都执行

到此这篇关于实现一个简单得数据响应系统的文章就介绍到这了,更多相关数据响应系统内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
又一个小巧的图片预加载类
May 05 Javascript
jquery遍历checkbox的注意事项说明
Feb 21 Javascript
jQuery实现提交按钮点击后变成正在处理字样并禁止点击的方法
Mar 24 Javascript
基于jquery实现的树形菜单效果代码
Sep 06 Javascript
使用ajaxfileupload.js实现上传文件功能
Aug 13 Javascript
基于原生js淡入淡出函数封装(兼容IE)
Oct 20 Javascript
JavaScript cookie详解及简单实例应用
Dec 31 Javascript
详解Vue生命周期的示例
Mar 10 Javascript
详解微信小程序实现WebSocket心跳重连
Jul 31 Javascript
微信小程序HTTP接口请求封装的实现
Feb 21 Javascript
微信小程序按钮点击动画效果的实现
Sep 04 Javascript
JS中数组实现代码(倒序遍历数组,数组连接字符串)
Dec 29 Javascript
JavaScript函数柯里化
Nov 07 #Javascript
JS数组去重详情
Nov 07 #Javascript
手写实现JS中的new
Nov 07 #Javascript
用JS写一个发布订阅模式
Nov 07 #Javascript
浅谈JavaScript浅拷贝和深拷贝
JavaScript严格模式不支持八进制的问题讲解
Javascript使用integrity属性进行安全验证
Nov 07 #Javascript
You might like
深入理解curl类,可用于模拟get,post和curl下载
2013/06/08 PHP
PHP获取浏览器信息类和客户端地理位置的2个方法
2014/04/24 PHP
PHP 7.0.2 正式版发布
2016/01/08 PHP
脚本之家贴图转换+转贴工具用到的js代码超级推荐
2007/04/05 Javascript
使用 JScript 创建 .exe 或 .dll 文件的方法
2011/07/13 Javascript
jQuery侧边栏随窗口滚动实现方法
2013/03/04 Javascript
iframe父页面获取子页面参数的方法
2014/02/21 Javascript
javascript的alert box在java中如何显示多行
2014/05/18 Javascript
JavaScript实现同步于本地时间的动态时间显示方法
2015/02/02 Javascript
JS中的THIS和WINDOW.EVENT.SRCELEMENT详解
2015/05/25 Javascript
js实现下拉列表选中某个值的方法(3种方法)
2015/12/17 Javascript
JavaScript操作HTML DOM节点的基础教程
2016/03/11 Javascript
JavaScript学习笔记之数组的增、删、改、查
2016/03/23 Javascript
Jquery Easyui表单组件Form使用详解(30)
2016/12/19 Javascript
分享Bootstrap简单表格、表单、登录页面
2017/08/04 Javascript
AngularJs中$cookies简单用法分析
2019/05/30 Javascript
如何利用node.js开发一个生成逐帧动画的小工具
2019/12/01 Javascript
Python生成器(Generator)详解
2015/04/13 Python
python numpy格式化打印的实例
2018/05/14 Python
Python实现的爬取小说爬虫功能示例
2019/03/30 Python
Python button选取本地图片并显示的实例
2019/06/13 Python
Python3环境安装Scrapy爬虫框架过程及常见错误
2019/07/12 Python
python实现FTP循环上传文件
2020/03/20 Python
python多进程使用函数封装实例
2020/05/02 Python
Python socket服务常用操作代码实例
2020/06/22 Python
html5 Canvas画图教程(5)—canvas里画曲线之arc方法
2013/01/09 HTML / CSS
利用Storage Event实现页面间通信的示例代码
2018/07/26 HTML / CSS
详解如何使用rem或viewport进行移动端适配
2020/08/14 HTML / CSS
美国的Eastbay旗下的运动款子品牌:Final-Score
2018/01/01 全球购物
Everlast官网:拳击、综合格斗和健身相关的体育用品
2020/08/03 全球购物
软件测试英文面试题
2012/10/14 面试题
入党推优材料
2014/06/02 职场文书
小学家长学校培训材料
2014/08/24 职场文书
校园运动会广播稿
2014/10/06 职场文书
2014年高校辅导员工作总结
2014/12/09 职场文书
学校教学管理制度
2015/08/06 职场文书