欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue實例初始化為渲染函數(shù)設(shè)置檢查源碼剖析

 更新時間:2022年08月22日 16:08:51   作者:林語琛  
這篇文章主要為大家介紹了Vue實例初始化為渲染函數(shù)設(shè)置檢查源碼剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

之前的文章提到,Vue實例化時_init方法做了很多處理,其中就有這么一段:

if (__DEV__) {
  initProxy(vm)
} else {
  vm._renderProxy = vm
}

在生產(chǎn)模式下,_renderProxy直接指向了Vue實例本身,而在開發(fā)環(huán)境下調(diào)用了initProxy方法,那么它究竟是做什么的呢?

_renderProxy是干什么的

通過對_renderProxy進(jìn)行全局搜索,我們在src\core\instance\render.ts文件中找到了它:

// 源碼文件 src\core\instance\render.ts
vnode = render.call(vm._renderProxy, vm.$createElement)

也就是說,_renderProxy是渲染函數(shù)render的執(zhí)行上下文,在生產(chǎn)環(huán)境下,執(zhí)行上下文就是實例本身,而在開發(fā)環(huán)境下,執(zhí)行上下文則使用initProxy進(jìn)行了處理,我們接下來看看它究竟做了什么。

initProxy方法

首先判斷了當(dāng)前環(huán)境下Proxy對象是否存在進(jìn)行了判斷:

//源碼文件 src\core\instance\proxy.ts
const hasProxy = typeof Proxy !== 'undefined' && isNative(Proxy)
//...
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
  }
}

如果Proxy對象不存在,就放棄治療,上下文仍為原Vue實例。

而如果Proxy對象存在,則進(jìn)一步去$options里獲取_withStripped屬性,如果_withStripped存在,則使用getHandler方法來代理Vue實例,如果不存在,就使用hasHandler來代理實例。

關(guān)于Proxy對象的用法,我在這篇文章里提過,簡單來說,它可以為一個對象設(shè)定代理,用以攔截對象的各種方法。

那么,我們進(jìn)一步看一下,hasHandlergetHandler都做了什么,首先是比較簡單的getHandler:

// 源碼文件:src\core\instance\proxy.ts
const getHandler = {
  get(target, key) {
    if (typeof key === 'string' && !(key in target)) {
      if (key in target.$data) warnReservedPrefix(target, key)
      else warnNonPresent(target, key)
    }
    return target[key]
  }
}

這個方法攔截了Vue實例對象的getter,也就是說,當(dāng)獲取實例的屬性時,就會觸發(fā)這個方法,在這個方法中,對屬性值是否在實例中以及是否在實例的$data中進(jìn)行了檢查,如果不存在則發(fā)出相應(yīng)的警告:

// 源碼文件:src\core\instance\proxy.ts
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://v2.vuejs.org/v2/api/#data',
    target
  )
}
const warnNonPresent = (target, key) => {
  warn(
    `Property or method "${key}" is not defined on the instance but ` +
      'referenced during render. Make sure that this property is reactive, ' +
      'either in the data option, or for class-based components, by ' +
      'initializing the property. ' +
      'See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.',
    target
  )
}

hasHandler則是對實例對象的in操作符進(jìn)行攔截,也就是攔截以下操作:

  • 屬性查詢:foo in proxy
  • 繼承屬性查詢:foo in Object.create(proxy)
  • with 檢查: with(proxy) { (foo); }
  • Reflect.has()

那么做了什么呢:

// 源碼文件:src\core\instance\proxy.ts
const hasHandler = {
  has(target, key) {
    const has = key in target
    const isAllowed =
      allowedGlobals(key) ||
      (typeof key === 'string' &&
        key.charAt(0) === '_' &&
        !(key in target.$data))
    if (!has && !isAllowed) {
      if (key in target.$data) warnReservedPrefix(target, key)
      else warnNonPresent(target, key)
    }
    return has || !isAllowed
  }
}

