Open ly2011 opened 5 years ago
vue源码探索的一些疑惑
父组件的初次render会将子组件的vnode存于父组件的vnode的children中,父组件mount之前会做一次初始化patch,patch完会根据vnode创建dom元素,但在创建完,插入dom前会先创建子组件的vue实例和dom元素,并且插入到父组件的dom中去,然后再将父组件插入到浏览器dom中,所以在所有子组件mount之后,父组件才会mount
<!-- 父组件中 --> <child @custom-event="handler" /> <!-- 子组件中 --> this.$emit('custom-event', params)
父组件初次render生成vnode时,会将监听在子组件上的事件(event和handler)挂到到子组件vnode的 componentOptions.listeners 中,在创建或更新子组件的时候将其挂到自身的 $options._parentListeners,然后子组件将这些事件挂在自身的 _events 下,每次$emit就会触发 _events 里的相应的事件,_events 就相当于自身的一个事件池,$on,$off,$emit都会在事件池中触发相应操作
componentOptions.listeners
$options._parentListeners
_events
<!-- 父组件中 --> <child @hook:mounted="handler" />
待验证,因为看到子组件的vue实例的$options感觉像是在父组件中的解析的结果,而$options.proto才是子组件本身的options
vm._renderProxy
options.render._withStripped
https://github.com/vuejs/vue/blob/dev/src/core/instance/proxy.js#L69
vue的render的作用域是vm._renderProxy,在本地开发时候,vue对于template里用到的但是没有在data里定义的数据进行提示,这时候就有了Proxy的has和get拦截。
对于非SFC,使用el或者templete来创建组件的方式,vue会解析template生成render,形如
vm.$options.render = function () { with (this) { return _c(/*...*/) } }
而使用webpack和vue-loader时,对于SFC,vuejs@component-compiler-utils将template编译成严格模式下不包含with的代码,并为编译后的render设置render._withStripped = true,这时候render会变成下面这样
var render = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _vm._m(0) }
模板内的变量都是通过属性访问操作_vm._m的形式访问的,Proxy的has是拦截不到属性访问的,所以用了get来拦截
这样以后自定义render也可以有警告提示了
const render = function (h) { return h('div', [this.a]) } render._withStripped = true var vm = new Vue({ el: '#app', render, data: { test: 1 } })
1. 父组件create => 子组件create => 子组件mounted => 父组件mounted?
父组件的初次render会将子组件的vnode存于父组件的vnode的children中,父组件mount之前会做一次初始化patch,patch完会根据vnode创建dom元素,但在创建完,插入dom前会先创建子组件的vue实例和dom元素,并且插入到父组件的dom中去,然后再将父组件插入到浏览器dom中,所以在所有子组件mount之后,父组件才会mount
2. 为啥子组件的emit能触发父组件在该子组件上的监听事件?
父组件初次render生成vnode时,会将监听在子组件上的事件(event和handler)挂到到子组件vnode的
componentOptions.listeners
中,在创建或更新子组件的时候将其挂到自身的$options._parentListeners
,然后子组件将这些事件挂在自身的_events
下,每次$emit就会触发_events
里的相应的事件,_events
就相当于自身的一个事件池,$on,$off,$emit都会在事件池中触发相应操作3. 父组件如何监听子组件的生命周期事件?
4. 子组件的解析分两部分,一部分是在父组件render的时候解析,一种是自己render的时候解析?
待验证,因为看到子组件的vue实例的$options感觉像是在父组件中的解析的结果,而$options.proto才是子组件本身的options
vm._renderProxy
设置代理时候为啥要判断options.render._withStripped
?vue的render的作用域是vm._renderProxy,在本地开发时候,vue对于template里用到的但是没有在data里定义的数据进行提示,这时候就有了Proxy的has和get拦截。
对于非SFC,使用el或者templete来创建组件的方式,vue会解析template生成render,形如
而使用webpack和vue-loader时,对于SFC,vuejs@component-compiler-utils将template编译成严格模式下不包含with的代码,并为编译后的render设置render._withStripped = true,这时候render会变成下面这样
模板内的变量都是通过属性访问操作_vm._m的形式访问的,Proxy的has是拦截不到属性访问的,所以用了get来拦截
这样以后自定义render也可以有警告提示了