接上文中b会随着a的变化而变化,那么将b替换成当前view视图就可以实现响应式改变页面了
1.实现App.js,注意抽离用户不需要操作的effectWatch
//App.js
import {reactive} from './core/reactivity/index.js'
import { h } from './core/h.js'
export default {
render (context) {
// //构建view =>b
// const div = document.createElement('div')
// div.innerHTML = context.state.count
// //root
// return div
//构建虚拟dom
return h('div',
{
id:'app - id',
class:'showTim'
},
[h('p',null,'hhh'),
h('p', null, 'heiheihei')
]
)
},
setup () {
//a =>响应式的数据
const state = reactive({ count: 0 })
window.state = state
return { state }
}
}
2.实现main.js
//index.js
import App from "./App.js";
import { createApp } from "./core/index.js";
createApp(App).mount(document.querySelector('#app'))
3.实现creatApp
//core/index.js
import { effectWatch } from './reactivity/index.js'
import { mountElement } from './renderer/index.js'
//rootComponent ==> App.js
export function createApp (rootComponent) {
return {
//rootContainer == #app
mount (rootContainer) {
const context = rootComponent.setup()
effectWatch(() => {
rootContainer.innerHTML = ''
//element ==> render函数 return的 div
// const element = rootComponent.render(context)
// rootContainer.append(element)
//传入的是虚拟dom对象
const subTree = rootComponent.render(context)
console.log(subTree)
mountElement(subTree,rootContainer)
}
)
}
}
}
4.实现mountElement
//core/renderer/index.js
//vdom=>真实dom
export function mountElement(vnode,container){
const {tag,props,children} = vnode
//tag
const el = document.createElement(tag)
//props
if(props){
for (const key in props) {
const val = props[key]
el.setAttribute(key,val)
}
}
//children
//1.它可以接受一个string
if(typeof children==='string'){
const textNode = document.createTextNode(children)
el.append(textNode)
}else if(Array.isArray(children)){
children.forEach((v) => {
mountElement(v,el)
}
)
}
container.append(el)
}
5.渲染函数h
//core/h.js
export function h(tag,props,children){
return {
tag,
props,
children
}
}