有关代码
- vnode 扩展支持字符串类型
在开始之前我们先来处理一个小问题,就是我们程序的扩展性,这里如果 vnode 是 number 类型也就是数值类型我们需要对其处理转换为字符串。
if(typeof vnode === 'string'){
//create textNode
return document.createTextNode(vnode)
}
通过 String 方法将 vnode 转为字符串
if(typeof vnode === 'string'){
//create textNode
return document.createTextNode(vnode)
}
// vnode is equal string
if(typeof vnode === 'string'){
//create textNode
return document.createTextNode(vnode)
}
- 在渲染子组件前需要判断子组件是否为空
if(vnode.children){
vnode.children.forEach(child=>render(child,dom))
}
类组件
class Box extends React.Component{
render(){
return (
<div className='box' size="24">
hello,<span>zidea</span>
</div>
)
}
}
import Component from './component';
//定义 createElement
function createElement(tag,attrs,...children){
return {
tag,
attrs,
children
}
}
export default {
createElement,
Component
};
实现类组件生命周期方法
在开始之前我们可以简单复习一下 react 的生命周期各个阶段,这么多生命周期函数大致可以分为装配、更新和卸载三个部分。
- 装配
- constructor
- componentWillMount
- componentDidMount
- 更新
- componentWillReceiveProps
- componentWillUpdate
- componentDidUpdate
class Box extends React.Component{
constructor(props){
super(props)
console.log("call constructor");
}
componentWillMount(){
console.log("component will mount...");
}
componentWillReceiveProps(props){
console.log("component will receive props: " + props);
}
componentWillUpdate(){
console.log("component will update...")
}
componentDidUpdate(){
console.log("component did update...");
}
componentDidMount(){
console.log("component did mount...")
}
render(){
return (
<div className='box' size="24">
hello,<span>zidea</span>
</div>
)
}
}
渲染前
function setComponentProps(comp,props){
if(!comp.base){
if(comp.componentWillMount) comp.componentWillMount()
}else if(comp.componentWillReceiveProps){
comp.componentWillReceiveProps();
}
//设置组件的属性
comp.propos = props;
renderComponent(comp)
}
渲染后
通过判断comp.base
是否存在来判断网页是否已经完成渲染。
function renderComponent(comp){
let base;
//call render method to return jsx object
const renderer = comp.render();
//
base = _render(renderer);
if(comp.base && comp.componentWillUpdate){
comp.componentWillUpdate()
}
if(comp.base){
if(comp.componentDidUpdate){
comp.componentDidUpdate()
}
}else if(comp.componentDidMount){
comp.componentDidMount();
}
comp.base = base
}
更新
- 添加一个按钮
render(){
console.log("render...")
return (
<div className='box' size="24">
<button onClick = {this.increaseCounter.bind(this)}>increase</button>
counter : <span>{this.state.counter}</span>
</div>
)
}
- 定义 state
constructor(props){
super(props);
this.state = {
counter:0
}
console.log("call constructor");
}
- 定义 increaseCounter 方法
increaseCounter (){
//update state
this.setState({
counter:this.state.counter +1
})
}
- 实现 setState 方法
setState(nextState){
//update state object
Object.assign(this.state.nextState);
//render component
}
export function renderComponent(comp){
...
}
import {renderComponent} from '../react-dom';
class Component{
constructor(props = {}){
this.props = props;
this.state = {};
}
setState(nextState){
//update state object
Object.assign(this.state.nextState);
//render component
renderComponent(this);
}
}
export default Component;
export function renderComponent(comp){
let base;
//call render method to return jsx object
const renderer = comp.render();
//
base = _render(renderer);
if(comp.base && comp.componentWillUpdate){
comp.componentWillUpdate()
}
if(comp.base){
if(comp.componentDidUpdate){
comp.componentDidUpdate()
}
}else if(comp.componentDidMount){
comp.componentDidMount();
}
if(comp.base && comp.base.parentNode){
comp.base.parentNode.replaceChild(base,comp.base)
}
comp.base = base
}