Vue数据驱动模拟实现5

发布时间 - 2026-01-10 22:30:10    点击率:

一、前言

在"模拟Vue之数据驱动4"中,我们实现了push、pop等数组变异方法。

但是,在随笔末尾我们提到,当pop、sort这些方法触发后,该怎么办呢?因为其实,它们并没有往数组中新增属性呢。

而且,当数据改动后,如果我们在变动数据处,就立即更改数据也未免性能不够,此时,走读Vue源码,发现他用了一个很巧妙的方法,就是职责链模式。当某个数据有所变动时,它会向上传递,通俗点就是冒泡至根结点,这样我们也可以在自己代码中使用事件代理咯,哇卡哇卡。

示意图如下所示:

好了,说了这么多,我们下面就一起来实现下吧。

二、正文

注:以下代码皆编写在observer.js文件中。

首先,当数据变动,或者触发某个事件时,我们需要与变动数据关联一个自定义事件(自定义事件详情见here),如果触发某个事件,那么就执行,如下:

绑定事件方法:

//let p = Observer.prototype
p.on = function(eventName, fn){
 let listener = this.listener = this.listener || [];
 if(typeof eventName === 'string' && typeof fn === 'function'){
  if(!listener[eventName]){
   listener[eventName] = [fn];
  }else{
   listener[eventName].push(fn);
  }
 } 
}

取消事件方法:

//let p = Observer.prototype
p.off = function(eventName, fn){
 let listener = this.listener = this.listener || [];
 let actionArray = listener[eventName];
 if(typeof eventName === 'string' && Array.isArray(actionArray)){
  if(typeof fn === 'function'){
   actionArray.forEach( (func, i, arr) => {
    if(func === fn){
     arr.splice(i,1); 
    }
   });
  }
 }
}

触发事件方法:

//let p = Observer.prototype
p.emit = function(eventName){
 let listener = this.listener = this.listener || [];
 let actionArray = listener[eventName];
 if(Array.isArray(actionArray)){
  actionArray.forEach( func => {
   if(typeof func === 'function'){
    func(); 
   }
  }); 
 }
}

其次,就是当数据变动,触发自身相关事件后,怎么一路冒泡到根结点的处理了。

怎么冒泡到根结点呢?

那就自身结点关联父结点嘛,这样不就可以追溯到根节点了么。

所以,我们在Observer.walk时,就将自己的父节点记录即可,如下:

//let p = Observer.prototype
p.observe = function(key, data){
 if(typeof data === 'object'){
  let ob = new Observer(data); 
  //关联父节点
  ob._parent = {
   key,
   ob: this
  };
 } 
}

最后,有了子父结点的依赖关系,那么冒泡方法就OK啦,如下:

//let p = Observer.prototype
p.notify = function(eventName){
 let ob = this._parent && this._parent.ob;
 let key = ob && this._parent.key || 'root';
 console.log('parent--'+key+' event--'+eventName);
 this.emit(eventName);
 //判断节点是否有父节点,若有,就向上传递事件
 ob && ob.notify(eventName); 
}

Perfect,具体代码详见github.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Vue  # 数据驱动  # Vue数据驱动表单渲染  # 轻松搞定form表单  # 浅谈vuejs实现数据驱动视图原理  # 详解VueJS 数据驱动和依赖追踪分析  # Vue数据驱动模拟实现4  # Vue数据驱动模拟实现2  # Vue数据驱动模拟实现1  # Vue数据驱动模拟实现3  # 详解Vue数据驱动原理  # 自定义  # 自己的  # 好了  # 那就  # 说了  # 这么多  # 用了  # 不就  # 所示  # 若有  # 就将  # 它会  # 写在  # 绑定  # 就向  # 大家多多  # 下吧  # 追溯到  # 组中  # 实现了 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在阿里云部署织梦网站?  国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?  ChatGPT常用指令模板大全 新手快速上手的万能Prompt合集  利用vue写todolist单页应用  如何在景安服务器上快速搭建个人网站?  清除minerd进程的简单方法  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  如何在万网主机上快速搭建网站?  高端企业智能建站程序:SEO优化与响应式模板定制开发  详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)  如何打造高效商业网站?建站目的决定转化率  百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭  php json中文编码为null的解决办法  深入理解Android中的xmlns:tools属性  ,在苏州找工作,上哪个网站比较好?  php打包exe后无法访问网络共享_共享权限设置方法【教程】  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?  Laravel怎么为数据库表字段添加索引以优化查询  深圳网站制作的公司有哪些,dido官方网站?  Python3.6正式版新特性预览  浅谈Javascript中的Label语句  Laravel怎么上传文件_Laravel图片上传及存储配置  Laravel如何使用Service Provider注册服务_Laravel服务提供者配置与加载  制作电商网页,电商供应链怎么做?  如何破解联通资金短缺导致的基站建设难题?  Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南  Java解压缩zip - 解压缩多个文件或文件夹实例  EditPlus中的正则表达式实战(6)  利用python获取某年中每个月的第一天和最后一天  Laravel如何记录自定义日志?(Log频道配置)  Android自定义控件实现温度旋转按钮效果  Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】  Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转  Laravel如何创建自定义Facades?(详细步骤)  Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】  标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析  如何利用DOS批处理实现定时关机操作详解  Swift中switch语句区间和元组模式匹配  电商网站制作价格怎么算,网上拍卖流程以及规则?  南京网站制作费用,南京远驱官方网站?  Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】  HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  HTML 中动态设置元素 name 属性的正确语法详解  Laravel模型关联查询教程_Laravel Eloquent一对多关联写法  在Oracle关闭情况下如何修改spfile的参数  JavaScript如何操作视频_媒体API怎么控制播放  香港服务器WordPress建站指南:SEO优化与高效部署策略  如何快速搭建个人网站并优化SEO?