成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

人人都能懂的Vue源碼系列—07—initProxy

vspiders / 3480人閱讀

摘要:不同的代碼運(yùn)行環(huán)境賦值的結(jié)果不同。當(dāng)訪問的屬性不是類型或者屬性值在被代理的對象上不存在,則拋出錯(cuò)誤提示,否則就返回該屬性值。該方法可以在開發(fā)者錯(cuò)誤的調(diào)用屬性時(shí),提供提示作用。只不過目前規(guī)范還沒有很完善,使用的時(shí)候要稍加注意。

前幾篇文章中,我們主要講了merge options的一些操作。今天我們回到init方法往下講。

if (process.env.NODE_ENV !== "production") {
  initProxy(vm)
} else {
  vm._renderProxy = vm
}

上面的代碼邏輯很簡單,主要就是為Vue實(shí)例的_renderProxy屬性賦值。不同的代碼運(yùn)行環(huán)境賦值的結(jié)果不同。

當(dāng)前環(huán)境是開發(fā)環(huán)境,則調(diào)用initProxy方法

如果不是開發(fā)環(huán)境,則vue實(shí)例的_renderProxy屬性指向vue實(shí)例本身。

initProxy

接下來看initProxy方法究竟怎么樣代理vm屬性呢?

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

先來看hasProxy的代碼

  const hasProxy =
    typeof Proxy !== "undefined" &&
    Proxy.toString().match(/native code/)

從變量的名字我們知道它的作用就是判斷當(dāng)前環(huán)境中Proxy是否可用。同學(xué)們?nèi)绻皇煜roxy的用法,可以點(diǎn)擊這里。這個(gè)判斷方法在我們平時(shí)寫代碼中也可以進(jìn)行借鑒。
回到代碼中,如果當(dāng)前環(huán)境存在Proxy,則執(zhí)行塊內(nèi)的語句。

  const options = vm.$options
  const handlers = options.render && options.render._withStripped
    ? getHandler
    : hasHandler

上面兩行代碼的邏輯是,如果options上存在render屬性,且render屬性上存在_withStripped屬性,則proxy的traps(traps其實(shí)也就是自定義方法)采用getHandler方法,否則采用hasHandler方法。更多關(guān)于traps相關(guān)的內(nèi)容可點(diǎn)擊這里。
接下來看看getHandler和hasHandler方法

  const getHandler = {
    get (target, key) {
      if (typeof key === "string" && !(key in target)) {
        warnNonPresent(target, key)
      }
      return target[key]
    }
  }

getHandler方法主要是針對讀取代理對象的某個(gè)屬性時(shí)進(jìn)行的操作。當(dāng)訪問的屬性不是string類型或者屬性值在被代理的對象上不存在,則拋出錯(cuò)誤提示,否則就返回該屬性值。
該方法可以在開發(fā)者錯(cuò)誤的調(diào)用vm屬性時(shí),提供提示作用。

  const hasHandler = {
    has (target, key) {
      const has = key in target
      const isAllowed = allowedGlobals(key) || key.charAt(0) === "_"
      if (!has && !isAllowed) {
        warnNonPresent(target, key)
      }
      return has || !isAllowed
    }
  }

hasHandler方法的應(yīng)用場景在于查看vm實(shí)例是否擁有某個(gè)屬性。比如調(diào)用for in循環(huán)遍歷vm實(shí)例屬性時(shí),會(huì)觸發(fā)hasHandler方法。
首先使用in操作符判斷該屬性是否在vm實(shí)例上存在。

const has = key in target

接下來通過下列語句,看屬性名稱是否可用?

const isAllowed = allowedGlobals(key) || key.charAt(0) === "_"

allowedGlobals的定義如下

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

我們結(jié)合makeMap函數(shù)一起來看

export function makeMap (
  str: string,
  expectsLowerCase?: boolean
): (key: string) => true | void {
  const map = Object.create(null)
  const list: Array = str.split(",")
  for (let i = 0; i < list.length; i++) {
    map[list[i]] = true
  }
  return expectsLowerCase
    ? val => map[val.toLowerCase()]
    : val => map[val]
}

先來分析makeMap,其作用是通過傳入的string參數(shù)來生成映射表。如傳入下列參數(shù)

"Infinity,undefined,NaN,isFinite,isNaN,"
....

通過makeMap方法可以生成下面這樣的一個(gè)映射表

{
  Infinity: true,
  undefined: true
  ......
}

這個(gè)方法非常有用,我們在日常寫代碼的時(shí)候也可以進(jìn)行借鑒。
回到hasHandler源碼中。allowedGlobals最終存儲(chǔ)的是一個(gè)代表特殊屬性名稱的映射表。
所以結(jié)合has和isAllowed屬性,我們知道當(dāng)讀取對象屬性時(shí),如果屬性名在vm上不存在,且不在特殊屬性名稱映射表中,或沒有以_符號開頭。則拋出異常。
最后回到initProxy代碼中

  if (hasProxy) {
      ...
      vm._renderProxy = new Proxy(vm, handlers)
    } else {
      vm._renderProxy = vm
    }
  }

