设为首页收藏本站

IT技术擎 - 最棒的IT web技术交流社区

 找回密码
 注册为IT技术擎人

QQ登录

只需一步,快速开始

搜索
热搜: php h5 jquery
查看: 21|回复: 0

[未分类] 模拟Vue之数据驱动3

[复制链接]
发表于 2018-5-16 23:30:09 | 显示全部楼层 |阅读模式
一、前言
在"模拟Vue之数据驱动2"中,我们实现了个Observer构造函数,通过它可以达到监听已有数据data中的所有属性。
但,倘若我们想在某个对象中,新增某个属性呢?
如下: 那么岂不是,新增的infor属性,以及它的对象属性,没有得到监听。
此时,应该怎么处理呢? 通过走读Vue源码,发现他是采用另增属性方法$set实现的。 就是说,如果我们采用常规方法为对象增加属性(如上),我们没法得知并监控它,所以,我们为每个对象扩展一个$set方法,用于另增属性使用,即可,如下:
  1. data.user.$set('infor', {msg: 'happy'});
复制代码
好了,下面,我们就一同实现这个$set方法吧。

二、$set方法实现

首先,我们得创建一个恒定extendObj对象,用于将$set方法绑定在其中。 你可能会想,为什么我们需要一个extendObj对象呢?直接将$set函数赋值给每个需要监听的对象不就完了么? 是的,这样也可以,但是随着需求增长,倘若我们又想为每个监听对象扩展其他方法呢?难道又要去Observer里面为对象,一一赋值?
so,创建恒定extendObj对象,如下:
  1. const extendObj = {};
复制代码
因为,我们将$set绑定到extendObj中,且让$set为不可枚举型,所以会用到Object.defineProperty,固将其提取出来,作为一个方法如下:
  1. functionproxyObject(obj, key, val, enume){
  2. Object.defineProperty(obj, key, {
  3. value: val, enumerable: !!enume, writable: true, configurable: true
  4. });};
复制代码
接下来,就是实现$set方法了,整体结构如下:
  1. proxyObject(extendObj, '$set', function(key, val){
  2. //this指向extendObj if(this.hasOwnProperty(key)){
  3. return;
  4. }
  5. else{
  6. /*
  7. TODO:在extendObj中监听key属性, 且,若key属性值为对象,再次监听key属性值*/
  8. }});
复制代码
看到上面的TODO注释,是否似曾相识,不就是是在 \"模拟Vue之数据驱动2 \"遇见过的嘛,通过Observer.prototype.convert监听key属性,通过new Observer再次监听key属性值不就完啦。 的确,但是一旦这样做了,不就和上面我们提到的 \"直接将$set赋予监听对象 \"问题一样嘛,耦合性太大,且随着需求上涨,不易维护。
固而,在此需要一点小技巧:在observer模块中为每个监听对象赋予一个$Observer属性,其值指向Observer自身实例,如下:
  1. //observer.jsp.walk = function(data){
  2. let keys =Object.keys(data);
  3. keys.forEach( key = >{
  4. let val =data[key];
  5. if(typeofval === 'object'){
  6. newObserver(val);
  7. }
  8. this.convert(key, val);
  9. });
  10. //$Observer属性指向Observer自身实例 data.$Observer = this;
  11. }
  12. //新增一个observe方法p.observe = function(data){
  13. if(typeofdata === 'object'){
  14. newObserver(data); }}
复制代码
好了,这样之后,得$set整体实现如下:
  1. proxyObject(extendObj, '$set', function(key, val){
  2. if(this.hasOwnProperty(key)){
  3. return;
  4. }
  5. else{
  6. proxyObject(this, key, val, true);
  7. let ob = this.$Observer;
  8. ob.observe(val);
  9. ob.convert(key, val); }});
复制代码
到此,一个简单的$set方法构建完毕。 在上面我们提到,之所以需要一个恒定extendObj对象,是为了更好的代码管理。且,到目前为止,需要监听的对象上并没有扩展$set方法呢,所以,下面的事情就是为了达到以上效果,如下:
  1. //observer.jsfunctionObserver(data){
  2. if(!(thisinstanceofObserver)){
  3. returnnewObserver(data);
  4. }
  5. //将监听对象的隐指针指向我们的extendObj对象 data.__proto__ =extendObj;
  6. this.data =data;
  7. this.walk(data);}
复制代码
好了,一切完毕,接下来就测试下吧:
  1. <
  2. script src="./extendObj.js" > </script >
  3. <
  4. script src="./observer.js" > </script >
  5. <
  6. script >
  7. let data ={
  8. user: {
  9. name: 'Monkey', age: 24
  10. }, lover: {
  11. name: 'Dorie', age: 23
  12. }
  13. };
  14. Observer(data);
  15. </script >
复制代码
效果如下:
Perfect,完整代码见github。



上一篇:xml文件生成与下载
下一篇:JavaScript的setter与getter方法
该用户未在地球留下任何的痕迹

本版积分规则

QQ|小黑屋|帮助|IT技术擎 ( 沪ICP备15054863号  

GMT+8, 2018-8-22 15:47

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表