1、首先创建createElement函数

 1 function createElement (
2 type,
3 config,
4 ...children
5 ) {
6
7 const props = {
8 ...config,
9 children: children.map(child => typeof child === 'object' ? child : createTextNode(child))
10 }
11
12 return {
13 type,
14 props
15 }
16 }
17
18 function createTextNode (text) {
19
20 return {
21 type: 'TEXT',
22 props:{
23 children:[],
24 nodeValue: text
25 }
26 }
27 }

2、然后创建react-dom,即render函数

 1 function render(vnode, container) {
2 //vnode -> node
3 const node = createNode(vnode)
4 //node 插入container
5 console.log(node);
6 node && container && container.appendChild(node)
7 }
8
9 function createNode (vnode) {
10 const {
11 type,
12 props
13 } = vnode
14 let node;
15
16 //根据节点类型生成dom节点
17 if(type === 'TEXT'){
18 //文本
19 node = document.createTextNode('')
20 } else if(typeof type === 'string') {
21 node = document.createElement(type)
22 }
23 //遍历children
24
25 reconcileChildren(node, props ? props.children : [])
26
27 //更新属性
28 updateNode(node, props)
29 return node
30
31 }
32
33 function updateNode(node, nextVal) {
34 if(nextVal){
35 Reflect.ownKeys(nextVal).filter(ck => ck !== 'children').forEach(k => {
36 node[k] = nextVal[k]
37 })
38 }
39 }
40
41 function reconcileChildren(node, children) {
42 children.forEach(child => {
43 render(child,node)
44 })
45 }

3、Fiber实现:

function render(vnode, container) {
//vnode -> node
// const node = createNode(vnode)
//node 插入container
// console.log(node);
// node && container && container.appendChild(node)
// workLoop
wipRoot = {
stateNode: container,
props:{
children:[vnode]
}
}
nextUnitOfWork = wipRoot
} function createNode (vnode) {
const {
type,
props
} = vnode
let node; //根据节点类型生成dom节点
if(type === 'TEXT'){
//文本
node = document.createTextNode('')
} else if(typeof type === 'string') {
node = document.createElement(type)
}
//遍历children reconcileChildren(node, props ? props.children : []) //更新属性
updateNode(node, props)
return node } function updateNode(node, nextVal) {
if(nextVal){
Reflect.ownKeys(nextVal).filter(ck => ck !== 'children').forEach(k => {
node[k] = nextVal[k]
})
}
} // function reconcileChildren(node, children) {
// children.forEach(child => {
// render(child,node)
// })
// }
/* fiber */
//next work fiber
let nextUnitOfWork = null
// work in progress 正在工作红的fiber root
let wipRoot = null function reconcileChildren(workInProgress,children){
let prevNewFiber = null
children.forEach((child,i) => {
//FiberNode 节点
let newFiber = {
type: child.type,
key: child.key,
props:child.props,
stateNode: null,
child: null,
sibling: null,
return:workInProgress
} if(i === 0){
workInProgress.child = newFiber
} else {
prevNewFiber.sibling = newFiber
} prevNewFiber = newFiber
})
} function updateHostComponent(workInProgress){
if(!workInProgress.stateNode){
workInProgress.stateNode = createNode(workInProgress)
} reconcileChildren(workInProgress,workInProgress.props.children)
} function performUnitOfWork(workInProgress) {
//1 处理当前fiber
//原生标签
updateHostComponent(workInProgress) //2 返回下一个要处理的fiber
if(workInProgress.child){
return workInProgress.child
} let next = workInProgress while(next){
if(next.sibling){
return next.sibling
}
next = next.return
}
} //更新Fiber
function workLoop (idleDeadline) {
console.log(idleDeadline);
while(nextUnitOfWork && idleDeadline.timeRemaining() > 1) {
//处理当前fiber 并返回下个fiber
nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
}
//comnitRoot
if(!nextUnitOfWork && wipRoot){
//vnode - node 更新到container中
commitRoot()
}
} requestIdleCallback(workLoop,{ timeout: 2000 }) function commitRoot() {
commitWorker(wipRoot.child)
wipRoot = null
} function commitWorker(workInProgress){
if(!workInProgress){
return
}
//提交workInProgress
let parentNodeFiber = workInProgress.return
let parentNode = parentNodeFiber.stateNode
if(workInProgress.stateNode){
parentNode.appendChild(workInProgress.stateNode)
}
//提交 workInProgress.child
commitWorker(workInProgress.child)
//提交 workInProgress.sibling
commitWorker(workInProgress.sibling)
}
// export default { render }

4、最后演示

 1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>手写React</title>
6 <script src="main.js" type="text/javascript" charset="utf-8"></script>
7 <script src="treact-dom.js" type="text/javascript" charset="utf-8"></script>
8 </head>
9 <body>
10 <div id="root"></div>
11 <script type="text/javascript">
12 let rot = createElement(
13 "div",
14 null,
15 createElement(
16 "h1",
17 null,
18 "慢 慢 慢"
19 ),
20 createElement(
21 "p",
22 null,
23 "Terry"
24 ),
25 createElement(
26 "a",
27 { href: "https://www.kaikeba.com/" },
28 "Terry"
29 ),
30 "哈哈哈哈"
31 )
32 render(rot, document.getElementById("root"))
33 </script>
34 </body>
35 </html>

5、结果

最新文章

  1. Android提交数据到JavaWeb服务器实现登录
  2. wordpress数据库表说明
  3. 利用Delphi的File Of Type创建并管理属于你自己的数据库
  4. MongoDB的安装 转
  5. 获得输入框的文本document.getElementById(&#39;id&#39;).value;
  6. Codeforces Round #382 (Div. 2) D. Taxes 歌德巴赫猜想
  7. 无线 WIFI 的13个信道频率范围
  8. Mindjet MindManager 2012 从模板创建出现“Runtime Error pure virtual function call” 解决方法
  9. oracle Recyclebin
  10. Fiddler教程【转】
  11. 「JavaScript」同步、异步、回调执行顺序之经典闭包setTimeout分析
  12. Hadoop API:遍历文件分区目录,并根据目录下的数据进行并行提交spark任务
  13. [2019.03.16]使用DOM操作函数和CSS选择器来针对已有的HTML进行只凭JS的改动
  14. UVa 10970 - Big Chocolate 水题 难度: 0
  15. 分布式控制系统Git学习
  16. django —— MVT模型
  17. DropEditText
  18. Redis实现聊天功能
  19. spring揭密学习笔记(1) --spring的由来
  20. O​r​a​c​l​e​ ​1​1​g​ ​客​户​端​安​装​及​p​l​s​q​l​配​置

热门文章

  1. 【面试题】java一般
  2. 扫描仪扫描文件处理-Photoshop批处理无响应问题
  3. spring boot:spring security实现oauth2授权认证(spring boot 2.3.3)
  4. lerna管理前端模块实践
  5. IDEA出现Error Loading Project: Cannot load module xxx报错
  6. LinkedHashMap 实现LRU缓存
  7. MFiX中DEM颗粒信息随时间变化
  8. Swagger配置与使用
  9. Spark为什么只有在调用action时才会触发任务执行呢(附算子优化和使用示例)?
  10. python数据类型之String(字符串)