来到我们的App的主要结构
import {h} from '../../lib/guide-mini-vue.esm.js'
export const App = {
name:"App",
setup(){
const count = ref(10)
window.count = count
return {
count
}
},
render(){
return h('div',{},[h("div",{tId:1},[h("p",{},'主页' +this.count)])
}
}
在上一节讲到我们在初始化时把实例对象用proxy进行了劫持代理,当我们调用render就可以用this来访问我们的代理对象,并且我们的返回值用ref进行包裹处理时就不需要再进行.value的处理了
const publicPropertiesMap = {
$el:(i)=> i.vnode.el,
// $slots
$slots:(i)=> i.slots,
$props:(i)=> i.props
}
export const PublicInstanceProxyHandlers = {
get({_:instance},key){
// 先从setupstate中获取值
const {setupState,props} = instance
// if(key in setupState){
// return setupState[key]
// }
// 将上面的逻辑进行重构 加上我们的props的逻辑
// const hasOwn = (val,key)=> Object.prototype.hasOwnProperty.call(val,key)
if(hasOwn(setupState,key)){
return setupState[key]
}else if(hasOwn(props,key)){
return props[key]
}
// key=>el
const publicGetter = publicPropertiesMap[key]
if(publicGetter){
return publicGetter(instance)
}
// if(key === '$el'){
// return instance.vnode.el
// }
}
}
既然我们可以以this访问到我们setup中的内容,我们可以将this指向window,就可以在控制台中直接调试我们的值的更新
当我们触发更新流程时,就会进到我们的effect中的函数调用,如果mount过了就会进入到我们的else分支,然后调用我们的render函数,获取到我们的新旧虚拟节点树,然后又回到了我们的patch函数的调用,
instance.update = effect(()=>{
if(!instance.isMounted){
console.log('init')
const {proxy} = instance
const subTree = instance.subTree = instance.render.call(proxy);
// console.log(subTree)
// vndoeTree => patch
// vnode => element =>mountElement
patch(null,subTree,container,instance,anchor)
// 我们这里的subTree就是我们的根节点,我们所要赋值的el可以在subTree上找到
// 传入我们的虚拟节点
initialvnode.el = subTree.el
instance.isMounted = true
}else{
console.log('update')
// 需要一个更新之后的vnode
const {next,vnode} = instance
if(next){
next.el = vnode.el
updateComponentPreRender(instance,next)
}
const {proxy} = instance
const subTree = instance.render.call(proxy);
const prevSubTree = instance.subTree
instance.subTree = subTree