先引入React创建demo看下效果,在引入简版的wxyReact看下效果
下面开始根据demo写代码
1. 原生组件处理逻辑
1.1 原生demo src/index.js
//src/index.js
import React from './wxyReact'
import ReactDOM from './wxyReact/reactDom'
import './index.css'
const jsx = (<div className="dom">
<div className='dd'>我是div组件</div>
</div>)
ReactDOM.render(jsx, document.getElementById('root'));
1.2 创建wxyReact
我们需要在里面做什么呢?wxyReact是react的属性
wxyReact含有什么呢?先运行demo看看,
可以通过错误信息得到我们的react需要一个createElement
函数,
而参数假设通过源码中github.com/facebook/re…的createElement
函数312行得知返回为三个参数😝
是由于babel-loader默认编译,编译后的虚拟dom是如此 点击测试
so,我们就得到了wxyReact
👆👆👆👆上面的代码(方便复制)
//参数function createElement(type, props, ...children) { //返回虚拟dom //构建一个树状图,从父元素获取子元素,添加childern属性 props.children = children //根据type不同,区分处理方式 let vtype; if (typeof type === 'string') { //原生标签<div></div><p></p> vtype = 1 } return { type, props, vtype }}const React = { createElement }export default React
1.3 创建reactDom
reactDom是吧虚拟dom转换真实dom操作
在demo中可以观察到reactDom
中包含render函数参数是node和父元素
ReactDOM.render(jsx, document.getElementById('root'));
👆👆👆👆上面的代码(方便复制)
import { initVnode } from './virtual-dom'function render(vnode, container) { const node = initVnode(vnode, container) //把真实的dom节点放到container里面去 container.appendChild(node)}const ReactDOM = { render }export default ReactDOM
初始化虚拟dom
👆👆👆👆上面的代码(方便复制)
//把vnode变成node export function initVnode(vnode, container) { //查看vode解构区分节点渲染方式 let node = null; const { vtype } = vnode if (!vtype) { node = initTexNode(vnode, container); } if (vtype === 1) { //原生标签 node = initHtmlNode(vnode, container); } return node}function initTexNode(vnode, container) { const node = document.createTextNode(vnode) return node}function initHtmlNode(vnode, container) { const { type, props } = vnode const { children, ...rest } = props const node = document.createElement(type) props.children.map(item => { node.appendChild(initVnode(item, node)) }) //添加标签属性 Object.keys(rest).map(key => { if (key === 'className') { node.setAttribute('class', rest[key]) } }) return node}
效果如下
处理数组表达式渲染例如:
{[1, 2, 3].map(one => `第${one}个、`)}
添加数组处理
const { type, props } = vnode
const { children, ...rest } = props
const node = document.createElement(type)
props.children.map(item => {
//添加数组判断
+ if (Array.isArray(item)) {
+ for (let i of item) {
+ node.appendChild(initVnode(i, node))
+ }
} else {
node.appendChild(initVnode(item, node))
}
})
2. function函数处理逻辑
2.1添加function组件demo
//函数处理
+ function FuncCom(props) {
+ return <div >{props.name}</div>
+ }
const jsx = (<div className="dom">
<div className='dd'>我是div组件</div>
+ <FuncCom name='function组件' />
</div>)
2.2 在wxyReact.js添加vtype判断
let vtype;
if (typeof type === 'string') {
//原生标签<div></div><p></p>
vtype = 1
+ } else if (typeof type === 'function') {
+ vtype = 3
+ }
2.3 在virtual-dom.js添加function dom 处理方法
function initFunctionNode(vnode, container) { const { type, props } = vnode console.log("TCL: initFunctionNode -> type", type) //函数的虚拟dom const vfnode = type(props) //真实node return initVnode(vfnode, container)}
效果如下:
3. class组件处理方法
3.1 class组件demo
class ClassCom extends React.Component {
render() {
return (
<div>
{this.props.name}
</div>
);
}
}
const jsx = (<div className="dom">
<div className='dd'>我是div组件</div>
<FuncCom name='function组件' />
<ClassCom name='class组件' />
</div>)
3.2在wxyReact.js添加vtype判断
咋判断呢,class也是函数组件,怎么区分函数组件和class组件呢?
veryEase如下:
3.3在virtual-dom.js添加class组件 dom 处理方法
效果如下: