组件和状态管理初探

Component and State

Posted by yellowDog on 2018-07-24

参考:

原生实现

  • 状态改变 -> 构建新的DOM更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class likeButton {
constructor(){
this.state = {
isLiked: false
}
}
setState(state){
this.state = state;
this.el = this.render();
}
changeText(){
this.setState({
isLiked: !this.state.isLiked;
});
}
render(){
this.el = createDomString(`
<button class='like-btn'>
<span class='like-text'>${this.state.isLiked ? "取消" : "点赞"}</span>
<span> </span>
</button>
`);
this.el.addEventListener(`click`,this.changeText.bind(this),false);
return this.el;
}
}

但是改进DOM操作,并没有把新的DOM元素更新到页面

修改setState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
setState(state){
const oldElement = this.el;
this.state = state;
this.el = this.render();
if(this.onStateChange) this.onStateChange(oldElemnt, this.el)
}

//调用组件

const likeButton = new LikeButton();
wrapper.appendChild(likeButton.render());
likeButton.onStateChange = (oldElement,newElement) => {
wrapper.insertBefore(newElement, oldElement);
wrapper.removeChild(oldElement);
}

抽象出组件类

  • 代码复用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Component{
setState(state){
const oldEl = this.el;
this.state = state;
this._renderDOM();
if(this.onStateChange) this.onStateChange(oldEl,this.el)
}

_renderDOM(){
this.el = createDOMFromString(this.render());
if(this.onClick){
this.el.addEventListener(`click`,this.onClick.bind(this),false)
}
return this.el;
}
}

const mount = (component, wrapper) => {
wrapper.appendChild(component._renderDOM())
component.onStateChange = (oldEl, newEl) => {
wrapper.insertBefore(newEl, oldEl)
wrapper.removeChild(oldEl)
}
}

重新编写组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class LikeButton extends Component {
constructor () {
super()
this.state = { isLiked: false }
}
onClick () {
this.setState({
isLiked: !this.state.isLiked
})
}
render () {
return `
<button class='like-btn'>
<span class='like-text'{this.state.isLiked ? '取消' : '点赞'</span>
</button>
`
}
}

mount(new LikeButton(), wrapper)

编写自定义配置数据

  • 比如复用按钮需要不同的颜色

修改Component父类的constructor

1
2
3
constructor(props = {}){
this.props = props
}

继承的时候super(props)把props传递给父类


React中实现

React帮你做的事

  • 检查数据是否更新,不需要手动去更新DOM

  • 生命周期函数componentWillUnmount,在DOM被删除的时候,销毁组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Clock extends React.Component {
constructor(props) {
super(props); //传递props给基础构造函数
this.state = {
date: new Date()
};
}
componentDidMount() {
this.timerID = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
//更新state
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>hello world</h1>
<h2>{this.state.date.toLocaleTimeString()}</h2>
</div>
);
}
}

ReactDOM.render(<Clock />, document.querySelector("#root"));