当前位置: 首页 > Web前端 > HTML5

玩转React(四)——新建HTML标签

时间:2023-04-05 23:50:16 HTML5

第二篇《新型前端开发方式》说React有一个很酷的地方就是给了我们创建HTML标签的能力,所以今天的文章来解释一下详细介绍了React如何提供此功能,以及作为前端开发人员如何使用它。在第三篇《JavaScript代码里写HTML一样可以很优雅》中介绍了JavaScript的扩展语法JSX。相信你已经知道,所谓的创建新HTML的能力,其实就是用一种非常像HTML的JSX语法来使用基于React的视图层组件。.那么,要完成今天的任务,我们只需要搞清楚一个问题:如何基于React编写视图层组件。内容概要组件的定义有两种方式:类继承组件和功能组件。类继承组件特性更丰富,功能组件编写更简洁,执行更高效。组件名称的首字母应大写。属性是组件的外部输入。可以通过{}用任何JS表达式设置属性值。属性是只读的。属性可以设置默认值。属性是可以类型化的,React会在开发过程中对属性进行类型检查。为组件的所有属性设置类型检查是一种很好的做法,这有助于协同开发。通过内容总结,您可以快速了解本文内容是否对您有用,从而决定是否继续阅读,节省您的时间也是一件很有意义的事情。定义组件的几种姿势这里介绍几种在React中定义组件的方式。1.类继承有Java等面向对象开发经验的同学肯定很容易接受这种方式。ES6为JavaScript添加了类和类继承的特性。子类会继承父类的“基因”(成员方法、属性)。父类是组件,子类自然也是组件。React提供了两个父类,Component和PureComponent。它们之间有一点点区别,我们会在后面的文章中详细介绍。现在您可以将它们视为相同并暂时忽略它们。通过继承React提供的组件基类,我们可以创建这样的组件:importReact,{Component}from'react';classHelloMessageextendsComponent{render(){return

Helloworld.
;}}通过类继承创建组件,只需要继承Component基类,实现render方法即可。然后你就可以把HelloMessage当做一个新的“HTML标签”,你可以这样渲染到页面中:ReactDOM.render(,document.querySelector('#root'));你也可以用它来组装其他组件,例如:importReact,{Component}from'react';classHelloMessageListextendsReact.Component{render(){return(
)}}当然这个例子没有任何实际意义,只是为了演示组件的定义和用法。演示代码:https://codepen.io/Sarike/pen...二、函数式组件函数式组件顾名思义,以函数的形式定义一个组件,如下:importReactfrom'react';functionHelloMessage(){return
Helloworld.
;}//或者:constHelloMessage=()=>
Helloworld.
;其实它只是实现了类继承方法render方法。示例代码:https://codepen.io/Sarike/pen...类继承vs函数式组件这两种定义组件的方式在实际开发中经常会用到。对于大多数人来说,class继承方式的使用频率会更高。与函数式组件相比,类继承的方法写起来有点麻烦,但是它有更多的特点:,而且性能更好,不用处理一些复杂的特征,执行效率当然高。现在你不需要关心状态和生命周期函数的具体功能。我将在下一篇文章中详细解释。看完下一篇文章,选择哪种方式的问题就迎刃而解了。在开发一个组件的时候,我是这样做的:当我一开始就知道这个组件会用到状态或者生命周期函数时,毫无疑问,我会直接使用类继承;如果我一开始不使用这些功能我不确定以后是否会用到,所以我会先使用功能组件。如果随着业务的发展,组件需要应用这些特性,我会重构为一个类的继承方法。这次重构很简单,就是将原来的函数改成组件类的render方法即可。另外,还有一点需要注意,无论哪种方式,组件名称的首字母必须大写。严格来说,是JSX要求自定义组件名的首字母必须大写。如果以小写字母开头,React会将其视为内置组件,直接将其渲染为html标签,这将无法正确渲染用户自定义组件。定义的组件。如果必须以小写字母开头的组件名称,在JSX语法中使用它之前,还必须将其分配给以大写字母开头的变量,如下所示:functionhelloMessage(){return
Helloworld.
}constHelloMessage=helloMessage;ReactDOM.render(,mountNode);不过何必呢,纯属自找麻烦,实际开发项目的时候,组件名以大写字母Can开头即可。属性React中定义组件的两种方式在上面就说完了。在上面的例子中,我们定义的组件都是静态的。但是在实际开发中,视图层组件经常更新频繁,或者需要从后端API获取动态数据显示在组件中。这就要求组件具有接收外部输入的能力。属性是组件的输入。在第二篇《新型前端开发方式》中说“视图是数据的映射”,所以里面说的数据指的是属性。如果把组件理解为函数,那么属性就是函数的参数,函数的返回值就是呈现在页面上的视图。并且通过上面部分的学习,在React中,组件确实可以通过函数的形式来定义,函数的参数是一个包含了当前组件接收到的所有属性的对象。具有属性名称的组件定义如下所示:importReact,{Component}from'react';classHelloMessageextendsComponent{render(){return
Hello{this.props.name}.
;}}函数式风格:从'react'导入React;functionHelloMessage(props){return
Hello{props.name}.
;}//或:constHelloMessage=props=>
Hello{props.name}.
;属性的传递与HTML相同(本文最后部分会详细介绍各种类型的属性),如下:importReact,{Component}from'react';importReactDOMfrom'react-dom';classHelloMessageListextendsComponent{render(){return(
)}}ReactDOM.render(,document.querySelector('#root'));这样,页面就会显示:HelloLucy.HelloTom.HelloJack。示例代码:https://codepen。io/Sarike/pen...propertiesmustberead-onlyproperties必须是只读的,这个很重要,请严格电网合规性对应于上面提到的内容。如果把一个组件理解为一个函数,那么这个函数一定是一个纯函数(Purefunction)。在纯函数中,它的参数是不可修改的,一定的输入必然有一定的输出。虽然有时,你修改了组件的属性,但它似乎工作正常。没错,没有人能阻止你这样做,因为JavaScript语言的特性。但请先相信我,严格遵守这条规则不仅能让你少走很多弯路,还能让你的应用更加稳定和可维护。如果直接修改组件的属性,React不会感知到这个修改,所以不会重新渲染组件,会导致当前组件的视图显示与数据不一致,但是这个修改后的属性会displayedwiththenextrenderingofthecomponent对视图有效,本次渲染的时机不确定。不难想象,如果一个大型项目充满了这种不确定性,那该有多痛苦。总之,如果随意修改组件的属性,很容易让你的应用程序充满许多难以排查的bug。默认属性通常,我们需要为组件的属性设置默认值。就像HTML标签的属性也有默认值一样,比如form标签的method属性默认值为GET,input标签的type属性默认值为text。还是在HelloMessage组件上面,如果需求是不传入name属性时,默认显示HelloWorld,也就是说name属性默认值为World。一个容易想到的方法:
Hello{this.props.name||'World'}.
这样确实可以解决现在的需求,但是属性可能还是Object或者function。当然你可以先判断这个属性是否undefined再决定是否使用默认值,但是这样会让代码看起来很不优雅,同时也会增加很多繁琐的判断逻辑。因此,React提供了相应的机制来设置组件属性的默认值,如下所示,需要通过组件的静态字段defaultProps来设置组件属性的默认值。像这样:importReact,{Component}from'react';classHelloMessageextendsComponent{render(){return
Hello{this.props.name}.
;}}HelloMessage.defaultProps={name:'World'}这样就可以了,没有给组件设置任何属性,那么它就会在页面上显示HelloWorld。示例代码:https://codepen.io/Sarike/pen...属性类型及校验在开发比较复杂的前端应用时,我们经常会遇到很多类型检查导致的问题,比如上面的HelloMessage组件,我期望的是它的name属性只能是string类型。如果你给我一个对象,我无法正确显示它。为了在开发过程中尽快发现此类问题,React为组件添加了类型检查机制。您需要为组件设置静态字段propTypes来为组件的每个属性设置类型检查器。从'react'导入React,{Component};从“prop-types”导入PropTypes;classHelloMessageextendsComponent{render(){return
Hello{this.props.name}.
;}}HelloMessage.defaultProps={name:'World'}HelloMessage.propTypes={name:PropTypes.string}这样,在开发过程中,React可以验证组件接收到的属性值是否符合指定的类型。如果验证失败,它将发出警告。React只会在开发模式下执行属性类型检查。当代码发布到生产环境时,为了减少额外的性能开销,类型检查将被跳过。其实给每个组件写一个完整的属性类型是一个很好的习惯。这样不仅可以及时发现问题,更重要的是,加上一些简单的注释,这将成为一个很好的组件文档,一个完美的组件应该具有良好的封装性和易复用性。在协作开发的项目中,当其他开发者需要引用你开发的组件时,只需要查看组件的属性列表就可以大致了解如何使用这个组件,省去很多不必要的交流。以下是React提供的可用数据类型检查器。PropTypes.arrayPropTypes.boolPropTypes.funcPropTypes.numberPropTypes.objectPropTypes.stringPropTypes.symbolPropTypes.element元素实际上是一个JSX表达式。上一篇说JSX是React.createElement的语法糖。一个JSX表达式实际上会生成一个JS对象,在React中称为Elements。PropTypes.node可以渲染的所有数据类型,包括:数字、字符串、元素或这些类型的数组。PropTypes.instanceOf(Message)类PropTypes.oneOf(['News','Photos'])枚举的实例,属性值必须是其中一个值。PropTypes.oneOfType([PropTypes.string,PropTypes.number])类型枚举,属性必须是其中一种类型。PropTypes.arrayOf(PropTypes.number)属性是一个数组,数组中的元素必须符合指定的类型。属性PropTypes.objectOf(PropTypes.number)是一个对象,对象中各个字段的值必须符合指定的类型。PropTypes.anyAny类型如果你想指定某些属性为必需属性,你可以链式调用它的isRequired来标识某个属性是当前组件所必需的。如果在使用组件时未指定,将抛出警告。此外,您还可以通过函数自定义属性验证器。如果验证失败,需要返回一个Error实例,如下所示:'+propName+'`提供给'+'`'+componentName+'`。验证失败。');}}设置组件的属性值上面我们知道了组件的属性有很多种,下面说说各种类型的属性是如何传递给组件的。其实很简单。属性的值可以用一对花括号{}括起来,它可以指定任何JavaScript表达式。像这样:return()展开运算符也可以使用展开运算符...展开一个对象的所有字段,依次作为属性传递给组件,上面的代码相当于:constuserInfo={name:'Tom',age:18,isActivated:true,interests:['basketball','music'],address:{city:'北京',road:'北五环'}}return值为true的属性简写如果属性类型为Boolean且当前属性值为true,则只写属性名即可,如下所示:children属性自定义组件可以通过this.props.children得到一个特殊的属性。该属性与其他属性的区别在于传递方式。children属性的值是指一对闭合的JSX标签之间的内容,如下:然后在UserList里面你可以通过this.props.children得到如下JSX片段:在这个例子中,你得到的实际上是一个包含两个User元素对象的数组。小结本文主要介绍React中组件的定义,以及几个关键的注意事项。此外,还介绍了组件属性的作用、属性默认值、属性类型校验以及如何为组件传递属性。希望内容对大家有用。如果您有任何问题或建议,可以给我留言,谢谢。