- 组件有一个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) }
组件响应式更新```javascriptconst { reactive, effect } = Vue//挂载组件节点function mountComponent(vnode, container, anchor) {//通过vnode获取组件选项 即vnode.typeconst 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.typeconst componentOption = vnode.type//获取render函数const { render, data, beforeCreate, created, beforeMount, mounted } =componentOptionbeforeCreate && beforeCreate()//响应式数据const state = reactive(data())//定义组件实例const instance = {state, //组件状态isMounted: false, //组件是否已经挂载subTree: null, //组件的虚拟DOM}vnode.component = instancecreated && 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})}
