Class组件
一:class方法调用当前实例的方法
- 方法写成普通函数,在onClick后绑定this也就是
this.x.bind(this)
class App extends React.Component<Props, State> {
x() {
console.log('ccc')
}
render() {
return (
<div>
<button onClick={this.x.bind(this)}></button>
</div>
)
}
}
- 方法等于一个箭头函数
class App extends React.Component<Props, State> {
x= () => {
console.log('ccc')
}
render() {
return (
<div>
<button onClick={this.x}></button>
</div>
)
}
}
通常情况下我们用第二种,但是第二种有一个缺陷:我们的方法写成普通函数的情况下,这个方法是绑定在当前实例的原型上的,所有实例公用一个方法,而我们写成等于一个箭头函数它就是就相当于在构造函数内部生成了一个私有的x方法,像下边这样
constructor(props) {
this.x = () => {}
}
只要有一个实例就会有一个x方法,所以它的缺点就是浪费内存,解决方法:无解
二:在js里指定props里的参数和类型
安装prop-types
import PropTypes from "prop-types";
class App extends React.Component<Props, State> {
// 默认的prop类型为message为字符串
static propTypes = {
message: PropTypes.string
}
}
React的计算属性
直接在属性前面写一个get就是获取当前属性也就是计算属性
interface State {
firstName: string;
lastName: string;
}
class App extends React.Component<Props, State> {
constructor(props) {
super(props)
this.state = {
firstName: 'Wang',
lastName: 'lifa'
}
}
get name() {
return this.state.firstName + this.state.lastName
}
render() {
return (
<div>
{this.name}
</div>
);
}
}
函数组件
一. 在函数组件里使用生命周期
我们需要使用useEffect api
const App: React.FunctionComponent<Props> = props => {
const [n, setN] = useState(1);
const x = () => {
setN(n + 1);
};
useEffect(() => {
console.log("aaa");
});
return (
<div>
<h1>{props.message}</h1>
<div>{n}</div>
<button onClick={x}>+1</button>
</div>
);
};
只要有数据更新就会触发这个api,如果我们想针对某一个数据的改变才调用这个api,那么需要在后面指定一个数组,数组里面是需要更新的那个值,它变了就会触发这个api
useEffect(() => {
console.log("aaa");
}, [n]);
只有在n改变的时候才会触发
如果我们想只在mounted的时候触发一次,那我们需要指定后面的为空数组,那么就只会触发一次,适合我们做ajax请求
useEffect(() => {
console.log("mounted");
}, []);
如果想在组件销毁之前执行,那么我们就需要在useEffect
里return 一个函数
useEffect(() => {
console.log("mounted");
return () => {
console.log('我死了')
}
}, []);
二:设置默认名字和默认props的操作以及参数检查
- 设置默认props
// 设置message为可选参数
interface Props {
message?: string;
}
// 设置默认的message为default message
App.defaultProps = {
message: "default message"
};
ReactDOM.render(<App />, rootElement);
问题:因为我们的message为可选参数所以可能即使我们通过js的方式指定了默认的message,但是ts还是会认为你没有message,所以如果我们直接在方法里对props.message进行操作有可能会报错
解决方法:对message做非空断言,不让ts去管它
const App: React.FunctionComponent<Props> = props => {
props.message!.split('')
}
- 设置默认的组件名
App.displayName = "Lifa";
- 通过js设置默认的props类型
import PropTypes from "prop-types";
App.propTypes = {
message: PropTypes.number
};
函数式 vs Class
- 函数式
函数式的本质:不能进行二次赋值
无状态(useState): 每次都是生成一个新的状态,之前的状态不要了
容易实现函数式
函数式的好处:可以使用数学知识
- 类
有状态(state):每次都是修改的同一个状态
很难实现函数式
面向对象的好处:适合普通人类