react18将会用到ReactDOM.createRoot作为根函数渲染,render最作为兼容。
为什么用createroot?
render则是拿不到root,只能在开辟一个新的对象
let root = ReactDOM.createRoot(document.getElementById('root')) root.render(jsx) root.render(jsx2) 实现复用
创建一个react-dom.js文件
render拿到的children:
其中 props属性,type,key是不是很眼熟? 这就是最原始的vnode(ReactFiber.js里crateFiber接收的参数)
拿到dom元素后开始生成filber,然后组件渲染
import {createFiber} from './ReactFiber'
import { scheduleUpdateOnFiber } from './ReactFilberWorkLoop';
/**
* @internalRoot 内部跟节点
*/
function ReactDOMRoot(internalRoot){
this._internalRoot = internalRoot
}
/**
* @children 子节点
*/
ReactDOMRoot.prototype.render = function(children){
console.log('render-children',children);
const root = this._internalRoot;
updateContainer(children,root)
}
/**
* @element 子节点,
* @container 根节点,document.getElementById('root')
* 初步渲染更新filber结构(先更新VDOM)
*/
function updateContainer(element,container){
const {containerInfo} = container
console.log('updateContainer-父节点:',containerInfo);
console.dir(containerInfo);
//父子节点的dom对象拿到了,生成fiber
const filber = createFiber(element,{
//父节点的filber
type:containerInfo.nodeName.toLocaleLowerCase(),
stateNode:containerInfo,
})
//组件渲染
scheduleUpdateOnFiber(filber)
}
/**
* @container 根节点,document.getElementById('root')
*/
function createRoot(container){
const root = {containerInfo:container}
return new ReactDOMRoot(root)
}
export default {
createRoot,//懒汉式单件设计模式,返回唯一的ReactDOMRoot实例
}
在workloop.js中添加函数scheduleUpdateOnFiber,此函数用于初次渲染和更新,保存根节点。
let wip = null; //当前正在工作中的fiber
let wipRoot = null;
//初次渲染和更新
export function scheduleUpdateOnFiber(filber){
wip = filber;
//当所有fiber更新完之后,更新到根节点上,因此将初始的根节点保存
wipRoot = filber;
}
现在该考虑如何更新节点了。怎么将performUnitOfWork跑起来