组件分类
函数组件
function Welcome(props) {
return <h1>Hello,{props.name}</h1>
}
// 使用
<Welcome name="frank"/>
类组件
class Welcome extends React.Component {
render() {
return <h1>Hello,{this.props.name}</h1>
}
}
// 使用
<Welcome name="Frank" />
<Welcome />
会变成一个react 语法,而不是变成HTML元素
<div />会被翻译为React.createElement('div')
<Welcome />翻译为React.createElement(Welcome)
props(外部数据)
外部数据不能写 只能读取
类子组件
this.props.xxx
// 父组件
function App() {
return (
<div className="App">
爸爸
<Son messageForSon="我是你爸爸" /> // “123”字符串或者JS表达式{a+b}
</div>
)
}
// 类子组件
class Son extends React.Component {
render() {
return (
<div className="Son">
{this.props.messageForSon}
</div>
)
}
}
函数子组件
props.xxx
// 父组件
class Son extends React.Component {
render() {
return (
<div className="Son">
{this.props.messageForSon}
<Grandson messageForGrandSon="训责你" />
</div>
)
}
}
// 子组件
const Grandson = (props) => {
return (
<div className="Grandson">
{props.messageForGrandSon}
</div>
)
}
state(内部数据)
类组件
// 声明
constructor() {
super()
this.state = {
n: 0
}
}
// 调用
n: {this.state.n}
// 更新
<buttononClick={() => {this.add()}}>
+14
</button>
add() {
// 写法一
// this.setState({ n: this.state.n + 1 }) // 重新声明一个对象
// 写法二
// 这里的n 不会立刻变 会等一会儿改变
this.setState(state => {
const n = state.n + 1
return { n }
})
}
setState(函数) 最好用这个方式 方法一里面的n 不会同步更新。
函数组件
// n 是读的值 setN 是写的值
const [n, setN] = React.useState(0)
// 读取
n:{n}
// 写
setN(n + 1) // 永远不会改变n 会产生一个新的n
类组件注意事项
this. state.n += 1无效?
其实n已经改变了,只不过UI不会自动更新而已
调用setState才会触发UI更新(异步更新)
因为React没有像Vue监听data一样监听state
setState会异步更新UI
setState之后,state 不会马上改变,立马读state会失败(读取的是旧的)
更推荐的方式是setState(函数)
this. setState(this. state)不推荐?
React希望我们不要修改旧state (不可变数据)
常用代码: setState({n: state.n+1})
函数组件注意事项
跟类组件类似的地方
也要通过setX(新值)来更新UI
跟类组件不同的地方
没有this, 一律用参数和变量
引用多个值
类组件
class Son extends React.Component {
constructor() {
super();
this.state = {
n: 0,
m: 0
};
}
addN() {
this.setState({ n: this.state.n + 1 });
// m 会被覆盖为 undefined 吗?
}
addM() {
this.setState({ m: this.state.m + 1 });
// n 会被覆盖为 undefined 吗?
}
render() {
return (
<div className="Son">
儿子 n: {this.state.n}
<button onClick={() => this.addN()}>n+1</button>
m: {this.state.m}
<button onClick={() => this.addM()}>m+1</button>
<Grandson />
</div>
);
}
}
当其中一个值修改时,另一个值会沿用上次的值,而不会被undefined覆盖。
注意类组件的setState只会合并第一层的属性不会合并下一层的属性。案例
如果要合并可以采取 Object.assign()将第上层数据拿过来。案例
const user = Object.assign({}, this.state.user);
如果要合并可以采取(…)剩余操作符将第上层数据拿过来。案例
constructor() {
super();
this.state = {
n: 0,
m: 0,
user: {
name: "frank",
age: 18
}
};
}
// 修改数据
changeUser() {
this.setState({
// m 和 n 不会被置空
user: {
...this.state.user, // 复制之前的所有属性
name: "jack"
// age 被置空
}
});
}
函数组件
const Grandson = () => {
const [n, setN] = React.useState(0);
const [m, setM] = React.useState(0);
return (
<div className="Grandson">
孙子 n:{n}
<button onClick={() => setN(n + 1)}>n+1</button>
m:{m}
<button onClick={() => setM(m + 1)}>m+1</button>
</div>
);
};
函数组件不会合并属性,案例
React事件绑定
class Son extends React.Component {
addN = () => this.setState({ n: this.state.n + 1 })
render() {
return <button onClick={this.addN}>n+1</button>
}
}