React系列(二)--|React系列(二)-- React基本语法实现思路
前言
我们先不讲什么语法原理,先根据API效果强行模拟语法使用,实现一个简易版的React.
下面代码跟React源码没有关系,只是单纯模拟思路实现
render
第一步我们先用类创建一个元素返回,并且绑定点击事件,代码如下,可以正常看到一个按钮出现了.
class AddButton {
// 创建Dom
createDOM(domString) {
const div = document.createElement("div");
div.innerHTML = domString;
return div;
}// 输出实例
render() {
this.dom = this.createDOM(``);
this.dom.addEventListener("click", () => console.log("click"), false);
return this.dom;
}
}// 插入页面
document.body.appendChild(new AddButton().render());
state && setState 实现类状态和修改状态方法
class AddButton {
// 内置状态
constructor() {
this.state = { num: 0 };
}// 创建Dom
createDOM(domString) {
const div = document.createElement("div");
div.innerHTML = domString;
return div;
}// 唯一修改状态更新视图
setState(state) {
this.state = state;
this.dom = this.render();
}// 修改数据
handleAdd() {
const num = this.state.num + 1;
this.setState({
num: num
});
}// 输出实例
render() {
this.dom = this.createDOM(``);
this.dom.addEventListener("click", () => this.handleAdd(), false);
return this.dom;
}
}// 插入页面
document.body.appendChild(new AddButton().render());
渲染之后看到
this.dom
输出已经发现改变了,但是视图并没有渲染,那是因为这是结尾一次性插入,下面就渲染视图这块往下走重新渲染 我们现在把插入数据的操作内置到class里面,新增一个方法插入新元素移除旧元素.
class AddButton {
// 内置状态
constructor() {
this.state = { num: 0 };
}// 创建Dom
createDOM(domString) {
const div = document.createElement("div");
div.innerHTML = domString;
return div;
}// 只是一个替换元素的方法
changeDom() {
const oDom = this.dom;
this.dom = this.render();
document.body.insertBefore(this.dom, oDom);
document.body.removeChild(oDom);
}// 唯一修改状态更新视图
setState(state) {
this.state = state;
this.changeDom();
}// 修改数据
handleAdd() {
const num = this.state.num + 1;
this.setState({
num: num
});
}// 输出实例
render() {
this.dom = this.createDOM(``);
this.dom.addEventListener("click", () => this.handleAdd(), false);
return this.dom;
}
}// 插入页面
document.body.appendChild(new AddButton().render());
现在效果虽然实现,但是还是得开头手动把元素插入视图
抽取公用类 我们先将一些共有方法提取到一个单独类,另外补全一下props属性传参
class React {
// 内置状态
constructor(props = {}) {
// 实例
this.wrapper = null
// 状态
this.state = {}
// 属性
this.props = {}
}// 创建Dom
createDOM(domString) {
const div = document.createElement("div");
div.innerHTML = domString;
return div;
}// 只是一个替换元素的方法
changeDom() {
const oDom = this.dom;
this.dom = this._render();
this.wrapper.insertBefore(this.dom, oDom);
this.wrapper.removeChild(oDom);
}// 唯一修改状态更新视图
setState(state) {
this.state = state;
this.changeDom();
}// 输出实例
_render(wrapper) {
if (wrapper) this.wrapper = wrapper;
this.dom = this.createDOM(this.render());
this.dom.addEventListener("click", () => console.log('添加自定义事件'), false);
return this.dom;
}
}
然后组件只需要直接继承
Component
然后处理自己逻辑即可class AddButton extends React {
constructor() {
super();
this.state = { num: 0 };
}handleAdd() {
const num = this.state.num + 1;
this.setState({
num: num
});
}render() {
return ``;
}
}
上面做了几件事:
- 抽取通用的逻辑到React类
- 自定义组件AddButton
Component
里面,下一章节实现添加自定义事件 因为事件是由组件自定义的,所以我们思路是在组件实例定义好之后,通用类绑定事件
class React {
// 内置状态
constructor(props = {}) {
// 实例
this.wrapper = null
// 状态
this.state = {}
// 属性
this.props = {}
// 事件
this.event = {}
}// 创建Dom
createDOM(domString) {
const div = document.createElement("div");
div.innerHTML = domString;
return div;
}// 只是一个替换元素的方法
changeDom() {
const oDom = this.dom;
this.dom = this._render();
this.wrapper.insertBefore(this.dom, oDom);
this.wrapper.removeChild(oDom);
}// 唯一修改状态更新视图
setState(state) {
this.state = state;
this.changeDom();
}// 初始化事件
initEvent() {
const events = Object.keys(this.event)
events.forEach(key => {
this.dom.addEventListener(key, this.event[key].bind(this), false);
})
}// 输出实例
_render(wrapper) {
if (wrapper) this.wrapper = wrapper;
this.dom = this.createDOM(this.render());
// 需要创建实例后才能初始化
this.dom && this.initEvent()
return this.dom;
}
}
同时组件代码也需要相对应的修改
class AddButton extends React {
constructor() {
super();
this.state = { num: 0 };
this.event = {
click: this.handleAdd
}
}handleAdd() {
const num = this.state.num + 1;
this.setState({
num: num
});
}render() {
return ``;
}
}
ReactDom.render 【React系列(二)--|React系列(二)-- React基本语法实现思路】大家都知道React会提供这么一个方法将组件插入一个指定元素,我们直接模拟
const ReactDom = {
// 指定元素内插入组件实例
render(component, wrapper) {
wrapper.appendChild(component._render(wrapper));
}
};
最终运行代码 我们上面已经实现了几个功能:
- 负责创建元素的React类,包括单向数据流,自定义状态,事件,替换元素等
- 负责挂载的ReactDom类
至此,抛开实际思路不说,我们已经简单模拟出来React的基本语法实现了.
推荐阅读
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- 遇到一哭二闹三打滚的孩子,怎么办┃山伯教育
- 赢在人生六项精进二阶Day3复盘
- 2019年12月24日
- 陇上秋二|陇上秋二 罗敷媚
- 一百二十三夜,请嫁给我
- 迷失的世界(二十七)
- 我要我们在一起(二)
- 基于|基于 antd 风格的 element-table + pagination 的二次封装
- (二)ES6第一节变量(let|(二)ES6第一节变量(let,const)