美文网首页
ES6 Proxy实现

ES6 Proxy实现

作者: 龚达耶 | 来源:发表于2020-07-09 00:31 被阅读0次

    Proxy作为库的设计者和框架设计者专用的功能 用于修改某些操作的默认行为,等同于在语言层面做出修改。

    Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

    Proxy有两个参数一个是原始的对象 一个是用来定制拦截的行为

    A Proxy is created with two parameters:

    target: the original object which you want to proxy

    handler: an object that defines which operations will be intercepted and how to redefine intercepted operations.

    我们看Proxy现在支持已经很成熟了

    image.png
    <script>
    const handler = {
        get: function(obj, prop) {
            return prop in obj ? obj[prop] : 37;
        }
    };
    
    const p = new Proxy({}, handler);
    p.a = 1;
    p.b = undefined;
    
    console.log(p); 
    </script>
    
    image.png

    当然我们也可以使用set和get来validate我们可以在set里面做一些判断

    <script>
        let object = {
            a: 1,
            b: 2
        }
        let handlers = []
        function reactive(obj) {
            return new Proxy(obj, {
                get(obj, prop) {
                    console.log(obj, prop)
                    return obj[prop]
                },
                set(obj, prop, val) {
                    console.log(obj, prop, val)
                    obj[prop] = val
                    for (let handler of handlers)
                        handler()
                    return obj[prop]
                }
            })
        }
    
        function effect(handler) {
            handler()
            handlers.push(handler)
        }
        let dummy;
        let proxy = reactive(object)
    
        effect(() => dummy = proxy.a)
        console.log(dummy)
        proxy.a = 111
        console.log(dummy)
    </script>
    

    最终我们来实现双向数据绑定

    <input id="test">
    <script>
    let object = {
        a: {x:1},
        b: 2
    }
    let handlers = new Map()
    let usedReactivities = []
    let reactivites = new Map()
    function reactive(obj) {
      if(reactivites.has(obj)){
        return reactivites.get(obj)
      }
        return new Proxy(obj, {
            get(obj, prop) {
                console.log(obj, prop)
                usedReactivities.push([obj,prop])
                if(typeof obj[prop] === 'object'){
                  return reactive(obj[prop])
                }
                return obj[prop]
            },
            set(obj, prop, val) {
                obj[prop] = val
               console.log(handlers)
                console.log(obj, prop, val)
                if( handlers.get(obj)){
                  if( handlers.get(obj).get(prop)){
                    for(let handler of handlers.get(obj).get(prop)){
                      handler()
                    }
                  }
                }
                return obj[prop]
            }
        })
        reactivites.set(obj, proxy)
        reactivites.set(proxy, proxy)
        return proxy
    }
    let proxy = reactive(object)
    
    function effective(handler) {
      usedReactivities=[]
        handler()
        console.log(usedReactivities)
        for (let usedReactivity of usedReactivities){
          let [obj, prop] = usedReactivity
          console.log([obj, prop])
          if(!handlers.has(obj)){
            handlers.set(obj, new Map())
          }
          if(!handlers.get(obj).has(prop)){
            handlers.get(obj).set(prop, [])
          }
          handlers.get(obj).get(prop).push(handler)
        }
    }
    
    let p = reactive({r:100})
    effective(()=>{
      document.getElementById("test").value= p.r
    })
    
    document.getElementById("test").addEventListener("input", e=>{
      p.r = e.target.value
    })
    
    </script>
    

    相关文章

      网友评论

          本文标题:ES6 Proxy实现

          本文链接:https://www.haomeiwen.com/subject/nfhlcktx.html