<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 10063字,需瀏覽 21分鐘

           ·

          2021-05-04 22:53

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

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

          makeMap,allowedGlobals

          我們先來(lái)看看 makeMap 這個(gè)方法,做了什么處理:

          /*makeMap函數(shù), str參數(shù)是接受的字符串, expectsLowerCase參數(shù)是否需要小寫(xiě)*/
           function makeMap(str, expectsLowerCase {
            /* 創(chuàng)建一個(gè)對(duì)象 */
            var map = Object.create(null);
            /*將字符串分割成數(shù)組*/
            var list = str.split(',');
            /*對(duì)數(shù)組進(jìn)行遍歷*/
            for (var i = 0; i < list.length; i++) {
               /*將每個(gè)key對(duì)應(yīng)的值設(shè)置為true*/
               map[list[i]] = true;
            }
            /*最終返回, 根據(jù)參數(shù)設(shè)置是否是需要轉(zhuǎn)換大小寫(xiě)*/
            return expectsLowerCase
                 ? function (val{
                    return map[val.toLowerCase()];
                 }
                 : function (val{
                    return map[val];
                 }
          }

          然后給一些 js 內(nèi)置的全局方法做了相應(yīng)的處理:

          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 函數(shù)的只要作用把這些全局的API轉(zhuǎn)成以下的形式,

          {
              Infinity:true,
              undefined:true
          }

          isNative

          可以學(xué)習(xí)一下源碼是如何檢測(cè)是不是支持原生方法

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

          warnNonPresent

          這個(gè)方法的意思是不存在,未定義的屬性,方法被使用給出警告,我們來(lái)看看例子:

          <!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 變量,但是他沒(méi)有在 data 中定義,此時(shí) warnNonPresent 會(huì)處理拋出警告如圖所示

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

          用于檢測(cè)屬性 key 的聲明方法,是否是 $ 或者 _ 開(kāi)頭的,如果是,會(huì)給出警告,拿個(gè)簡(jiǎn)單的例子來(lái)看下效果:

          <!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要代理的對(duì)象, key在外部操作時(shí)訪問(wèn)的屬性*/
              hasfunction has(target, key{
                  /*key in target返回true或者false*/
                  var has = key in target;
                  /*在模板引擎里面,有一些屬性vm沒(méi)有進(jìn)行代理, 但是也能使用, 像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函數(shù), 當(dāng)訪問(wèn)屬性,沒(méi)有存在vm實(shí)例上, 會(huì)報(bào)錯(cuò)提示*/
                      else {
                          warnNonPresent(target, key);
                      }
                  }
                  /*has或者isAllowed*/
                  return has || !isAllowed
              }
          };

          hasHandler 只配置了 has 鉤子 ,當(dāng)進(jìn)行propKey in proxy in 操作符 或者 with() 操作時(shí), 會(huì)觸發(fā) has鉤子函數(shù)

          hasHandler在查找key時(shí),從三個(gè)方向進(jìn)行查找

          • 代理的 target 對(duì)象 通過(guò) in 操作符
          • 全局對(duì)象API allowedGlobals 函數(shù)
          • 查找是否是渲染函數(shù)的內(nèi)置方法 第一個(gè)字符以_開(kāi)始 typeof key === 'string' && key.charAt(0) === '_'

          hasHandler, 首先去檢測(cè) vm 實(shí)例上是否有該屬性, 下面的代碼是vm實(shí)例上可以查看到test

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

          如果在 vm 實(shí)例上沒(méi)有找到, 然后再去判斷下是否是一些全局的對(duì)象, 例如 Number 等, Number是語(yǔ)言所提供的 在模板中也可以使用

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

          getHandler

          const getHandler = {
              get(target, key) {
                if (typeof key === 'string' && !(key in target)) {
                  // 檢測(cè) data 是屬性 key 是不是 $,_ 開(kāi)頭
                  if (key in target.$data) warnReservedPrefix(target, key)
                  else warnNonPresent(target, key)
                }
                return target[key]
              }
          }

          initProxy

          initProxy = function initProxy(vm{
          /*hasProxy 判斷當(dāng)前環(huán)境是否支持es 提供的 Proxy*/
          if (hasProxy) {
             // determine which proxy handler to use
             var options = vm.$options;
             /*不同條件返回不同的handlers, getHandler或者h(yuǎn)asHandler */
             var handlers = options.render && options.render._withStripped
                 ? getHandler
                 : hasHandler;
             /* 代理vm實(shí)例 */
             vm._renderProxy = new Proxy(vm, handlers);
          else {
             vm._renderProxy = vm;
              }
          };


          瀏覽 69
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  97黑人强奸韩日制服丝袜免费视频 | 色天天伊人 | 性久久久久| 夜夜做夜夜爽 | 国产一级电影 |