实现mobx

思路

1.通过autoRun触发get拦截。
2.通过get注册target,key和autoRun的一一对应关系。
3.通过set去更新属性,执行autoRun。

Mobx.js

let proxies = new WeakMap();
let observers = new WeakMap();
let currentObserver = null;

const isObserver = (obj)  => {
    return obj === proxies.get(obj);
}

const toObserver = (obj ,_fun) =>{
    return new Proxy(obj,{
        get (target,key,receiver) {
            console.log('获取值');
            // 判断代理是否存在
            const targetProxy = proxies.get(target);
            const observer =  observers.get(target)
            const autoFunSet = observer && observer.get(key);
            if(currentObserver && targetProxy && !autoFunSet){
                observer.set(key, new Set().add(currentObserver));
            }

            if(currentObserver && targetProxy && autoFunSet){
                autoFunSet.add(currentObserver);
            }
            // 看看 这个target -> key - currentFunc是否是一一对应关系,如果不是,则添加,如果是这不作为。
            return Reflect.get(target,key,receiver);
        },
        set (target,key,value,receiver) {
            console.log('设置值');
            // 查看这个target ,key 是否是代理,如果是则找其相关的对应关系,执行对应关系,不是则直接返回值
            const targetProxy = proxies.get(target);
            const observer = observers.get(target);
            const autoFunSet = observer && observer.get(key);

            if(typeof target !== 'object' && !targetProxy){
                return Reflect.set(target,key,value,receiver);
            }

            if(targetProxy && observer && autoFunSet){
                const autos = observer.get(key);
                for ( let _func of [...autos]){
                    _func();
                }
            }
            return Reflect.set(target,key,value,receiver);
        }
    })
}

const registerObserver = (target,key) => {
    observers.set(target,new Map(key,this.currentObserver));
}

const autoRun = (_fun) => {
    console.log('autoRun')
    currentObserver = _fun;
    if(typeof _fun === 'function'){
        _fun();
    }
    currentObserver = null;
}

const observable = (obj) => {
    const proxy = proxies.get(obj);
    if(proxy){
        return proxy;
    }
    const observer = toObserver(obj);
    proxies.set(obj,observer);
    observers.set(obj,new Map());
    return  observer;
}

test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            width: 500px;
            height: 500px;
            margin: auto;
        }
    </style>
</head>
<body>
    <p>
        颜色:<input id="input"/>
    </p>
    <p>
        文案:<input id="text"/>
    </p>
    <ul id="list"></ul>
    <script type="text/javascript" src="./Mobx.js"></script>
    <script>
        const input = document.querySelector('#input');
        const text = document.querySelector('#text');
        const list = document.querySelector('#list');

        const obj = observable({
            text:'hehe',
            color:'red'
        });
        
        input.oninput = (e) => {
            const value = e.target.value;
            console.log(value)
            obj.color = value;
        }

        text.onblur = (e) => {
            const value = e.target.value;
            console.log(value)
            obj.text = value;
        }

        autoRun(() =>{
            input.style.color = obj.color;
        });

        autoRun(() =>{
            let li = document.createElement('li');
            li.innerText = obj.text;
            list.appendChild(li);
        })
        console.log(obj.a,input);
    </script>
</body>
</html>
posted @ 2020-10-31 23:48  胡姐姐  阅读(140)  评论(0编辑  收藏  举报