VUE props 實現(xiàn)原理(源碼解析)
前言
我們在使用組件的時候拟枚,都會給組件傳入一些屬性傻粘,但是在使用時瀑志,卻只是關注了它傳遞數(shù)據(jù)的功能,沒有想過它是怎樣的一個原理,具體是怎么實現(xiàn)的井厌。
其實我們平時寫出來的組件港柜,本質(zhì)上就是一個template
模板氯夷,而這個template
模板在vue
中枚粘,會通過render
函數(shù)解析庄涡,最終生成一個VNode
默色。那我們通過源碼來看一下在生成VNode
后,組件屬性是怎樣實現(xiàn)傳遞的。
源碼解析
生成虛擬節(jié)點源碼
在生成虛擬節(jié)點這法精,我們可以看到這樣一段代碼如迟,而這段代碼中摘符,propsData
則是所有屬性的一個定義带族,而這個對象的放在了虛擬節(jié)點上蝙砌,那我們可以看看組件初始化時祠饺,這個propsData
對象經(jīng)歷了怎么的操作。
const vnode = new VNode(
`vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
data, undefined, undefined, undefined, context,
{ Ctor, propsData, listeners, tag, children },
asyncFactory
)
組件初始化源碼
在下段代碼中,我們可以看到propsData
對象是被賦值到了當前實例上的$options
的propsData
屬性中懊渡,那我們可以看一下初始化props
時肾档,這個propsData
對象又經(jīng)過了怎樣的一個過程酣溃。
const opts = vm.$options = Object.create(vm.constructor.options)黔姜、
const parentVnode = options._parentVnode
opts._parentVnode = parentVnode
const vnodeComponentOptions = parentVnode.componentOptions
opts.propsData = vnodeComponentOptions.propsData
初始化props
源碼
在這里,從$options
拿到$options
對象后蒂萎,聲明了一個叫_props
的空對象秆吵。
const propsData = vm.$options.propsData || {}
const props = vm._props = {}
下面通過vm.$parent
判斷一下是不是根元素,如果是根元素五慈,屬性則需要設置為響應式的纳寂,如果不是則不需要。
const isRoot = !vm.$parent
if (!isRoot) {//如果是根元素 屬性需要定義成響應式
toggleObserving(false)
}
循環(huán)用戶定義了的propsOptions
選項泻拦,它會根據(jù)用戶定義的對象來和用戶傳入的值通過validateProp
方法來進行一個校驗毙芜,并且拿到最終的結(jié)果value
。
然后將當前key和value值争拐,通過defineReactive
定義到我們前面的_props
中腋粥。
最終,將_props
對象定義到我們的實例上去架曹,這樣我們就可以通過實例隘冲,直接拿取到屬性了。
for (const key in propsOptions) {
keys.push(key) //校驗用戶定義的屬性和傳入的屬性
const value = validateProp(key, propsOptions, propsData, vm)
if (process.env.NODE_ENV !== 'production') {
} else {
defineReactive(props, key, value)
}
if (!(key in vm)) {
proxy(vm, `_props`, key)
}
}
總的來說绑雄,就是將父組件傳給它的屬性展辞,定義到了它自己的實例上了。