如果是元素,首字母小写;如果是组件,首字母大写;这是一个约定,大家都这么写;
一、元素
const div = React.createElement('div',...)
- 上面这是一个React元素;
二、组件(以后都是优先使用函数组件)
const Div = ()=>React.createElement('div'..)
- 上面这是一个React组件;
- 目前而言,一个返回React元素的函数就是React组件;
- React组件中又分为两种,函数组件和类组件;
函数组件
function Welcome(props){
return <h1>Hello, {props.name}</h1>;
}
类组件
- 类组件中可以定义state、函数这些;
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>
}
}
添加props(外部数据)
- 函数组件直接读取参数
props.xxx
; - 类组件直接读取属性
this.props.xxx
;
添加state(内部数据)
- 函数组件用
useState
返回数组,第一项读,第二项写; - 类组件用
this.state
读,用this.setState
写;
类组件注意事项
1、this.state.n += 1
无效?
- 其实n已经改变了,只不过UI不会自动更新而已;
- React中要调用setState才会触发UI更新(异步更新);
- 因为React没有像Vue监听data那样去监听state;
2、setState后会异步更新UI
- setState之后呢,state并不会马上改变,所以setState之后立马去读取state里的值取到的还是旧值;
- 更推荐的方式是
setState(函数)
;
this.setState((state) => {
const n = state.n + 1;
return { n };
});
3、不推荐this.setState(this.state)
- 因为React希望我们不要去修改旧的state,直接setState一整个state,这个state的内存地址和旧的是不一样的!!!(因为state是不可变数据)
函数组件注意事项
1、跟类组件相似的地方
- 也是通过setN(新值)来更新UI;但是setN永远不会改变n,而是会产生一个新值;
2、跟类组件不同的地方
- 它没有
this
,一律用参数和变量;
对于复杂state(即state中不止一个变量,且变量中还有对象)
function App() {
return (
<div className="App">
爸爸
<Son />
</div>
);
}
class Son extends React.Component {
constructor() {
super();
this.state = {
n: 0,
m: 0,
user: {
name: "frank",
age: 18
}
};
}
addN() {
this.setState({ n: this.state.n + 1 });
// m 会被覆盖为 undefined 吗?
}
addM() {
this.setState({ m: this.state.m + 1 });
// n 会被覆盖为 undefined 吗?
}
changeUser() {
this.setState({
// m 和 n 不会被置空
user: {
name: "jack"
// age 被置空
}
});
}
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>
<hr />
<div>user.name: {this.state.user.name}</div>
<div>user.age: {this.state.user.age}</div>
<button onClick={() => this.changeUser()}>change user</button>
<Grandson />
</div>
);
}
}
const Grandson = () => {
const [n, setN] = React.useState(0);
return (
<div className="Grandson">
孙子 n:{n}
<button onClick={() => setN(n + 1)}>+1</button>
</div>
);
};
1、类组件中(参考上面代码)
①setState({ n: this.state.n + 1 })
时,m是不会变成undefined的;因为类组件中setState会自动合并第一层数据,不赋值的这个变量会自动沿用上一次的值,而不会被覆盖成undefined;
②但是!!!你如果单独去修改user里的name时,那么age会被覆盖为undefined!!!修改对象里的属性时,不能单独只修改那个属性,应该先把这个对象拷贝一下,即this.setState({ user: { ...this.state.user, name: 'winwin'}})
;
③也就是说你修改的是简单类型时,可以直接修改它(因为第一层数据会自动合并);但是修改的是复杂类型里的值时,你需要先把这个复杂类型先拷贝一下,再对需要修改的属性进行赋值;
2、函数组件中
①函数组件中setX完全不会自动合并,所以当用useState
声明变量时,最好不要声明成对象,下面代码的这种写法不推荐;
②如果非要声明成对象,那么setX的时候要先拷贝X才可以;
③因为setX不会自动合并数据,所以最好不要把X声明成对象!!!
const Grandson = () => {
const [state, setState] = React.useState({
n: 0,
m: 0
});
return (
<div className="Grandson">
孙子 n:{state.n}
<button onClick={() => setState({ ...state, n: state.n + 1 })}>n+1</button>
m:{state.m}
<button onClick={() => setState({ ...state, m: state.m + 1 })}>m+1</button>
</div>
);
};
三、React和Vue的编程模型
四、类组件和函数组件的优缺点
- 类组件有状态;函数组件没有状态;
- 类组件不能二次赋值;函数组件可以再次赋值;
- 类组件可以运用数学知识;函数组件适合普通人类;