资讯专栏INFORMATION COLUMN

[ 一起学React系列 -- 3 ] UI的扩展数据源Props以及Props约束

kumfo / 1793人阅读

摘要:所以还是印证那句话是组件渲染的唯一依据。所以对组件的进行约束是创建一个健康组件的必要条件。这里我们约束属性类型为。使用方式运行结果没有错误假如我们再加入一个子组件控制台如预期报错自定义约束万物皆有其局限性。

日常扯淡前的废话

上一篇我们介绍了React中State对象,说到它是组件渲染的唯一依据;当然我们也可以认为State是组件中的数据源之一,它保存着组件渲染的所有数据并且可以直接作用于组件的渲染。这里有两个地方我们画了所谓的重点,因为要考啊。666...

Props

Props是Facebook为React组件提供的另一个神级API。顾名思义,prop(property)就是属性的意思;props呢就是properties,当然是很多个属性啦。因为大千世界中每个事物不可能只有一个属性,所以
处于人道主义考虑(扯淡...头伸过来),React设计师就允许我们给组件设置很多很多的属性,究竟有多?当然是看我们开发者自己的心情咯。组件的Props类似于DOM的attributes,随便从某个网页上inspect某个节点都能看到除了tag以外这个节点还挂载了很多别的东西,比如我们常用的class或者id都是节点的属性。当然React组件中Props的表现也相似。不过相对于普通DOM的属性操作,React的属性操作可以说是优雅万分,至于优雅到什么程度,下面会有例子呈上。我们一步一步来!

Props为什么能提供数据?

首先看个例子:

创建组件。一个很简单的组件,用来显示从props传来的文字
import React, {Component} from "react";

class Show extends Component {
    render() {
        return (
            

{this.props.content}

) } } export default Show;
使用组件
 

从例子中可以看到向组件Show添加一个属性很便捷,写一个属性名再赋值就行了(而如果DOM需要添加一个属性的话则需要调用setAttribute方法,异常繁琐)。其次,当我们给组件添加了属性之后,那么这些属性就被挂载到组件的this.props中。因此这就是为什么我们可以在组件中通过this.props.content来获取通过Props传入的文字(而如果DOM需要获取一个属性的话则需要调用getAttribute方法)。我们看下实际效果:

当然我们也可以在添加属性的同时进行简单的逻辑处理,我们改下Show组件使用方式:

看下实际效果:

简直神器...不过笔者在这里想强调下

不建议写复杂的逻辑。过于复杂的逻辑会降低代码的可阅读性,所以如果某个属性值被添加前需要做很多的处理,请把逻辑封装在一个方法里最后用处理结果进行赋值即可,比如酱紫:
class App extends Component {

    createContent = () => {
        let result = 0;
        for (let i = 0; i <= 100; i++) {
            result += i;
        }
        return result;
    };

    render() {
        return (
            

Welcome to React

); } } export default App;

这样可以将节点和逻辑分离,增加可阅读性而且代码会显得很优雅。

Props与State有什么不同?

开头有说过State并不是组件的唯一数据源,当然上面的例子也证明了这一点。然而,它们又有什么不同?

1,Props被保存在this.props中,State被保存在this.state中;获取也如此。
2,State可以在组件中更新,而Props不可以。至于为什么,我们接下来会有解释;
3,State的更新会引发组件的重新渲染;Props的更新(从组件外)并不会引发该组件的重新渲染。因此如果想在Props被更新的同时引发渲染,那么就需要在componentwillreceiveprops中或者getDerivedStateFromProps中将更新后的Props同步给State,这样可以触发组件的重新渲染,其本质还是借用State的力量。所以还是印证那句话:State是组件渲染的唯一依据
Props给我们带来了什么?

从上面的例子中我们可以看出我们可以将组件之外的数据通过Props传递给组件,这一特性也同样解决了父子组件之间通信的问题:如果父组件想传递数据给子组件,那么就可以将所需要传递的数据通过Props传递给子组件,上面的例子写得很详细。同样,正是因为组件的Props大多都是父组件向子组件传递数据的通道,那么也就解释了为什么在子组件中不能修改Props中数据的原因,因为别人传给你的东西你改啥?出问题谁背锅?所以笔者在这里强调一个:不要在组件中更改Props!。因为我们直接修改Props中基本类型的时候React会自动报错,但是如果修改引用类型的话比如向数组添加一个元素,React并不会报错因为地址没变进而导致组件运行异常。

Props约束

我们都知道JavaScript是一门弱类型的语言,与强类型语言比如Java不同,我们在定义一个变量的时候不会去声明这个对象到底是整型还是浮点还是字符串等等...因此当我们给组件添加属性的时候很可能会引发组件运行出错,比如组件有个属性叫list,我们希望它是一个数组并且在组件中对其使用了forEach。但是另一个开发人员引用这个组件的时候由于不清楚所以传了一个数字,那么组件就挂了。所以对组件的Props进行约束是创建一个健康组件的必要条件。

约束工具

本来React库中包含了属性监测的包,但是在某个版本被移除了(笔者记不清从哪个版本开始)。不过我们仍可通过第三方包做同样的事情 prop-types

类型约束

其实Props约束最需要解决的是类型的约束,由于篇幅有限因此下面通过一个例子介绍下具体使用方法,详情请点开链接自行查阅文档

