从vue源码来看Proxy的用处

从vue源码来看Proxy的用处

The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).MDN Proxy

MDN表述该对象组织器是用于对某对象定义用户自定义行动的。那末,这究竟是什么意思呢?我们下面直接来剖析一下Vue源码中运用到Proxy对象的处所,来邃晓该对象组织器的作用。

Proxy在Vue中的运用

起首我们来看一看Vue源码的 1430行

/* not type checking this file because flow doesn't play well with Proxy */

  var initProxy;

  {
    var allowedGlobals = makeMap(
      'Infinity,undefined,NaN,isFinite,isNaN,' +
      'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
      'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
      'require' // for Webpack/Browserify
    );

    var warnNonPresent = function(target, key) {
      warn(
        "Property or method \"" + key + "\" is not defined on the instance but " +
        "referenced during render. Make sure to declare reactive data " +
        "properties in the data option.",
        target
      );
    };

    var hasProxy = typeof Proxy !== 'undefined' &&
    Proxy.toString().match(/native code/);

    if (hasProxy) {
      var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta');
      config.keyCodes = new Proxy(config.keyCodes, {
        set: function set(target, key, value) {
          if (isBuiltInModifier(key)) {
            warn(("Avoid overwriting built-in modifier in config.keyCodes: ." + key));
            return false
          } else {
            target[key] = value;
            return true
          }
        }
      });
    }

    var hasHandler = {
      has: function has(target, key) {
        var has = key in target;
        var isAllowed = allowedGlobals(key) || key.charAt(0) === '_';
        if (!has && !isAllowed) {
          warnNonPresent(target, key);
        }
        return has || !isAllowed
      }
    };

    var getHandler = {
      get: function get(target, key) {
        if (typeof key === 'string' && !(key in target)) {
          warnNonPresent(target, key);
        }
        return target[key]
      }
    };

    initProxy = function initProxy(vm) {
      if (hasProxy) {
        // determine which proxy handler to use
        var options = vm.$options;
        var handlers = options.render && options.render._withStripped
          ? getHandler
          : hasHandler;
        vm._renderProxy = new Proxy(vm, handlers);
      } else {
        vm._renderProxy = vm;
      }
    };
  }

起首,我们要邃晓一件事变,vue摒弃了对ie9以下的支撑。纵然如许,因为Proxy作为一个es6的新特征,支撑度依旧不高,作者也只是尝试着使用了一下。下面我们来一步一步解说。

源码解说

 var allowedGlobals = makeMap(
      'Infinity,undefined,NaN,isFinite,isNaN,' +
      'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
      'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
      'require' // for Webpack/Browserify
    );

该处定义了所许可的全局对象范例。

var warnNonPresent = function(target, key) {
      warn(
        "Property or method \"" + key + "\" is not defined on the instance but " +
        "referenced during render. Make sure to declare reactive data " +
        "properties in the data option.",
        target
      );
 };

该处定义了一个报警要领,传入键名或要领名,log显现一条正告

 var hasProxy = typeof Proxy !== 'undefined' &&
    Proxy.toString().match(/native code/);

该处是对es6特征Proxy的检测, 其检测手腕是确认Proxy是原生完成并未被用户代码所掩盖。

    var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta');
    config.keyCodes = new Proxy(config.keyCodes, {
        set: function set(target, key, value) {
          if (isBuiltInModifier(key)) {
            warn(("Avoid overwriting built-in modifier in config.keyCodes: ." + key));
            return false
          } else {
            target[key] = value;
            return true
          }
        }
      });

该段代码对config.keyCodes对象进行了代办,其意义在于制止用户修正Vue内建的一些按键值,这些按键值和按键名是对应的。假如用过Vue的用户应当晓得,Vue在事宜对象上对一些经常使用按键和经常使用操纵进行了内建(这个内建历程被用eval函数紧缩了,由一堆代码段组成的,没什么看头),作者一定不愿望也不许可用户修正设置的时刻掩盖了内建内容。因而,当我们做config.keyCodes[‘stop’] = xxx如许的操纵的时刻,Vue就会通知你说“你这个人,不忠实,为何想着改我东西”,直接打出制止改写内建设置的正告。假如非内建内容,那末能够直接设置上。

    initProxy = function initProxy(vm) {
      if (hasProxy) {
        // determine which proxy handler to use
        var options = vm.$options;
        var handlers = options.render && options.render._withStripped
          ? getHandler
          : hasHandler;
        vm._renderProxy = new Proxy(vm, handlers);
      } else {
        vm._renderProxy = vm;
      }
    };

这句话就不再诠释了,相似上面。不过读者可能会问has是什么? 那末下面我们来解说一下Proxy的各个参数

Proxy所需参数

两个, var b = new Proxy(a, { has: fn xxx, get: fn xxx, set: fn xxx …. })

target 被代办的对象

handler 处理器对象

用来定义我们对该对象的种种操纵

完全的handler处理器对象内容:

{
    get: '咋猎取',
    set: '咋设置',
    deleteProperty: '咋删除',
    enumerate: '咋罗列',
    ownKeys: '咋猎取一切该对象的属性键 ',
    has: '问你有无, 比方 "xxx" in target',
    defineProperty: '怎样defineProperty, 这个我们也是能够代办的',
    getOwnPropertyDescriptor: '猎取属性形貌的代办',
    getPrototypeOf: '找原型时刻的代办',
    setPrototypeOf: '设置对象原型的时刻的代办',
    isExtensible: '推断对象是不是可扩大的时刻的代办',
    preventExtensions: '设置阻挠对象扩大的时刻的代办',
    apply: '实行挪用操纵的时刻的代办',
    construct: '实行实例化的时刻的代办'
}

以上皆是函数~~

所以Proxy的作用是?

阻拦,预警,上报,扩大功用,统计,强化对象…能想得到的都能沾到点边,这里Vue的代码主要将代办运用于阻拦。而且因为范例依旧在生长,所以人人慎用。。。

材料

MDN js Proxy Object

MDN Proxy Handler

sec-proxy-object-internal-methods-and-internal-slots

    原文作者:有把但没什么卵用
    原文地址: https://segmentfault.com/a/1190000008303003
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