1. 函數式和類式
1.1 Code
- 函数式写法更加简洁和思维导向,适用
于无状态、UI纯粹的组件,且可以使用Hooks处理副作用。 - 类式写法适用于有
内部状态、生命周期方法和复杂交互逻辑的组件,提供了更多的灵活性和控制力。
函數式寫法
- 方法名就是組件名
import React, { useState } from 'react';
const CounterFunctional = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
return (
<div>
<h2>Counter (Functional)</h2>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
};
export default CounterFunctional;
類式寫法
- 類名就是組件名
- 必須繼承React.Component
- 必須有render方法,而且有返回值
import React from 'react';
class CounterClass extends React.Component {
//直接把變數放入state
state = {
count: 0,
}
//這種寫法相當於賦值,給這個類添加了一個屬性increment
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<h2>Counter (Class)</h2>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
export default CounterClass;
笨重寫法,需要bind修改this的指向
import React from 'react';
class CounterClass extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
this.increment = this.increment.bind(this)
}
increment() {
this.setState({
count: this.state.count + 1,
})
}
render() {
return (
<div>
<h2>Counter (Class)</h2>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
export default CounterClass;
1.2 Diff
狀態管理:
- 函数式组件可以使用React Hooks,如
useState、useReducer等来管理状态和订阅等行为。 - 类组件可以通过
state属性来存储和更新内部数据,this.state初始化、this.setState更新。
生命週期:
- 函數式組件使用
useEffect鉤子來處理組件掛載 - 类组件具有一系列生命周期方法(如
componentDidMount、componentDidUpdate等),可以在特定的时刻执行一些操作,例如数据获取、订阅和清理等。
1.3 useState
useState 以及任何其他以“use”开头的函数都被称为 Hook
const [count, setCount] = useState(initialCount)
- 它返回一个状态和一个狀態更新函數;
initialCount是我们传入的一个初始状态,它是惰性的,我们可以通过传一个函数来返回一个值当作初始状态,并且这个函数只会在初始渲染时执行一次;
回購頭來看,前面函數式編程代碼
//定義了一個變量count = 0
//定義了一個方法setCount
const [count, setCount] = useState(0)
const handleClick = () => {
setCount(count + 1)
// 使用新值调用状态更新器函数setState(newState)更新状态。
//也可以使用一个回调setState(prev => next)来更新狀態,該回調將返回基於先前狀態的新狀態
// setCount(count => count + 1)
}
handleClick();
userState注意事項:
- 仅顶层调用 Hook :不能在循环,条件,嵌套函数等中调用useState()。
- 在多个useState()调用中,渲染之间的调用顺序必须相同。
- 必须仅在函数组件或自定义钩子内部调用useState()。
2. 組件實例的三大核心屬性
下面的三件套都是對類組件說的,函數式組件沒有this
2.1 state
1.重點:State對每一個組件來說,是隔离且私有的
state是組件最重要的屬性,裡面的內容是多個key-value組合
2.注意:組件自定義的方法中this為undefined,如何解決?
- 通過bind(this)強制修改this指向
- 使用箭頭函數,this指向父級
3.修改state值
使用this.setState({key:value})來修改。
export default class xxxxPopup extends React.Component {
constructor(props) {
super(props)
this.state = {
Entity: {
name: '',
desc: '',
}
}
}
OnSubmit =() => {
console.log(this.state.subdomainEntity)
}
render() {
return (
<CRow>
<CCol xs="12" md="12">
<CCardHeader>
<CNavbarBrand className="glossay-madal-header">
<p>
<div>
<strong>New Domain</strong>
</div>
<div>
<p>Create a new SubDomain</p>
</div>
</p>
</CNavbarBrand>
</CCardHeader>
</CCol>
</CRow>
)
}
}
2.2 props
父子組件傳值
Father.js是父组件,Header.js是子组件
import React from 'react';
import Header from './Header';
class Father extends React.Component {
constructor(props) {
super(props);
this.state = {
title: 'hello qing',
num: 123//num如果是字符串的话,控制台会报错,因为子组件设置了Header.propTypes
};
}
run = () => {
alert('我是父组件run方法');
}
getDate = () => {
alert(this.state.title);
}
//获取子组件传过来的数据
getSonData = (result) => {
alert(result);
}
//父组件调用子组件的数据和方法
getSonRun = () => {
// alert(this.refs.footer.state.sonmsg);
this.refs.footer.run();
}
render() {
return (
// 父组件可以传值,也可以传方法给子组件,还可以把整个父组件传给子组件
<div><Header title="haha" run={this.run} father={this} ref='footer' num={this.state.num} getSonData={this.getSonData}>header中间的文字对应props.children</Header>
<hr />我是父组件内容
<br />
<button onClick={this.getSonRun}>获取整个子组件</button>
</div>
);
}
}
export default Father;
import React from 'react';
import Proptypes from 'prop-types';
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
sonmsg:'header----sonmsg'
};
}
getFathMsg=()=>{
alert(this.props.father.state.title);
}
run=()=>{
alert('我是子组件的run方法');
}
render() {
return (
<div>
<h1>{this.props.children}</h1>
<h2>{this.props.title}---我是子组件内容</h2>
<button onClick={this.props.run}>调用父组件中的run方法</button>
<button onClick={this.props.father.getDate}>调用父组件中的getDate方法</button>
<button onClick={this.getFathMsg}>获取父组件中state中的title属性</button>
<button onClick={this.props.father.getSonData.bind(this,'我是子组件传过来的')}>子组件给父组件传值</button>
<button onClick={this.props.getSonData.bind(this,'我是子组件传过来的222')}>子组件给父组件传值2</button>
</div>
);
}
}
//defaultProps:如果父组件调用子组件时,不给子组件传title属性,那么就在子组件中使用defaultProps定义的默认值
Header.defaultProps={
title:'标题'
}
// propTypes:验证父组件传值类型的合法性,Proptypes.number中的Proptypes名称可以自己定义,与上面引入的名称一致即可
Header.propTypes={
num:Proptypes.number
}
export default Header;