前言
React框架是一个组件化的框架,为了适合大型项目的开发,React将项目分割成一个个的组件,并频繁地在组件之间传递数据。可以说要想学好React框架的使用,需要能够灵活地操作组件。本文重点介绍React组件的书写方式,并给出组件中数据与事件的处理规则。
注意:React 16.x之前的版本中,创建组件可以使用React.createClass()方法来实现,但是从React 16版本开始,该方法彻底被废弃,开始全面使用ES6中的class关键字来创建组件。在学习过程中,大家就不要再尝试React.createClass()方法了。
一、使用ES6的class关键字创建组件
React使用ES6的class关键字创建组件的语法格式如下所示。
class 组件名 extends React.Component{
render(){
return (
//JSX元素
)
}
}
上述格式在书写时有以下格式要求:
- 组件名的首字母必须大写。
- 必须具备render()函数。
例1:创建一个名为App的组件,该组件显示一个h2标题和具有3个列表项的无序列表。
class App extends React.Component{
render(){
return (
前端开发的三大框架
- React
- Vue.js
- Angular
)
}
}
ReactDOM.render(
,
document.querySelector("#app")
)
从上述代码中可以看出,组件名App可以出现在ReactDOM.render()函数的第一个参数中,既可以是标记对的格式(
可以看出,有两个React属性在组件中非常常用:
- React.Component:所有的自定义组件都继承React.Component。
- React.Fragment:作为自定义组件的唯一根节点,并在DOM结构中不渲染。
为了简化上述两个属性的调用,我们可以使用ES6对象解构的格式在项目开头对其进行声明:
const {Component,Fragment} = React;
我们用这种方法再带领大家创建一个组件。
例2:创建一个名为App的组件,该组件遍历数组形成5个超级链接。
const {Component,Fragment}=React;
let linkText=["百度","腾讯","新浪","网易","谷歌"];
let linkUrl=[
"https://www.baidu.com",
"https://www.qq.com",
"https://www.sina.com.cn",
"https://www.163.com",
"https://www.google.com"
];
class App extends React.Component{
render(){
return (
{
linkText.map((item,index)=>{
return {item}
})
}
)
}
}
ReactDOM.render(
,
document.querySelector("#app")
);
二、为组件设置状态区
根据ES6语法规定,使用class定义的React组件本质上是一个类,ES6允许在类的内部为类设置一个构造函数,在这个构造函数内部可以为整个React组件设置状态区(state)。学习过Vue.js框架的小伙伴们可以将其理解为Vue实例的数据区(即data部分)。
语法格式如下所示。
class 组件名 extends React.Component{
constructor(props){
super(props);
this.state={
//声明状态区数据
}
}
}
例3:组件Student的状态区有两个数据,标题title和学生信息info,利用状态区的数据在页面中生成展示学生信息的表格。
const {Component,Fragment}=React;
class Student extends Component{
constructor(props){
super(props);
this.state={
title:'小海前端2059期学员名单',
info:[
{name:'张三', sex:'男', age:24, phone:'159xxxxxxxx'},
{name:'李四', sex:'女', age:22, phone:'139xxxxxxxx'},
{name:'王五', sex:'男', age:25, phone:'157xxxxxxxx'}
]
}
}
render(){
return (
{this.state.title}
姓名 性别 年龄 联系电话
{
this.state.info.map((stud,index)=>{
return (
{stud.name}
{stud.sex}
{stud.age}
{stud.phone}
)
})
}
)
}
}
ReactDOM.render(
,
document.querySelector("#app")
);
从上述代码中可以看出,在JSX语法结构中引用state区中的数据要使用 this.state 的格式来实现。
大家思考一个问题:这里的this指向什么呢?
class Student extends Component {
constructor(props){
super(props);
this.state={
//定义state区数据
}
}
render(){
console.log(this);
return (
//JSX语法结构
);
}
}
上述代码在render()函数中利用console.log()结构将this的内容输出到控制台中,最终的输出结果如下图所示。
从这个图中可以看出,组件中的this关键字总是指向这个组件本身,并且可以通过this.state调用组件状态区中的数据。
那么如何修改组件state区中的数据呢?这里需要用到this.setState()方法来实现,格式如下所示。
this.setState({
数据名:取值
})
让我们先为大家讲解如何为组件中的元素绑定事件,然后在事件触发时再来修改state区中的数据。
三、为组件中的元素绑定事件
在React中,一般采用元素属性的方式来为其绑定事件。事件类型名采用on-开头,后面的事件单词采用首字母大写的形式来书写。
- 单击事件:onClick
- 鼠标经过事件onMouseOver
- 鼠标离开事件onMouseOut
- 获得焦点事件:onFocus
- 释放焦点事件:onBlur
例4:创建Exam组件。页面中有一个按钮,单击按钮改变state数据区中名为frame的数据取值。
const {Component,Fragment}=React;
class Exam extends Component{
constructor(props){
super(props);
this.state={
frame:'Vue.js'
}
}
changeData(){
this.setState({
frame:'React'
})
}
render(){
return (
你好,{this.state.frame}
)
}
}
ReactDOM.render(
,
document.querySelector("#app")
);
大家仔细观察为button按钮绑定单击事件的句子:
该句的本质是定义了一个名为changeData()的函数,让按钮的单击事件触发时执行这个函数。但是,在函数中this关键字就不指向组件本身了。为了让函数内部的this也只想组件本身,必须在JSX语法结构中调用函数时使用bind(this)来保证this关键字在函数中的指向。
如果在事件函数内部使用不到this关键字,那么在调用函数时就可以不使用bind(this)了。
例5:创建组件Box。在页面中有一个矩形容器,当鼠标经过时让其改变背景颜色(#ff5857),鼠标离开时恢复原有的背景颜色(#3385ff)。
const {Component,Fragment}=React;
class Box extends Component{
constructor(props){
super(props);
this.state={
bgc:'#ff5857'
}
}
mouseOver(){
this.setState({
bgc:'#3385ff'
})
}
mouseOut(){
this.setState({
bgc:'#ff5857'
})
}
render(){
return (
)
}
}
ReactDOM.render(
,
document.querySelector("#app")
);
上述代码中的div,类名box负责设置容器的宽度和高度,style属性负责设置背景颜色,同时背景颜色使用了一个state区中名为bgc的数据来设置。当鼠标经过这个容器时利用this.setState()方法改变bgc的取值为#3385ff;当鼠标离开这个容器时利用this.setState()方法改变bgc的取值为#ff5857。
四、确保组件方法中的this指向组件本身
前面的例子我们是采用bind(this)的方法来保证组件中方法内部的this指向组件本身的。本小节为大家总结其他的实现方法。
1、调用方法时使用bind(this)来改变方法内部this的指向。
2、在构造函数中注册方法。
也可以在构造函数中将这个方法利用bind(this)注册一遍,这样在调用时就不需要在改变this的指向了。
constructor(props){
super(props);
this.state={ //定义state区数据 };
this.btnClick=this.btnClick.bind(this); //在构造函数中重新注册方法
}
3、在调用方法时使用箭头函数。
也可以在调用方法是直接使用箭头函数,这样也可以解决方法内部this的指向问题。
上述三种方法都可以实现对事件函数的调用,同学们可以在例3或例4的基础上改变调用方法的方式,自行演示上述方法的可行性。
总结
本文是React系列教程的第三篇文章,主要为大家讲解了React组件的书写方式。同时还讲解了组件状态区的使用、为组件元素绑定事件等。明天会为大家系统的讲解React组件数据之间的传递。
关于作者
小海前端,具有18年Web项目开发和前后台培训经验,在前端领域著有较为系统的培训教材,对Vue.js、微信小程序开发、uniApp、React等全栈开发领域都有较为深的造诣。入住Segmentfault,希望能够更多的结识Web开发领域的同仁,将Web开发大力的进行普及。同时也愿意与大家进行深入的技术研讨和商业合作。