这篇文章主要介绍了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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。