最近因为工作需要,开始学习react,在读了基础部分的文档之后,决定写一个todolist来练习。功能十分简单,简单的增加删除。涉及到一些可以总结的部分,还是有部分涉及不到的地方,以后再谈。
开始
这里我直接用了官方的cli工具create-react-app,安装过程如下
npm install -g create-react-app
create-react-app my-app
cd my-app
npm start
index.js为入口文件,首先要引入相关的js文件
import ReactDOM from "react-dom";
import React from "react";
import "./index.css";
jsx
说到react,就不得不提到jsx,何为jsx,其实完全可以就理解为js,只不过里面有不加引号的html代码段,举个例子:
<li key={index}>
{li}
<span onClick={this.delList} data-id={index}>
x
</span>
</li>
这里是我return出来的语句,可以看到原来是html的部分都是那样,在html中的{}表示的就是js的语句了。
组件
可以理解为每一个react.Component对象就是一个组件,由于js里不存在纯粹意义上的class,即使是es6也只是用语法糖做了一些处理,所以定义组件有两种写法。
一、使用function
二、使用class
这里更推荐使用class,由于react基本就是和babel一起使用,所以学会新的方法很有必要,建议去mdn上搜索class看看文档。
具体用法:
class XXX extends React.Component
注意要大写,在渲染的时候在页面中标签也要是大写,比如这里的<Todos/>,原因是小写会识别为标准的html标签
ReactDOM.render(<Todos />,document.getElementById("root"));
更多细节参考文档,重点说明父子组件通信的问题,这里我设计了两个组件。
结构示意图
父组件Todos包括确定按钮和ul元素,子组件list则是所有列表的集合。
react有个原则是:
组件不能直接操作其它组件,而数据是从父到子单项传递的
这里,要说明两个参数props,state。state表示自身可以捕捉到改变的值,props则来自于父组件。
这里我在父组件Todo里,设置了state
state = {
list: [1, 2, 3],
targetValue:'work'
};
这里面的list就是要传递到子组件的值,我们在子组件上定义
<List
additem={this.state.item}
tolist={this.state.list}
onChange={this.listChange}
/>
而在子组件,就可以用
this.props.tolist
获取到list的值了,那么在父组件增加list的值,刷新state,子组件就会更新。
删除的方法绑定在子组件上,要如何去影响父组件的list呢?
这里要使用回调了,首先在子组件的每一项上绑定相应的方法
<span onClick={this.delList} data-id={index}>
x
</span>
然后通过props通知给父组件
delList(e) {
let index = e.target.getAttribute("data-id");
this.props.onChange(index);
}
父组件标签部分绑定相应的方法
<List
additem={this.state.item}
tolist={this.state.list}
onChange={this.listChange}
/>
最后在方法的部分做处理即可,完整代码如下:
import ReactDOM from "react-dom";
import React from "react";
import "./index.css";
class List extends React.Component {
constructor(props) {
super(props);
this.delList = this.delList.bind(this);
}
delList(e) {
let index = e.target.getAttribute("data-id");
this.props.onChange(index);
}
render() {
return this.props.tolist.map((li, index) => {
return (
<li key={index}>
{li}
<span onClick={this.delList} data-id={index}>
x
</span>
</li>
);
});
}
}
class Todos extends React.Component {
constructor(props) {
super(props);
this.listChange = this.listChange.bind(this);
}
state = {
item: "xxx",
list: [1, 2, 3],
targetValue:'work'
};
listChange(index) {
let cur = this.state.list;
cur.splice(index, 1);
this.setState({ list: cur });
}
addItem(){
let value = this.state.targetValue;
let newlist = this.state.list
newlist.push(value)
this.setState({list:newlist})
}
getValue(e){
this.setState({targetValue:e.target.value})
}
render() {
return (
<div>
<input type='text' value={this.state.targetValue} onChange={this.getValue.bind(this)}/><button onClick={this.addItem.bind(this)}>确定</button>
<ul>
<List
additem={this.state.item}
tolist={this.state.list}
onChange={this.listChange}
/>
</ul>
</div>
);
}
}
ReactDOM.render(<Todos />, document.getElementById("root"));