React组件名首字母必须为大写
一、组件类型
(一)函数组件
- 函数组件(无状态组件,UI组件):
是一个纯函数,只用组件展示,组件只负责根据外部传入的 props 来展示,书写更简洁,执行效率更高(推荐)
默认没有this
>例子:
function Home(){
return(
< div></ div>
)
}
函数内必须要有return
(二)类组件
- 类组件(状态组件)
(状态就是一些可变的数据,当数据改变,就会自动刷新组件:重新执行一遍render)
类组件有更丰富的特性,如:state 状态、生命周期、this 等
>例子:
class Nav extends React.Component{
render(){
return (
< div></ div>
)
}
}
必须继承自React.Component
必须包含render(){}方法
- React 类组件拥有自己的状态 state,state 状态改变时自动刷新组件(执行组件中的 render 方法)
>例子:
class Nav extends React.Component{
constructor() {
super(); // 调用super后才能使用this
this.state = { }
}
render(){
return (
< div></ div>
)
}
}
- 获取:this.state.xxx
- 修改: this.setState()
修改state的原则:创建一个新的数据并覆盖它
this.setState({
datalist:newData
})
- 默认只有construtor、render、生命周期函数中可以直接使用this,自定义的函数需要手动绑定(下面会进行优化)
> 例子:
class Nav extends React.Component{
constructor() {
super(); // 调用super后才能使用this
this.state = { }
// 给自定义函数绑定this
this.addItem = this.addItem.bind(this);
}
//自定义方法
addItem(text){
const {datalist} = this.state;
this.setState({
datalist:newData
})
}
render(){
return (
<div>
<TodoForm addItem={this.addItem} />
</div>
)
}}
(三)受控组件与非受控组件
- 受控组件:表单元素的值与组件的state进行绑定
- 非受控组件:传统节点操作
二、组件通讯
- props:类组件与函数组件都适用
函数组件:通过函数的第一个参数访问|
类组件:通过this.props访问
(类组件中的 constructor的第一个参数也是Props : constructor(props) {})
(一)父子通讯:props
1、父传子:props
(1)父组件操作:给子组件定义属性并传递数据
例子:
function TodoList() {
let datalist = [
{ id: 1,
text: "早点睡觉",
done: false,
date: new Date()
},
]
return (
<div>
<TodoContent datalist={datalist} />
<TodoForm />
</div>
)
}
(2)子组件操作
- 函数组件:函数的第一个参数为props
例子:
function TodoContent(props) {
return (
{ props.datalist.map((item) => {
return <TodoItem item={item} />
})
}
)
}
- 类组件:this.props
例子:
class TodoForm extends React.Component{
constructor(props) {
super(); // 调用super后才能使用this
this.state = { }
}
submitItem() {
if (this.state.text) { // 对文本框有无值进行判断
this.props.addItem(this.state.text); //传输文本框中的值
this.setState({
text: '', //清空文本框
})
} else {}
render(){
return (
<div>
<button onClick={this.submitItem}>确定</button>
</div>
)
}
}
2、子传父:props(把父组件的方法通过props传递到子组件中执行)
(1)父组件操作:给子组件定义属性并传递方法
例子:
function TodoList() {
let datalist = [
{ id: 1,
text: "早点睡觉",
done: false,
date: new Date()
},
]
removeItem(id) {} //方法
return (
<div>
<TodoContent removeItem={this.removeItem} />
</div>
)
}
(2)子组件操作:执行传入的方法并传递数据
例子:
function TodoItem({ item, removeItem}) {
return (
<tr>
<td>
<button onClick={removeItem.bind(null, item.id)}>删除</button>
</td>
</tr>
)
}
(二)兄弟组件通讯:状态提升
- 把状态(数据)放到两个组件共同的父级
(三)多层次组件通讯
1、props 逐层传递(不推荐)
- 从上到下,所有的组件都要帮助传递这个 props 到目标位置
- 缺点:操作繁琐、难以维护
2、context 组件共享
所谓 context,就是上下文环境,某个组件只要往自己的 context 里面放了某些状态,这个组件之下的所有子组件都能直接访问这个状态,实现步骤如下:
(1)第一步:创建 Context:
let defaultValue = { username: "laoxie" };
**let MyContext = React.createContext(defaultValue);**
MyContext.Provider,如父组件没有共享数据,子组件获取时得到初始化数据
(2)第二步:父组件共享数据( Provider)
-
父组件往Context中存入数据并提供给它的子组件使用
-
let data = {username:‘jingjing’}
<MyContext.Provider value={data} >
< App/>
</MyContext.Provider> -
组件App下的所有子组件都能获取到data数据,如父组件未设置 Provider,子组件接收时得到 defaultValue 的值
(3)第三步:子组件接收数据
- Consumer
<MyContext.Consumer>
{
(value) => {
return(
//各个子组件跟数据
)
// 回调函数中获取value值
}
}
</MyContext.Consumer>
- ContextType
只适用于类组件,需要给类组件添加一个静态属性
例子:
class TodoForm extends Reaact.Component{
//this.context
}
TodoForm.contextType = MyContext
只适用于类组件,通过this.context获取
SubComponent.contextType = MyContext;
this.context.username; //jingjing