這篇文章主要介紹了Vue初始化為渲染函數怎么設置的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Vue初始化為渲染函數怎么設置文章都會有所收獲,下面我們一起來看看吧。
Vue實例化時_init
方法做了很多處理,其中就有這么一段:
if (__DEV__) { initProxy(vm) } else { vm._renderProxy = vm }
在生產模式下,_renderProxy
直接指向了Vue實例本身,而在開發環境下調用了initProxy
方法,那么它究竟是做什么的呢?
通過對_renderProxy進行全局搜索,我們在src\core\instance\render.ts
文件中找到了它:
// 源碼文件 src\core\instance\render.ts vnode = render.call(vm._renderProxy, vm.$createElement)
也就是說,_renderProxy
是渲染函數render
的執行上下文,在生產環境下,執行上下文就是實例本身,而在開發環境下,執行上下文則使用initProxy
進行了處理,我們接下來看看它究竟做了什么。
首先判斷了當前環境下Proxy
對象是否存在進行了判斷:
//源碼文件 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
對象存在,則進一步去$options
里獲取_withStripped
屬性,如果_withStripped
存在,則使用getHandler
方法來代理Vue實例,如果不存在,就使用hasHandler
來代理實例。
關于Proxy
對象的用法,我在這篇文章里提過,簡單來說,它可以為一個對象設定代理,用以攔截對象的各種方法。
那么,我們進一步看一下,hasHandler
和getHandler
都做了什么,首先是比較簡單的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
,也就是說,當獲取實例的屬性時,就會觸發這個方法,在這個方法中,對屬性值是否在實例中以及是否在實例的$data
中進行了檢查,如果不存在則發出相應的警告:
// 源碼文件: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
操作符進行攔截,也就是攔截以下操作:
屬性查詢: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 } }
類似的,依然是對屬性是否在實例中存在進行了檢查,但是多了一步判斷,也就是allowedGlobals
,它實際上是一個全局方法列表,當模板中出現了里面的方法名后,不會進行下一個步驟的判斷,也就不會因為在Vue實例和$options
中找不到這個名字的屬性而彈出報錯,這些方法你在開發過程中肯定都用過:
// 源碼文件: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 )
關于“Vue初始化為渲染函數怎么設置”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Vue初始化為渲染函數怎么設置”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。