React 学习笔记 【ReactDom.render() 渲染原理】
JSX渲染机制
- 1,通过bebel语法解析模块(babel-preset-react)把jsx语法编译为React.createElement(…);
React.createElement(
"div",
{
id:"box",
style:{color:'red',fontSize:'20px'},
className:'title'
},
"\u5E74\u9F84\uFF1A"
)
- 2,执行React.createElement(type,props,children)方法,创建一个虚拟对象(虚拟DOM)
// 对象主要包括
{
key:null,
ref:null,
props:{
id:"box",
style:{color:'red',fontSize:'20px'},
className:'title',
children: "\u5E74\u9F84\uFF1A" //->存放的是元素中的内容,元素中的内容如果比较复杂是一个数组
},
.........
__proto__:Object
}
- 3,ReactDom.render(jsx语法生成的对象,容器,回调函数),基于render方法把生成的对象动态创建DOM元素,插入到指定容器中
如下是用原生JS模拟实现render()方法
// 1,createElement
function createElement(type,props,children){
//创建一个对象,并设置一些默认值
let obj ={
type:'',
props:{children:''},
key:null,
ref:null
}
// 拓展运算,把传入进来的type和props覆盖到obj上
obj={...obj,type,props:{...props,children}};
// props对象中 把key和ref取出来放在外面obj中,props的key和ref删除
if('key' in obj.props){
obj.key = obj.props.key;
obj.props.key=undefined;
}
if('ref' in obj.props){
obj.ref = obj.props.ref;
obj.props.ref= undefined;
}
// 把重新组装的对象返回出去
return obj
};
let jsxObj =createElement(
'H1',
{
id:"box",
style:{color:'red',fontSize:'20px'},
className:'title',
},
'\u5E74\u9F84\uFF1A'
);
// 2,render方法
function render(jsxObj,container,callback){
// 解构赋值
let {type,props} = jsxObj||{};
// 创建dom元素
let newEle =document.createElement(type);
// 把props的属性添加到新创建的元素上
for(let attr in props){
//容错处理
// 如果不是对象的私有属性,就结束循环
if(!props.hasOwnProperty(attr)) break;
// 如果当前属性没有值,则跳过本次循环
if(!props[attr]) continue;
let value = props[attr];
//特殊处理,className,style,children
if( attr ==='className'){
newEle.setAtrribute('class',value);
continue
};
if(attr ==='style'){
if(value==='') continue;
for(let styleKey in value){
if(value.hasOwnProperty(styleKey)){
newEle['style'][styleKey] = value[styleKey]
}
}
continue
};
if(attr ==='children'){
if(typeof value==='string'){
let textNode = document.createTextNode(value);
newEle.appendChild(textNode)
}
continue
}
// 把遍历出来的属性和属性值设置到新创建的元素上
newEle.setAttribute(attr,value);
};
//把创建的元素添加到容器中
container.appendChild(newEle);
// 回调函数存在,就执行回调函数
callback&&callback();
}
let root = document.querySelector("#root")
render(jsxObj,root,()=>{
console.log('渲染完毕')
})
最后在index.js中引入即可
// 自己编写的render 方法
import './self_jsx'