作用:主要作用是在实例上挂载一个 _renderProxy 指向 vm 实例自身, 这个代理的作用就是为了在开发阶段给我们一个友好而准确的提示
条件:当且仅当当前环境属于 非生产环境 并且支持 Proxy 的时候 拿取实例中不存在的值的时候会报错
场景:主要的使用场景是在 render 的时候会通过 _renderProxy 来获取实例中的内容,在上述条件中,如果获取的是不存在或者保留字符则会报错。
// core/isntance/init.jsif (process.env.NODE_ENV !== 'production') {initProxy(vm)} else {vm._renderProxy = vm}
let initProxyif (process.env.NODE_ENV !== 'production') {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)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://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.',target)}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)}const hasProxy =typeof Proxy !== 'undefined' && isNative(Proxy)if (hasProxy) {const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact')config.keyCodes = new Proxy(config.keyCodes, {set (target, key, value) {if (isBuiltInModifier(key)) {warn(`Avoid overwriting built-in modifier in config.keyCodes: .${key}`)return false} else {target[key] = valuereturn true}}})}const hasHandler = {has (target, key) {const has = key in targetconst 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}}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]}}initProxy = function initProxy (vm) {if (hasProxy) {// determine which proxy handler to useconst options = vm.$options// options.render._withStripped 一般只有在测试的时候为 true,这也就一意味着,通常而言都是范式 hasHandlerconst handlers = options.render && options.render._withStripped? getHandler: hasHandlervm._renderProxy = new Proxy(vm, handlers)} else {vm._renderProxy = vm}}}
