1. 组件
React 将组件看成是一个状态机,一开始有一个初始状态,和用户互动导致状态变化,从而触发重新渲染。
组件有函数式组件和类组件,组件的开头必须大写。
- 定义组件
import React, { Component } from 'react';
class App extends Component {
render() {
return (<div>
</div>);
}
}
- 类组件:一个类就是一个模块
class Produce extends Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
return (<div>
<div>商品图片</div>
<div>商品名称</div>
<div>商品价格</div>
<hr />
</div>);
}
}
- 函数式组件:一个函数就是一个组件
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = { color: "red", backgroundColor: "green" }
}
setColor = v => {
this.setState({ color: v })
}
bgColor = v => {
this.setState({ backgroundColor: v })
}
render() {
return (<div>
<h3 style={{ color: this.state.color }}>子父传参</h3>
<Ctrl setColor={this.setColor}></Ctrl>
<h3 style={{ backgroundColor: this.state.backgroundColor }}>点击更换背景颜色</h3>
<Ctrl setColor={this.bgColor}></Ctrl>
</div>);
}
}
export default App;
function Ctrl(props) {
return (
<div>
<button onClick={() => props.setColor("orange")}>橙</button>
<button onClick={() => props.setColor("green")}>绿</button>
<button onClick={() => props.setColor("lightgreen")}>青</button>
<button onClick={() => props.setColor("blue")}>蓝</button>
<button onClick={() => props.setColor("plum")}>紫</button>
</div>
)
}
自定义组件,体现出组件的复用性。
对象可以通过this.state属性读取值,当点击组件,导致状态变化,this.setState方法就会修改状态值,每次修改之后,自动调用this.render方法,再次渲染组件。
props是单向数据流,只读。
- this.props表示一旦定义,就不再改变的特性
- this.state会随着用户互动而产生变化的特性
2.表单
用户在表单填入的内容,属于用户跟组件的互动,应该用 this.state 读取
import React, { Component, createRef } from 'react';
class APP extends Component {
constructor(props) {
super(props);
this.state = {
msg: "你好,小兔子"
}
//创建一个dom引用
this.inpRef = createRef();
}
getVal = () => {
//获取表单
alert(this.inpRef.current.value)
}
changeMsg=(e)=>{
this.setState({msg:e.target.value})
}
render() {
return (<div>
{/* 受控表单-表单双向绑定 */}
<p>{this.state.msg}</p>
{/* 使用箭头函数 */}
{/* <input type="text" value={this.state.msg} onChange={e=>this.changeMsg(e)} name="" id="" /> */}
{/* 使用bind */}
<input type="text" value={this.state.msg} onChange={this.changeMsg.bind(this)} name="" id="" />
{ /*非受控表单*/}
<input type="text" name="" id="" ref={this.inpRef} />
<button onClick={this.getVal}>获取值</button>
</div>);
}
}
export default APP;
简单案例,上面代码中文本框的值,不能用this.props.value读取,而是需要定义一个 onChange 事件的回调函数,通过 event.target.value 读取用户输入的值
3.实现todolist
在开始写之前,首先进行整体分析:将 TodoList 分为一个总组件和两个子组件,子组件一个输入内容,一个显示内容列表。
import React, { Component} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
list: [
{ title: "学习vue", done: true },
{ title: "学习react", done: false },
]
}
}
delItem = item => {
//缓存list
var list = this.state.list;
//查找下标
var ind = this.state.list.findIndex(value => value.title === item.title);
//删除
list.splice(ind, 1);
//更新
this.setState({ list })
}
render() {
return (<div>
{this.state.list.map(item =>
<div className='item' key={item.title}>
<input type="checkbox" checked={item.done} />
<span>{item.title}</span>
<button onClick={this.delItem.bind(this, item)}>x </button>
</div>
)}
</div>);
}
}
export default App;
通过props完成父子组件之间的通信,这里的map方法是用到了es6中的解构赋值,然后将值一一传递到子组件中去。
通过checked修改item的状态,并通过定义方法delItem实现删除功能;
添加功能和删除功能思路是一致的。
addItem = () => {
var list = this.state.list;
var inp = this.tempRef.current;
list.unshift({ title: inp.value, done: false })
this.setState({ list })
this.tempRef.current.value = "";
}
利用list里done的值去进行已完成还是未完成的判断
checkItem = item => {
//获取缓存
var list = this.state.list;
//找到下标
var ind = this.state.list.findIndex(value => value.title === item.title);
//取反
list[ind].done = !list[ind].done;
//重置更新列表数据
this.setState({ list });
}
render() {
return (<div>
<input type="text" ref={this.tempRef} />
<button onClick={this.addItem}>添加</button>
<h3>正在进行{this.state.list.filter(item => !item.done).length}</h3>
{this.state.list.filter(item => !item.down).map(item =>
<div className='item' key={item.title}>
<input type="checkbox" checked={item.done} onChange={this.checkItem.bind(this, item)} />
<span>{item.title}</span>
<button onClick={this.delItem.bind(this, item)}>x </button>
</div>
)}
<h3>已经完成{this.state.list.filter(item => item.done).length}</h3>
{this.state.list.filter(item => item.down).map(item =>
<div className='item' key={item.title}>
<input type="checkbox" checked={item.done} onChange={this.checkItem.bind(this, item)} />
<span>{item.title}</span>
<button onClick={this.delItem.bind(this, item)}>x </button>
</div>
)}
</div>);
}
这里用filter直接进行过滤
这样就实现了简单的删除添加过筛选的功能
本地存储
// 组件渲染后调用 componentDidMount()
componentDidMount() {
var str = localStorage.getItem("list") || "[]";
//获取本地存储的数据的数据 取不到用“[]”
var list = JSON.parse(str); //转成js对象
this.setState({ list }); //更新list
}
//componentDidUpdate方法:只要页面的state或者model中的state中定义的变量值发生改变,这个方法就会执行。
componentDidUpdate(prevProps, prevState) {
localStorage.setItem("list", JSON.stringify(this.state.list));
//当数据更新的时候,把数据转换为字符串 存储
}
最后总结:
知识点
调用数据,函数,事件,父子组件
重难点
1. this与箭头函数的使用
2. 定义组件以及调用,jsx的思想
3. 父子之间的通信