- 组件有一个render函数,返回组建的虚拟DOM
```javascript
//组件
const MyComponent = {
name: “MyCOmponent”,
render() {
return {
} }, } //组件类型的虚拟节点 const componentNode = { type: MyComponent, }type: "div",
children: "我是组件",
//挂载组件节点 function mountComponent(vnode, container, anchor) { //通过vnode获取组件选项 即vnode.type const componentOption = vnode.type //获取render函数 const { render } = componentOption //获取要渲染的节点,即render函数返回值 const subTree = render() //挂载节点 patch(null, subTree, container, anchor) }
组件响应式更新
```javascript
const { reactive, effect } = Vue
//挂载组件节点
function mountComponent(vnode, container, anchor) {
//通过vnode获取组件选项 即vnode.type
const componentOption = vnode.type
//获取render函数
const { render, data } = componentOption
//响应式数据
const state = reactive(data())
//响应式组件更新
effect(() => {
//获取要渲染的节点,即render函数返回值
const subTree = render.call(state, state)
//挂载节点
patch(null, subTree, container, anchor)
})
}
上面的代码只能实现组件挂载,没有组件更新
定义组件实例用于组件更新,和组件生命周期
function mountComponent(vnode, container, anchor) {
//通过vnode获取组件选项 即vnode.type
const componentOption = vnode.type
//获取render函数
const { render, data, beforeCreate, created, beforeMount, mounted } =
componentOption
beforeCreate && beforeCreate()
//响应式数据
const state = reactive(data())
//定义组件实例
const instance = {
state, //组件状态
isMounted: false, //组件是否已经挂载
subTree: null, //组件的虚拟DOM
}
vnode.component = instance
created && created().call(state)
//响应式组件更新
watchEffect(() => {
const instance = vnode.component
//获取要渲染的节点,即render函数返回值
const subTree = render.call(state, state)
//初次挂载
if (!instance.isMounted) {
//挂载节点
beforeCreate && beforeCreate.call(state)
patch(null, subTree, container, anchor)
instance.isMounted = true
//加载完成 mounted时事件周期
mounted && mounted.call(state)
} else {
//更新节点
patch(instance.subTree, subTree, container, anchor)
}
instance.subTree = subTree
})
}