怎么更新harmonyos系统,(持续更新 )HarmonyOS系统中的JS开发框架 4

接上文

b49a796bff4b7dec422269008fa298f0.png

第一部分export function Subject(target) {

const subject = this;

subject._hijacking = true;

defineProp(target, SYMBOL_OBSERVABLE, subject);

if (Array.isArray(target)) {

hijackArray(target);

}

Object.keys(target).forEach(key => hijack(target, key, target[key]));

}

构造函数。基本没什么难点。设置 _hijacking 属性为 true,用来标示这个对象已经被劫持了。Object.keys 通过遍历来劫持每个属性。如果是数组,则调用 hijackArray。

第二部分

两个静态方法。Subject.of = function(target) {

if (!target || !canObserve(target)) {

return target;

}

if (target[SYMBOL_OBSERVABLE]) {

return target[SYMBOL_OBSERVABLE];

}

return new Subject(target);

};

Subject.is = function(target) {

return target && target._hijacking;

};

Subject 的构造函数并不直接被外部调用,而是封装到了 Subject.of 静态方法中。

如果目标不能被观察,那么直接返回目标。如果

target[SYMBOL_OBSERVABLE] 不是 undefined,说明目标已经被初始化过了。

否则,调用构造函数初始化 Subject。

Subject.is 则用来判断目标是否被劫持过了。

第三部分Subject.prototype.attach = function(key, observer) {

if (typeof key === 'undefined' || !observer) {

return;

}

if (!this._obsMap) {

this._obsMap = {};

}

if (!this._obsMap[key]) {

this._obsMap[key] = [];

}

const observers = this._obsMap[key];

if (observers.indexOf(observer) < 0) {

observers.push(observer);

return function() {

observers.splice(observers.indexOf(observer), 1);

};

}

};

这个方法很眼熟,对,就是上文的

Observer.prototype.subscribe 中调用的。作用是某个观察者用来订阅主题。而这个方法则是“主题是怎么订阅的”。

观察者维护这一个主题的哈希表 _obsMap。哈希表的 key 是需要订阅的 key。比如某个观察者订阅了 name 属性的变化,而另一个观察者订阅了 age 属性的变化。而且属性的变化还可以被多个观察者同时订阅,因此哈希表存储的值是一个数组,数据的每个元素都是一个观察者。

第四部分Subject.prototype.notify = function(key) {

if (

typeof key === 'undefined' ||

!this._obsMap ||

!this._obsMap[key]

) {

return;

}

this._obsMap[key].forEach(observer => observer.update());

};

当属性发生变化是,通知订阅了此属性的观察者们。遍历每个观察者,并调用观察者的 update 方法。我们上文中也提到了,脏检查就是在这个方法内完成的。

第五部分Subject.prototype.setParent = function(parent, key) {

this._parent = parent;

this._key = key;

};

Subject.prototype.notifyParent = function() {

this._parent && this._parent.notify(this._key);

};

这部分是用来处理属性嵌套(nested object)的问题的。就是类似这种对象:

{ user: { name: 'JJC' } }。

第六部分function hijack(target, key, cache) {

const subject = target[SYMBOL_OBSERVABLE];

Object.defineProperty(target, key, {

enumerable: true,

get() {

const observer = ObserverStack.top();

if (observer) {

observer.subscribe(subject, key);

}

const subSubject = Subject.of(cache);

if (Subject.is(subSubject)) {

subSubject.setParent(subject, key);

}

return cache;

},

set(value) {

cache = value;

subject.notify(key);

}

});

}

这一部分展示了如何使用

Object.defineProperty 进行属性劫持。当设置属性时,会调用 set(value),设置新的值,然后调用 subject 的 notify 方法。这里并不进行任何检查,只要设置了属性就会调用,即使属性的新值和旧值一样。notify 会通知所有的观察者。

第七部分

劫持数组方法。const ObservedMethods = {

PUSH: 'push',

POP: 'pop',

UNSHIFT: 'unshift',

SHIFT: 'shift',

SPLICE: 'splice',

REVERSE: 'reverse'

};

const OBSERVED_METHODS =

Object.keys(ObservedMethods).map(

key => ObservedMethods[key]

);

ObservedMethods 定义了需要劫持的数组函数。前面大写的用来做 key,后面小写的是需要劫持的方法。function hijackArray(target) {

OBSERVED_METHODS.forEach(key => {

const originalMethod = target[key];

defineProp(target, key, function() {

const args = Array.prototype.slice.call(arguments);

originalMethod.apply(this, args);

let inserted;

if (ObservedMethods.PUSH === key || ObservedMethods.UNSHIFT === key) {

inserted = args;

} else if (ObservedMethods.SPLICE===key) {

inserted = args.slice(2);

}

if (inserted && inserted.length) {

inserted.forEach(Subject.of);

}

const subject = target[SYMBOL_OBSERVABLE];

if (subject) {

subject.notifyParent();

}

});

});

}

数组的劫持和对象不同,不能使用

Object.defineProperty。我们需要劫持 6 个数组方法。分别是头部添加、头部删除、尾部添加、尾部删除、替换/删除某几项、数组反转。

通过重写数组方法实现了数组的劫持。但是这里有一个需要注意的地方,数据的每一个元素都是被观察过的,但是当在数组中添加了新元素时,这些元素还没有被观察。因此代码中还需要判断当前的方法如果是 push、unshift、splice,那么需要将新的元素放入观察者队列中。

另外两个文件分别是单元测试和性能分析,这里就不再分析了。

整体而言,比我预想的要好一些。

想了解更多内容,请访问:

51CTO和华为官方战略合作共建的鸿蒙技术社区

https://harmonyos.51cto.com?jssq

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值