如何编写一个React组件
在React的世界里,通常是用class
来声明一个组件的,它必须继承自React.Component
。
例如下面的代码:
// MyFirstComponent.jsx
class MyFirstComponent extends React.Component {
state = {
text: "Hello React"
};
/** 组件生命周期钩子函数:在组件挂载完成后立即被调用 */
componentDidMount() {
alert("组件挂载完成!");
}
render() {
return (
<div>{this.state.text}, I am {this.props.author}!</div>
)
}
}
export default MyFirstComponent;
// index.js
import MyFirstComponent from "MyFirstComponent";
/** 渲染结果:<div>Hello React, I am Shaye!</div> */
ReactDOM.render(<MyFirstComponent author="Shaye"></MyFirstComponent>, document.getElementById("app"));
以上就是一个常规的React组件编写方式,不过我们还可以通过观察上面的代码,发现几个有趣的地方:
-
MyFirstComponent
中有一个函数componentDidMount
是组件生命周期钩子函数。实际上React为组件设计了一系列的生命周期钩子函数 -
MyFirstComponent
中有一个特别的函数render()
,这个函数把类似html
的模板内容jsx
作为返回值。这是一个必须定义的函数,否则React
将抛出错误 -
jsx
乍看之下像是一种模板引擎,实际上是一种JavaScript
的语法扩展,它的核心理念就是著名的all in js
,它完全是在JavaScript
内部实现的,它和传统的模板引擎一样,也可以绑定js
表达式 -
jsx
绑定的数据可以很明显地看出来自两个对象:this.state
和this.props
;this.state
是MyFirstComponent
内部自定义的组件状态;this.props
是外部凭借标签属性的形式传进MyFirstComponent
内部的数据,类似于函数的传参;
总结来说,当你掌握了 组件生命周期 JSX 组件状态state 组件属性props ,你就知道该如何编写React组件了。
组件生命周期
官方文档已经有非常详尽的介绍,这里不再赘述,请点击这里查看组件生命周期的官方文档。
JSX
你可以任意地在JSX
当中使用javaScript
表达式,在JSX
当中的表达式要包含在大括号里。
例如下面的代码:
<div className={this.state.clname} style={{ fontSize: "20px" }}>{this.state.content} forever</div>
JSX
里的React元素,比如div
,最终都会被编译器转译,被某些特定函数处理变成一个轻量的javascript object
。比如上面提到的元素div
最终会变成如下的object
:
// 注意: 以下示例是简化过的(不代表在 React 源码中是这样)
const divElement = {
type: "div",
props: {
// this.state.clname的值
className: "love",
style: {
fontSize: "20px"
},
// "you"为this.state.content的值
children: ["you", "forever"]
}
}
React就是通过读取这些对象来操作DOM
并保持数据内容一致。所以,实际上你依然在写js
。所以,class
和style
必须使用在js
中的写法
比如:class
=> className
再比如:font-size: 20px;
=> { fontSize: "20px" }
特别地,React元素的属性仍然可以像原生html
一样使用引号来定义以字符串为值的属性,例如:className="my-claname"
除了以上所提,JSX
的事件绑定与原生html
也有一些语法上的不同:
- React的事件命名采用驼峰式写法,而不是小写。
- React事件绑定的必须是一个函数对象,不能是字符串。
代码示例:
<div onClick={this.handleClick}>我是一个按钮</div>
// 也可以向事件回调函数传递参数
<div onClick={(params) => this.handleClick(params)}>我是一个按钮</div>
组件状态state
state
是私有的,完全受控于当前组件。既然是状态,那么就会有更新的需求,如何更新呢?
代码示例:
// 对`this.state`或者它的属性直接`=`赋值,将永远不会触发组件渲染,必须使用`setState()`
// 在组件的生命周期钩子函数中调用this.setState()
componentDidMount() {
this.setState({
content: "lalalala"
})
}
// 在组件的自定义函数中调用this.setState()
handleClick = () => {
this.setState({
content: "uauauaua"
})
}
setState()
是React中唯一一个动态更新组件的途径,当它被调用之后,自身组件以它的所有子组件都将触发重渲染
特别地,state
同样也可以作为属性传递给子组件;setState()
详细文档
组件属性props
props
是父组件传递下来的数据,一般是来自父组件的state
或者组件的其他成员变量。并且,props
是只读的,组件永远无法修改自己的props
。只有在父组件调用setState()
之后才能使子组件的属性发生变化并重新渲染。props
只能从上往下传,组件也只能修改自身私有的state
,意味着整个应用的数据流只能是自上往下的单向数据流
总结
组件生命周期 JSX 组件状态state 组件属性props 再加上一个自上而下的单向数据流,这些便是React组件最基本的特点了吧!