類似的,依然是對屬性是否在實例中存在進(jìn)行了檢查,但是多了一步判斷,也就是allowedGlobals,它實際上是一個全局方法列表,當(dāng)模板中出現(xiàn)了里面的方法名后,不會進(jìn)行下一個步驟的判斷,也就不會因為在Vue實例和$options中找不到這個名字的屬性而彈出報錯,這些方法你在開發(fā)過程中肯定都用過:

// 源碼文件:src\core\instance\proxy.ts
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,BigInt,' +
    'require' // for Webpack/Browserify
)

總結(jié)

Vue實例化過程中,在開發(fā)環(huán)境下會調(diào)用initProxy方法來包裝render函數(shù)原本的執(zhí)行上下文(也就是Vue實例本身),在它的getterin操作符中加入一部分屬性的檢查,當(dāng)模板中調(diào)用的屬性不存在于實例中或不存在于$options中時,及時提出警告。

以上就是Vue實例初始化為渲染函數(shù)設(shè)置檢查源碼剖析的詳細(xì)內(nèi)容,更多關(guān)于Vue實例初始化渲染函數(shù)檢查的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解決vue無法加載文件D:\Program Files\nodejs\node_global\vue.ps1,因為在此系統(tǒng)上禁止運(yùn)行腳本

    解決vue無法加載文件D:\Program Files\nodejs\node_global\vue.ps1,

    這篇文章主要給大家介紹了關(guān)于解決vue無法加載文件D:\Program Files\nodejs\node_global\vue.ps1,因為在此系統(tǒng)上禁止運(yùn)行腳本的相關(guān)資料,這個報錯是由于在系統(tǒng)上禁止運(yùn)行腳本導(dǎo)致的,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • vue通過笛卡兒積實現(xiàn)sku庫存配置方式

    vue通過笛卡兒積實現(xiàn)sku庫存配置方式

    這篇文章主要介紹了vue通過笛卡兒積實現(xiàn)sku庫存配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • jdk1.8+vue elementui實現(xiàn)多級菜單功能

    jdk1.8+vue elementui實現(xiàn)多級菜單功能

    這篇文章主要介紹了jdk1.8+vue elementui實現(xiàn)多級菜單功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • vue-Router安裝過程及原理詳細(xì)

    vue-Router安裝過程及原理詳細(xì)

    路由是網(wǎng)絡(luò)工程里面的專業(yè)術(shù)語,就是通過互聯(lián)把信息從源地址傳輸?shù)侥康牡刂返幕顒印1举|(zhì)上就是一種對應(yīng)關(guān)系。分為前端路由和后端路由。小編將再下面文章為大家做詳細(xì)介紹,感興趣的小伙伴請和小編一起來學(xué)習(xí)吧
    2021-09-09
  • 使用vue的transition完成滑動過渡的示例代碼

    使用vue的transition完成滑動過渡的示例代碼

    這篇文章主要介紹了使用vue的transition完成滑動過渡的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • Vue3中Provide?/?Inject的實現(xiàn)原理分享

    Vue3中Provide?/?Inject的實現(xiàn)原理分享

    provide和inject主要為高階插件/組件庫提供用例,這篇文章主要給大家介紹了關(guān)于Vue3中Provide?/?Inject的實現(xiàn)原理,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-02-02
  • 解析Vue.js中的組件

    解析Vue.js中的組件

    組件(Component)是 Vue.js 最強(qiáng)大的功能之一。組件可以擴(kuò)展 HTML 元素,封裝可重用的代碼。這篇文章主要介紹了vue.js 中的組件,需要的朋友參考下
    2018-02-02
  • 關(guān)于vue設(shè)置環(huán)境變量全流程

    關(guān)于vue設(shè)置環(huán)境變量全流程

    這篇文章主要介紹了關(guān)于vue設(shè)置環(huán)境變量全流程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • vue項目中接入websocket時需要ip端口動態(tài)部署問題

    vue項目中接入websocket時需要ip端口動態(tài)部署問題

    這篇文章主要介紹了vue項目中接入websocket時需要ip端口動態(tài)部署問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Vue 同步異步存值取值實現(xiàn)案例

    Vue 同步異步存值取值實現(xiàn)案例

    這篇文章主要介紹了Vue 同步異步存值取值實現(xiàn)案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08

最新評論