如果Proxy屬性存在,則把包裝后的vm屬性賦值給_renderProxy屬性值。否則把vm是實(shí)例本身賦值給_renderProxy屬性

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

代理對象是es6的新特性,它主要用來自定義對象一些基本操作(如查找,賦值,枚舉等)。
我們上面講的這些代碼主要應(yīng)用了lookup和enumeration部分的自定義能力。proxy是一個(gè)強(qiáng)大的特性,為我們提供了很多"元編程"能力。只不過目前規(guī)范還沒有很完善,使用的時(shí)候要稍加注意。最后按照我們的老規(guī)矩,以一張圖完成今天的講解。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94916.html

相關(guān)文章

  • 人人都能懂的Vue源碼系列—02—Vue構(gòu)造函數(shù)

    摘要:果然我們找到了的構(gòu)造函數(shù)定義。告訴你是一個(gè)構(gòu)造函數(shù),需要用操作符去調(diào)用。在深入方法之前,我們先把目光移到文件里在的構(gòu)造函數(shù)定義之后,有一系列方法會(huì)被立即調(diào)用。下篇博文主要介紹相關(guān)的內(nèi)容,涉及到原型鏈和構(gòu)造函數(shù)以及部分的實(shí)現(xiàn),敬請期待 上篇博文中說到了Vue源碼的目錄結(jié)構(gòu)是什么樣的,每個(gè)目錄的作用我們應(yīng)該也有所了解。我們知道core/instance目錄主要是用來實(shí)例化Vue對象,所以我...

    X_AirDu 評論0 收藏0
  • 人人都能懂的Vue源碼系列—01—Vue源碼目錄結(jié)構(gòu)

    摘要:閱讀的源碼,或者說閱讀一個(gè)框架的源碼,了解它的目錄結(jié)構(gòu)都是很有幫助的。人人都能懂的源碼系列文章將會(huì)詳細(xì)的介紹源碼的方方面面。 閱讀Vue的源碼,或者說閱讀一個(gè)框架的源碼,了解它的目錄結(jié)構(gòu)都是很有幫助的。下面我們來看看Vue源碼的目錄結(jié)構(gòu)。showImg(https://segmentfault.com/img/bV8fLS?w=598&h=654); Vue各目錄簡介 下圖是Vue各個(gè)...

    MAX_zuo 評論0 收藏0
  • 人人都能懂的Vue源碼系列—08—initLifecycle

    摘要:主要是通過為我們屬性添加一些自定義的行為。方法用來初始化一些生命周期相關(guān)的屬性,以及為等屬性賦值,來看源碼。名稱說明指定已創(chuàng)建的實(shí)例之父實(shí)例,在兩者之間建立父子關(guān)系。一個(gè)對象,持有已注冊過的所有子組件。 上篇文章,我們講了vm._renderProxy相關(guān)的內(nèi)容。主要是通過Proxy為我們vm屬性添加一些自定義的行為。今天我們回到init方法中,為大家講解initLifecycle。i...

    Cristalven 評論0 收藏0
  • 人人都能懂的Vue源碼系列—04—resolveConstructorOptions函數(shù)-下

    摘要:上一篇文章中說道,函數(shù)要分兩種情況進(jìn)行說明,第一種是為基礎(chǔ)構(gòu)造器的情況,這個(gè)已經(jīng)向大家介紹過了,今天這篇文章主要介紹第二種情況,是創(chuàng)建的子類。表示的是當(dāng)前構(gòu)造器上新增的,表示的是當(dāng)前構(gòu)造器上新增的封裝。 上一篇文章中說道,resolveConstructorOptions函數(shù)要分兩種情況進(jìn)行說明,第一種是Ctor為基礎(chǔ)構(gòu)造器的情況,這個(gè)已經(jīng)向大家介紹過了,今天這篇文章主要介紹第二種情況...

    My_Oh_My 評論0 收藏0
  • 人人都能懂的Vue源碼系列—04—resolveConstructorOptions函數(shù)-下

    摘要:上一篇文章中說道,函數(shù)要分兩種情況進(jìn)行說明,第一種是為基礎(chǔ)構(gòu)造器的情況,這個(gè)已經(jīng)向大家介紹過了,今天這篇文章主要介紹第二種情況,是創(chuàng)建的子類。表示的是當(dāng)前構(gòu)造器上新增的,表示的是當(dāng)前構(gòu)造器上新增的封裝。 上一篇文章中說道,resolveConstructorOptions函數(shù)要分兩種情況進(jìn)行說明,第一種是Ctor為基礎(chǔ)構(gòu)造器的情況,這個(gè)已經(jīng)向大家介紹過了,今天這篇文章主要介紹第二種情況...

    BlackHole1 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<