typescript 中的 Mvvm 框架底层原理

需要的基础知识

需要了解一些底层的知识才能往下走哦,请前往另一个博客

基本思想

对象 Object
对于 object ,就是改变这个对象的属性,通过重写这个属性的 get 和 set
就可以在 set 里面进行需要的操作
当一个属性被赋值时,我们在 set 的时候去做一些其他的操作
比如发送某一个事件,告诉外部这个变量发生了改变,这个就是 Mvvm 框架所使用的
数组 Array
对于数组,我们需要对数组里面的对象监听变化,即遍历数组,并使用上面的方法
而数组整个的变化,我们也需要监听
比如数组的 push() , pop() 这种会改变数组内容的重要方法
我们也必须通知到位,跟劫持对象的属性一样
劫持对象的属性用 get 和 set 
对于数组我们就重写他的方法即可

实现 JsonOb


/**
 * 实现动态绑定的核心部分,
 * 每次修改属性值,都会调用对应函数,并且获取值的路径
 */

const OP = Object.prototype;
const types = {
   
    obj: '[object Object]',
    array: '[object Array]'
}
const OAM = ['push', 'pop', 'shift', 'unshift', 'sort', 'reverse', 'splice'];




/**
 * 实现属性拦截的类
 */
export class JsonOb<T> {
   
    constructor(obj:T, callback: (newVal: any, oldVal: any, pathArray: string[]) => void) {
   
        if (OP.toString.call(obj) !== types.obj && OP.toString.call(obj) !== types.array) {
   
            console.error('请传入一个对象或数组');
        }
        this._callback = callback;
        this.observe(obj);
    }

    private _callback;
    /**对象属性劫持 */
    private observe<T>(obj: T, path?) {
   

        if (OP.toString.call(obj) === types.array) {
   
            this.overrideArrayProto(obj, path);
        }

        Object.keys(obj).forEach((key) => {
   
            let self = this;
            let oldVal = obj[key];
            let pathArray = path && path.slice();
            if (pathArray) {
   
                pathArray.push(key);
            }
            else {
   
                pathArray = [key];
            }
            Object.defineProperty(obj, key, {
   
                get: function () {
   
                    return oldVal;
                },
                set: function (newVal) {
   
                    //cc.log(newVal);
                    if (oldVal !== newVal) {
   
                        if (OP.toString.call(newVal) === '[object Object]') {
   
                            self.observe(newVal, pathArray);
                        }
                        self._callback(newVal, oldVal, pathArray)
                        oldVal = newVal
                    }
                }
            })

            if (OP.toString.call(obj[key]) === types.obj || OP.toString.call(obj[key]) === types.array) {
   
                this.observe(obj[key], pathArray)
            }

        }, this)
    }

    /**
     * 对数组类型进行动态绑定
     * @param array 
     * @param path 
     */
    private overrideArrayProto(array: any, path)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值