2022-10-06
- 上面的代码中,reactjs是react的核心库,用于定义组件规范,reactdom是渲染器用于创建组件和管理组件。proptypes传递给组件的数据做类型检查。React.createElement创建了一个react元素。
React.createElement( type, [props], […children] )
- 然后使用ReactDom.render将创建的react元素渲染到div#root中
- react使用虚拟dom挂在到真实的dom中。而react通过将全部 children 属性进行求值,并将结果传递给父元素的方式,对虚拟dom中的所有结构的每个细节构建为一棵完整的树,
- react除了需要 拓展元素的功能演示和其他UI相关,需要使用到react组件,组件相比于react元素拥有更多的特性,React.Component是将react元素和函数组织到一起的类。
class MyComponent extends React.Component {
// 必须定义 render()。否则会报错:
// MyComponent(…): No render method found on the returned component instance: you may have forgotten to define render.
render() {
// 返回单个 React 元素或 React 元素的数组
return reactElem
}
}
每个组件知道需要定义一个render()方法,几乎任何向屏幕显示内容的组件都带有render方法。
显示的结果如下,其中this.props获取了传递的属性。
react的MyComponent没有初始化this.props,并不是自己没有初始化,而是父类帮忙进行初始化了。一般在js和java中获取父类的构造器并获取数据需要使用super(),否则就会报错。
// 控制台输入如下代码,报错 // Uncaught ReferenceError: Must call super constructor in derived class before accessing ‘this’ or returning from derived constructor // Uncaught ReferenceError:在访问“this”或从派生构造函数返回之前,必须在派生类中调用超级构造函数,否则就会报错 class A{} class B extends A{ constructor(){
} } let b = new B() ``` - 如果不初始化state或不进行方法绑定,则不需要为react实现构造函数。通常,构造函数用于下面两种情况:1. 通过this.state 赋值对象来初始化内部state2.为事件函数绑定实例 - 类型检测,通过组件创建html元素,并利用propType验证所使用的属性。 ``` <script>
class MyComponent extends React.Component {
...
}
// 属性类型
MyComponent.propTypes = {
cnt1: PropTypes.number,
// 注:函数不是 function,而是 func
// 函数类型,并且必填
func: PropTypes.func.isRequired
}
// 默认值
MyComponent.defaultProps = {
cnt1: 'defaultName'
} </script> ```
Count.propTypes = {
basicObject: PropTypes.object,
numbers: PropTypes.objectOf(PropTypes.numbers),
messages: PropTypes.instanceOf(Message),
contactList: PropTypes.shape({
name: PropTypes.string.isRequired,
phone: PropTypes.string.isRequired,
}),
};
可以为父类添加validate函数判断子类的类型名和定义的是否相同
## 嵌套组件
- this.props 对象的属性与组件的属性一一对应,但其中有一个比较特殊的参数:this.props.children。它表示组件所有的子节点。
- 如下例,一个 span 标签在 Parent 中作为Child的子节点传入,可在 Child 中通过 this.props.children 取到:
class Parent extends React.Component {
render() {
return (
- 从而实现类似于vue中的插槽的功能
return ( <div> <div>{this.props.children[2]}</div> <div>{this.props.children[1]}</div> <div>{this.props.children[0]}</div> </div> )
- prop.child通过PropTypes.element进行类型检查
- React.Children.map(object children, function fn)会字每一个子节点上调用fn函数,并返回一个对象
- React.Children.forEach仅仅调用fn,不进行返回。
- React.Children.count统计了children中的组件总数
- React.Children.only返回 children 中仅有的子节点
## 动态组件
- React通过render渲染了最终拼接的react element,通过react 组件可以实现信息在element之间更好的传递,并提高了element的 复用性,但是这些仅仅对于静态文案。
- 状态可以帮助解决动态组件的问题this.state。
- 通过 this.state 访问的是可变状态;通过 this.props 访问的是不可变状态
- state 和 props 是数据的传输工具,这些数据构成应用并使其有用。
- State 与 props 类似,但是 state 是私有的,并且完全受控于当前组件 —— 官网
- react 中的 props 用来接收父组件传来的属性,state 是私有属性
- 应该在什么时候使用 state?想要改变存储在组件中的数据时。
- ```
- class MySubComponent extends React.Component {
constructor(props){
// 如果不需要使用 this.props,则可以是 super()
super(props)
// 在构造函数中访问 this 之前,一定要调用 super(),它负责初始化 this
this.state = {age: 18}
}
render() {
const c = React.createElement
return React.createElement(
'form',
{ className: 'sub-class' },
c('p', { },
c('input', {type: 'text', value: this.state.age})
),
c('p', { },
c('input', {type: 'submit', value: 'submit'})
),
)
}
}```
- state不能直接修改, react 中this.setState()) 来更新 React 类组件中的状态。
class Clock extends React.Component { constructor(props) { super(props) this.state = { date: new Date() } // bind() 方法会返回一个新的函数,里面绑定 this,否则 tick() 报错如下: // Uncaught TypeError: this.setState is not a function setInterval(this.tick.bind(this), 1000) } tick() { // 通过 setState 修改 state this.setState({ date: new Date() }) } render() { // … 不变 } } ```