最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vue 源码解析 (二)initProxy 初始化代理

    正文概述 掘金(公众号_人生代码)   2021-05-03   458

    Vue 源码解析 (二)initProxy 初始化代理

    在 src/core/instance/proxy.js 找到源码

    makeMap,allowedGlobals

    我们先来看看 makeMap 这个方法,做了什么处理:

    /*makeMap函数, str参数是接受的字符串, expectsLowerCase参数是否需要小写*/
     function makeMap(str, expectsLowerCase ) {
      /* 创建一个对象 */
      var map = Object.create(null);
      /*将字符串分割成数组*/
      var list = str.split(',');
      /*对数组进行遍历*/
      for (var i = 0; i < list.length; i++) {
         /*将每个key对应的值设置为true*/
         map[list[i]] = true;
      }
      /*最终返回, 根据参数设置是否是需要转换大小写*/
      return expectsLowerCase
           ? function (val) {
              return map[val.toLowerCase()];
           }
           : function (val) {
              return map[val];
           }
    }
    

    然后给一些 js 内置的全局方法做了相应的处理:

    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
    );
    

    makeMap 函数的只要作用把这些全局的API转成以下的形式,

    {
        Infinity:true,
        undefined:true
    }
    

    isNative

    可以学习一下源码是如何检测是不是支持原生方法

    export function isNative (Ctor: any): boolean {
      return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
    }
    

    warnNonPresent

    这个方法的意思是不存在,未定义的属性,方法被使用给出警告,我们来看看例子:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <script src="../vue.js"></script>
        <div id="app">
            <p>
                {{msg}}
            </p>
        </div>
        <script>
            const vm = new Vue({
                el: '#app',
            })
            console.log(vm)
        </script>
    </body>
    
    </html>
    

    上面例子直接在魔板中使用 msg 变量,但是他没有在 data 中定义,此时 warnNonPresent 会处理抛出警告如图所示

    warnReservedPrefix

    源码如下:

    const warnReservedPrefix = (target, key) => {
        warn(
          `Property "${key}" must be accessed with "$data.${key}" because ` +
          'properties starting with "$" or "_" are not proxied in the Vue instance to ' +
          'prevent conflicts with Vue internals. ' +
          'See: https://vuejs.org/v2/api/#data',
          target
        )
      }
    

    用于检测属性 key 的声明方法,是否是 $ 或者 _ 开头的,如果是,会给出警告,拿个简单的例子来看下效果:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <script src="../vue.js"></script>
        <div id="app">
            <p>
                {{$hhh}}
                {{_dddd}}
            </p>
        </div>
        <script>
            const vm = new Vue({
                el: '#app',
                data() {
                    return {
                        $hhh: 'ddd',
                        _dddd: 'ffff'
                    }
                },
            })
            console.log(vm)
        </script>
    </body>
    
    </html>
    

    hasHandler

    var hasHandler = {
        /*target要代理的对象, key在外部操作时访问的属性*/
        has: function has(target, key) {
            /*key in target返回true或者false*/
            var has = key in target;
            /*在模板引擎里面,有一些属性vm没有进行代理, 但是也能使用, 像Number,Object等*/
            var isAllowed = allowedGlobals(key) ||
                (typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data));
            /*在上面的has和isAllowed为false的情况下*/
            if (!has && !isAllowed) {
                if (key in target.$data) {
                    warnReservedPrefix(target, key);
                }
                /*warnNonPresent函数, 当访问属性,没有存在vm实例上, 会报错提示*/
                else {
                    warnNonPresent(target, key);
                }
            }
            /*has或者isAllowed*/
            return has || !isAllowed
        }
    };
    

    hasHandler 只配置了 has 钩子 ,当进行propKey in proxy in 操作符 或者 with() 操作时, 会触发 has钩子函数

    hasHandler在查找key时,从三个方向进行查找

    • 代理的 target 对象 通过 in 操作符
    • 全局对象API allowedGlobals 函数
    • 查找是否是渲染函数的内置方法 第一个字符以_开始 typeof key === 'string' && key.charAt(0) === '_'

    hasHandler, 首先去检测 vm 实例上是否有该属性, 下面的代码是vm实例上可以查看到test

    new Vue({
       el:"#app",
       template:"<div>{{test}}</div>",
       data:{
           test
       }
    })
    

    如果在 vm 实例上没有找到, 然后再去判断下是否是一些全局的对象, 例如 Number 等, Number是语言所提供的 在模板中也可以使用

    new Vue({
       el:"#app",
       /*Number属于语言提供的全局API*/
       template:"<div> {{ Number(test) +1 }}</div>",
       data:{
           test
       }
    })
    

    getHandler

    const getHandler = {
        get(target, key) {
          if (typeof key === 'string' && !(key in target)) {
            // 检测 data 是属性 key 是不是 $,_ 开头
            if (key in target.$data) warnReservedPrefix(target, key)
            else warnNonPresent(target, key)
          }
          return target[key]
        }
    }
    

    initProxy

    initProxy = function initProxy(vm) {
    /*hasProxy 判断当前环境是否支持es 提供的 Proxy*/
    if (hasProxy) {
       // determine which proxy handler to use
       var options = vm.$options;
       /*不同条件返回不同的handlers, getHandler或者hasHandler */
       var handlers = options.render && options.render._withStripped
           ? getHandler
           : hasHandler;
       /* 代理vm实例 */
       vm._renderProxy = new Proxy(vm, handlers);
    } else {
       vm._renderProxy = vm;
        }
    };
    

    起源地下载网 » Vue 源码解析 (二)initProxy 初始化代理

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元