1,首先安装第三方包是必须的 npm install prop-types --save
2,在文件中引入 import PropTypes from "prop-types"
3,修改之前的例子
import React, {Component} from "react";
import PropTypes from "prop-types";

class Show extends Component {

    render() {
        return (
            

{this.props.content}

) } } Show.propTypes = { content: PropTypes.string }; export default Show;

我们创建完组件后并且在export之前,使用字面量对象对组件的propTypes进行赋值以确定该组件的Props类型。这里我们约束content属性类型为string。假如我们传入的数据是一个数组的话

那么运行的结果就出错了:

index.js:2178 Warning: Failed prop type: Invalid prop `content` of type `array` supplied to `Show`, expected `string`.
"必需"约束

所谓的"必需"约束是指定组件必须要某个属性,写法如下:

Show.propTypes = {
    content: PropTypes.string.isRequired
};

这里表示Show组件必须要有content这个属性。假如没有呢?

index.js:2178 Warning: Failed prop type: The prop `content` is marked as required in `Show`, but its value is `undefined`.

自然在控制台就有报错信息了。

子组件约束

子组件约束主要是约束该组件的子组件有几个,假如我们规定该组件只能有一个子组件就可以这么写:

import React, {Component} from "react";
import PropTypes from "prop-types";

class Show extends Component {

    render() {
        return (
            
{this.props.children}
) } } Show.propTypes = { children: PropTypes.element }; export default Show;
此时我们是对该组件的children进行了约束,笔者认为children是React的保留字所以我们在定义Props的时候不要使用children。

使用方式:


    

Hello World

运行结果没有错误;

假如我们再加入一个子组件

    

Hello

World

控制台如预期报错:

Warning: Failed prop type: Invalid prop `children` of type `array` supplied to `Show`, expected a single ReactElement.
自定义约束

万物皆有其局限性。假如包提供的所有约束条件中没有我们所期望怎么办?那就自己写一个自定义约束即可;写法如下:

import React, {Component} from "react";

class Show extends Component {

    render() {
        return (
            

{this.props.custom}

) } } Show.propTypes = { custom: function (props, propName, componentName) { if (typeof(props[propName]) === "string") { if (!props[propName].startsWith("React")) { return new Error(`The prop ${propName} of Component ${componentName} is not start with "React"`) } } else { return new Error(`The prop ${propName} of Component ${componentName} is not a string object`) } } }; export default Show;

此时我们并不需要引入第三方库了,不过写法和前面的用法一样,只是字面量对象的值不是特定的类型而是一个校验函数,函数的第一个参数是该组件的props集;第二个参数是被该校验函数监测的prop名字(此时是custom;第三个参数是该组件的名字);从代码可以看出我们这个自定义约束的目的是监测该组件的custom属性值是否为字符串并且以React开头。首先我们添加正确的属性值:

运行正常;然后添加错误的属性值看看:

控制台打印出了我们预设的提示信息:

Warning: Failed prop type: The prop custom of Component Show is not start with "React"

再者如果我们添加错误的类型值看看:

错误信息正常打印:

Warning: Failed prop type: The prop custom of Component Show is not a string object

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97690.html

相关文章

  • [ 一起React系列 -- 2 ] UI灵魂--State

    摘要:首先卖个关子,下面我们一起来复习下小学还是初中的一枚数学知识。一旦更改了,会触发组件的重新渲染。为了页面渲染性能的考虑,有助于在中进行比较并确定是否重新渲染。 概念引入 对于React来说, 没有State就没有页面的渲染, 我们也将什么都看不到 咋一听怎么那么唬人?不过的确是这样,正如标题所言State是UI的灵魂。我们都知道React的核心思想之一是组件化,将页面所展示的东西按一定...

    XBaron 评论0 收藏0
  • [ 一起React系列 -- 4 ] 透传Context

    摘要:官方对的介绍是意思就是提供了一种通过组件树传递数据的方法,而无需在每个级别手动传递。这也是基于重要物证哈哈实例使用学习技术最终是要有产出的。依然被视作一个组件,不过不同的是它的子组件必须是一个方法并且该方法接收当前对象并最终返回一个节点。 抛转引玉 通过上一篇的科普我们知道如果父节点需要向子节点传递数据,那么就得通过Props来实现;那么摆在我们眼前的就有一个问题了:现有N个节点并且它...

    firim 评论0 收藏0
  • React

    摘要:基础创建虚拟参数元素名称,例如参数属性集合,例如,,,从参数开始,表示该元素的子元素,通常这些元素通过创建,文本文件可以直接插入嘻嘻哈哈这是渲染器,将元素渲染到页面中。 React简介 FeceBook开源的一套框架,专注于MVC的视图V模块。实质是对V视图的一种实现。 React框架的设计没有过分依赖于某个环境,它自建一套环境,就是virtual DOM(虚拟DOM)。 提供基础AP...

    hlcc 评论0 收藏0
  • React 深入系列3Props 和 State

    摘要:深入系列,深入讲解了中的重点概念特性和模式等,旨在帮助大家加深对的理解,以及在项目中更加灵活地使用。下篇预告深入系列组件的生命周期我的新书进阶之路已上市,请大家多多支持链接京东当当 React 深入系列,深入讲解了React中的重点概念、特性和模式等,旨在帮助大家加深对React的理解,以及在项目中更加灵活地使用React。 React 的核心思想是组件化的思想,而React 组件的定...

    hiyayiji 评论0 收藏0

发表评论

0条评论

kumfo

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<