props
当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。
props只读,无论是类式组件还是函数式组件,都不能修改props属性
import React, {Component} from 'react';
import { render } from 'react-dom';
//React V15.5 props类型检查从react核心库分离 原来PropTypes是React核心库的内容
import PropTypes from "prop-types";
class HelloWorld extends Component { //类式组件
//在类内部添加static属性:给类本身增加属性
//在类内部添加非static属性:给类的实例对象增加对象属性 常用于初始化
//在类中进行static限定
static propTypes = {
name:PropTypes.string.isRequired,
},
static defaultTypes = {
name:'Li Hao',
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
//类型检查 在类外进行限定
HelloWorld.propTypes = {
name:PropTypes.string.isRequired,
}
//对属性指定默认值
HelloWorld.defaultTypes = {
name:'Li Hao',
}
// 加载组件到 DOM 元素 mountNode
render(<HelloWorld name="Lihao"/>, document.getElementById('#root'));
props.children
class HelloWorld extends Component { //类式组件
render() {
return <div>Hello {this.props.children}</div>;
}
}
//JSX
<HelloWorld>xxx</HelloWorld>
// 此时HelloWorld组件标签中的内容会被当作this.props.children 交给组件使用
state
UI = render(state)
React 把组件看成是一个状态机(State Machines)。只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
class HelloWorld extends React.Component {
constructor(props) { //构造函数
super(props); //入参接收props必须调用super(props),否则会有意想不到的bug
this.state = {date: new Date()};//构造器初始化组件状态(state)
}
this.state = {date: new Date()}; //初始化组件状态(state) 给类的实例对象增加属性
// 在官方设计中 state的初始化应该在构造器constrcutor中执行
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
更新state
//JavaScript Function
//setState()接收两个参数,第一个是状态对象或者状态更新函数,第二个为执行完毕的回调函数
this.setState(
{attr1:'attr1'} //state Object
(preState,props)={ //state update function
return {attr1:preState.attr1 + 'new'} //状态更新函数 返回一个新的state对象
}
,()=>{ //setState执行结束,立刻执行
console.log(this.state.attr1)
})
//不能直接更新state
this.state.date = new Date() //错误示例
this.setState({date:new Date()}) //正确示例
//setState异步执行 为了优化性能,React会将多个setState()合并成一个调用
//如果更改的state的值并且马上要用到更改之后的值 可能获取不到想要的数据
this.state = { count: 0 }
incrementCount() {
this.setState({
count: this.state.count + 1,
});
}
handleIncrement = () => {
this.incrementCount();
//x2 代码目的累加3次 无法实现
}
/*
需要改为回调函数形式的setState()
区别在于:传入更新函数时,就可以访问当前状态值。
setState调用是 批量处理的,因此可以让更新建立在彼此之上,避免冲突。
*/
incrementCount() {
this.setState((prevState) => {
return {count: prevState.count + 1}
});
}
refs
refs是组件内部的引用集合(reference set),收集组件内部被ref标记的标签或者其他自定义组件,以供使用
在JSX中对组件||标签进行ref标识,就会在组件的refs属性中收集到。
class HelloWorld extends Component {
constructor(props) {
super(props);
this.ref3 = React.createRef(); //React v16.3新增api 用于处理ref
}
getRefs(){ //处理ref的函数
let ref1 = this.refs.ref1.value
let ref2 = this.ref2.value
let ref3 = this.ref3.current.value
}
render() {
return
<div>
<input ref="ref1" /> //字符串形式ref
<input ref={(ref2)=>{this.ref2 = ref2}} /> //回调函数形式ref
//初次渲染时,ref的回调函数触发,入参即位当前DOM节点 将DOM传给ref2
<input ref={this.ref3} /> //createRef形式ref
//参考官方文档 Refs转发
//我们通过调用 React.createRef创建了一个 React ref并将其赋值给ref变量。
//我们通过指定ref为JSX属性,将其向下传递给React组件。
//React传递ref给forwardRef内函数 (props, ref) => ...,作为其第二个参数。
//我们向下转发该ref参数到,将其指定为JSX属性。
//当ref挂载完成,ref.current 将指向DOM节点。
//简单来说,createRef创建的的ref会通过React.forwardRef((props,ref)=>{/*JSX*/})
//这样,ref就被向下转发到具体的组件中 可以binding到具体的对象上
</div>;
}
}
参考
- https://www.kancloud.cn/simon_chang/react/241064 通过PropTypes 进行类型检查
- https://juejin.cn/post/6989941495654514718
- https://es6.ruanyifeng.com/#docs/class Subtitle—静态属性
- https://react.docschina.org/docs/state-and-lifecycle.html React官方文档—state
- https://segmentfault.com/a/1190000015463599 setState() 解析
- https://react.docschina.org/docs/forwarding-refs.html refs转发
- https://juejin.cn/post/6963156767937134622