Vue数据驱动模拟实现3

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

一、前言

在"模拟Vue之数据驱动2"中,我们实现了个Observer构造函数,通过它可以达到监听已有数据data中的所有属性。

但,倘若我们想在某个对象中,新增某个属性呢?

如下:

那么岂不是,新增的infor属性,以及它的对象属性,没有得到监听。

此时,应该怎么处理呢?

通过走读Vue源码,发现他是采用另增属性方法$set实现的。

就是说,如果我们采用常规方法为对象增加属性(如上),我们没法得知并监控它,所以,我们为每个对象扩展一个$set方法,用于另增属性使用,即可,如下:

data.user.$set('infor', {msg: 'happy'});

好了,下面,我们就一同实现这个$set方法吧。

二、$set方法实现

首先,我们得创建一个恒定extendObj对象,用于将$set方法绑定在其中。

你可能会想,为什么我们需要一个extendObj对象呢?直接将$set函数赋值给每个需要监听的对象不就完了么?

是的,这样也可以,但是随着需求增长,倘若我们又想为每个监听对象扩展其他方法呢?难道又要去Observer里面为对象,一一赋值?

so,创建恒定extendObj对象,如下:

const extendObj = {};

因为,我们将$set绑定到extendObj中,且让$set为不可枚举型,所以会用到Object.defineProperty,固将其提取出来,作为一个方法如下:

function proxyObject(obj, key, val, enume){
  Object.defineProperty(obj, key, {
    value: val,
    enumerable: !!enume,
    writable: true,
    configurable: true
  });  
};

接下来,就是实现$set方法了,整体结构如下:

proxyObject(extendObj, '$set', function(key, val){
  //this指向extendObj
  if(this.hasOwnProperty(key)){
    return;
  }else{
    /*
     TODO:在extendObj中监听key属性,
     且,若key属性值为对象,再次监听key属性值
    */     
  }  
});

看到上面的TODO注释,是否似曾相识,不就是是在“模拟Vue之数据驱动2”遇见过的嘛,通过Observer.prototype.convert监听key属性,通过new Observer再次监听key属性值不就完啦。

的确,但是一旦这样做了,不就和上面我们提到的“直接将$set赋予监听对象”问题一样嘛,耦合性太大,且随着需求上涨,不易维护。

固而,在此需要一点小技巧:在observer模块中为每个监听对象赋予一个$Observer属性,其值指向Observer自身实例,如下:

//observer.js
p.walk = function(data){
  let keys = Object.keys(data);
  keys.forEach( key => {
    let val = data[key];
    if(typeof val === 'object'){
      new Observer(val);
    }
    this.convert(key, val);
  });
  //$Observer属性指向Observer自身实例
  data.$Observer = this;
}
//新增一个observe方法
p.observe = function(data){
  if(typeof data === 'object'){
    new Observer(data);  
  }  
}

好了,这样之后,得$set整体实现如下:

proxyObject(extendObj, '$set', function(key, val){
  if(this.hasOwnProperty(key)){
    return;
  }else{
    proxyObject(this, key, val, true);
    let ob = this.$Observer;
    ob.observe(val);
    ob.convert(key, val);  
  }  
});

到此,一个简单的$set方法构建完毕。

在上面我们提到,之所以需要一个恒定extendObj对象,是为了更好的代码管理。且,到目前为止,需要监听的对象上并没有扩展$set方法呢,所以,下面的事情就是为了达到以上效果,如下:

//observer.js
function Observer(data){
  if(!(this instanceof Observer)){
    return new Observer(data);
  }
  //将监听对象的隐指针指向我们的extendObj对象
  data.__proto__ = extendObj;
  this.data = data;
  this.walk(data);  
}

好了,一切完毕,接下来就测试下吧:

<script src="./extendObj.js"></script>
<script src="./observer.js"></script>
<script>
  let data = {
    user: {
      name: 'Monkey',
      age: 24
    },
    lover: {
      name: 'Dorie',
      age: 23
    }
  };
  Observer(data);
</script>

效果如下:

Perfect,完整代码见github。

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


# Vue  # 数据驱动  # Vue数据驱动表单渲染  # 轻松搞定form表单  # 浅谈vuejs实现数据驱动视图原理  # 详解VueJS 数据驱动和依赖追踪分析  # Vue数据驱动模拟实现5  # Vue数据驱动模拟实现4  # Vue数据驱动模拟实现2  # Vue数据驱动模拟实现1  # 详解Vue数据驱动原理  # 好了  # 不就  # 绑定  # 是在  # 他是  # 在此  # 已有  # 将其  # 太大  # 这样做  # 又要  # 作为一个  # 它可以  # 在上面  # 到此  # 岂不是  # 似曾相识  # 创建一个  # 小技巧  # 值为 


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


相关推荐: 北京专业网站制作设计师招聘,北京白云观官方网站?  Laravel如何使用模型观察者?(Observer代码示例)  手机怎么制作网站教程步骤,手机怎么做自己的网页链接?  如何在IIS管理器中快速创建并配置网站?  EditPlus 正则表达式 实战(3)  Laravel如何使用Livewire构建动态组件?(入门代码)  网站制作报价单模板图片,小松挖机官方网站报价?  Laravel怎么实现验证码功能_Laravel集成验证码库防止机器人注册  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  如何登录建站主机?访问步骤全解析  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  佛山网站制作系统,佛山企业变更地址网上办理步骤?  PHP正则匹配日期和时间(时间戳转换)的实例代码  油猴 教程,油猴搜脚本为什么会网页无法显示?  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  如何在VPS电脑上快速搭建网站?  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  如何快速选择适合个人网站的云服务器配置?  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤  logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?  Laravel怎么自定义错误页面_Laravel修改404和500页面模板  Laravel如何使用Blade组件和插槽?(Component代码示例)  Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势  如何制作一个表白网站视频,关于勇敢表白的小标题?  如何在IIS7上新建站点并设置安全权限?  网站页面设计需要考虑到这些问题  Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  Laravel如何集成第三方登录_Laravel Socialite实现微信QQ微博登录  移动端脚本框架Hammer.js  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  开心动漫网站制作软件下载,十分开心动画为何停播?  如何自定义建站之星网站的导航菜单样式?  laravel怎么在请求结束后执行任务(Terminable Middleware)_laravel Terminable Middleware请求结束任务执行方法  lovemo网页版地址 lovemo官网手机登录  详解Android中Activity的四大启动模式实验简述  美食网站链接制作教程视频,哪个教做美食的网站比较专业点?  新三国志曹操传主线渭水交兵攻略  如何在搬瓦工VPS快速搭建网站?  微信公众帐号开发教程之图文消息全攻略  微信小程序 配置文件详细介绍  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  浅述节点的创建及常见功能的实现  如何在建站主机中优化服务器配置?  如何在Windows服务器上快速搭建网站?  如何基于云服务器快速搭建网站及云盘系统?  今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层