1.React文件:
title
会被babel
转译成虚拟dom
//html中引入的index.js文件
import React from "./react"; // ①
import ReactDom from "./react-dom" // ②
const title = (
<h2 className = 'title'>
<span> hello React</span>
</h2> );
// 上⾯代码会被babel转义成下⾯对象 ⽽这个对象就是所谓的虚拟DOM
/*
var title = React.createElement("h2", {
className: "title"
}, " hello React ");
*/
console.log(title);
- 接着来看下引入的
React
:
// react/index.js
const React = {
createElement
}
function createElement(tag,attrs,...children) {
return{
tag,
attrs,
children
}
}
export default React
编译后,打开浏览器,在localhost:1234
端口可见:
2.ReactDom的render方法:
1.字符串:
在index.js
文件中修改如下:
import React from "./react";
import ReactDom from "./react-dom";
const title = (
<h2 className = 'title'>
<span> hello React</span>
</h2> );
// 上⾯代码会被babel转义成下⾯对象 ⽽这个对象就是所谓的虚拟DOM
/*
var title = React.createElement("h2", {
className: "title"
}, " hello React ");
*/
console.log(title);
// 测试render方法为字符串的时候是否可以渲染
ReactDom.render("你好世界",document.querySelector("#root"))
然后来看下react-dom
的代码:
- 和上面写
React
类似,这里面也有个render
方法,需要2个参数
:vDom
:虚拟domcontainer
:节点
// react-dom/index.js
const ReactDom = {
render
}
function render(vDom,container){
if (vDom==="undefined") return ;
if(typeof vDom === "string"){
const text = document.createTextNode(vDom);
return container.appendChild(text);
}
}
export default ReactDom;
测试结果:
2.虚拟dom对象:
在ReactDom
的render方法
中,主要还得是对于虚拟dom对象
的处理,宗旨就是先处理一层,再递归操作~!!! X3 (重要的事情说3遍)
const {tag,attrs} = vDom;
解构出对应的值。- 遍历所有的
attrs
,通过setAttributes
方法设置属性
。 setAttrubutes
方法中将attrs
中的属性转换为dom
属性。- 然后去看
vDom
的子节点children
,然后递归调用
。
const ReactDom = {
render
}
function render(vDom,container){
//如果vDom未定义或者是字符串
if (vDom==="undefined") return ;
if(typeof vDom === "string"){
const text = document.createTextNode(vDom);
return container.appendChild(text);
}
//虚拟dom对象
const {tag,attrs} = vDom;
const dom = document.createElement(tag);
if(attrs){
Object.keys(attrs).forEach(key=>{
const value = attrs[key]
setAttribute(dom,key,value)
})
}
//递归渲染子节点
vDom.children.forEach(child=>{
render(child,dom)
})
return container.appendChild(dom);
}
// 设置属性
function setAttribute(dom,key,value){
//将属性名className转换成class
if(key === "className"){
key = "class"
}
// 如果是事件 onClick onBlur
if(/on\w+/.test(key)){
// 转小写
key = key.toLowerCase();
dom.key = value || " "
}else if(key ==="style") //style的value可以是值,也可以是个对象
{
if(!value || typeof value === "string")
{
dom.style.cssText = value || "";
}else if(value && typeof value === "object")
{
// {width:20} 是value,key是width
for(let k in value)
{
if(typeof value[k] ==="number")
{
dom.style[k] = value[k] +"px";
}else
{
dom.style[k] = value[k];
}
}
}
}else
{ //其他属性
if(key in dom)
{
dom[key] = value || "";
}
if(value)
{
dom.setAttribute(key,value)
}
else
{
dom.removeAttribute(key)
}
}
}
export default ReactDom;