前一节课我们学完了react组件的三大属性之一的state,并且对state做了一个阶段性的总结。虽然总结的内容很少,但是每一点的展开的细节加到一起就是之前的7个课时的内容。那么今天这节课我们开始学习第二个属性:props

案例需求

我们学习props先通过一个案例来引入我们要学的东西。我不喜欢直接去讲一些枯燥的理论,我们先做点什么出来。那我们的需求是什么呢?

我们定义一个用来显示人员信息的组件,要求:

  • 姓名为必须指定,且为字符串类型
  • 性别如果没有指定,默认为男
  • 年龄必须指定,且为数字类型

效果:

image-20211220143232900

分析

我们来分析一下这个需求,我们上半部分和下半部分的内容是不是很相似,都是展示了姓名,性别和年龄。而且每一个人都是一个列表的形式,都是<ul><li>的标签。

实现

那么好,这个我们分析完了之后那就开始做吧。我们先别管那么多,先来实现,等我们实现了之后再来谈优化和问题解决:

class Person extends React.Component {
    render() {
        return (
            <ul>
                <li>姓名: 景珣</li>
                <li>性别: 男</li>
                <li>年龄: 18</li>
            </ul>
        );
    }
}

ReactDOM.render(<Person />, document.getElementById("test"));

我们来看一下上面的代码:

  1. 创建组件
  2. 在组件中添加render方法
  3. render方法中返回虚拟DOM,我这里先暂时写死了
  4. 渲染组件到页面

来看一下效果:

image-20211220144233302

一切正常,页面出来了。

页面动态化

那么我现在的信息都是写死的,可是我想让这个页面动态起来该怎么办?

state行不行

经过我们前面的学习,基本上大家马上下意识地就会说,我用state啊。state的用途不就是存放数据的嘛,然后我们通过更新数据来驱动页面重新渲染。

class Person extends React.Component {
    state = { name:"jingxun", age: 18, gender: "" }
    render() {
        return (
            <ul>
                <li>姓名: {this.state.name}</li>
                <li>性别: {this.state.gender}</li>
                <li>年龄: {this.state.age}</li>
            </ul>
        );
    }
}

ReactDOM.render(<Person />, document.getElementById("test"));

那这样写行不行呢?我们来看一下:

image-20211220144919755

是不是也正常渲染出来了啊?但是如果这样的话我是不是要在组件内部就把state定义好初始化好啊?但是如果我现在的需求要从组件外往组件里传入这些信息的话怎么办?这样我没法去初始化state了啊。因为我们之前就说了,我们初始化state直接用赋值语句来写了,这种方法只能在组件内部写死,没法接收外部参数啊,所以说我们不能在使用state了。

有些朋友可能说,我还是没太理解,那比如这么说把,下面这段代码:

class Person extends React.Component {
    state = { name:"jingxun", age: 18, gender: "" }
    render() {
        return (
            <ul>
                <li>姓名: {this.state.name}</li>
                <li>性别: {this.state.gender}</li>
                <li>年龄: {this.state.age}</li>
            </ul>
        );
    }
}

ReactDOM.render(<Person />, document.getElementById("test1"));
ReactDOM.render(<Person />, document.getElementById("test2"));

这里我渲染了两个容器,也都是用了state,但是我们得到的效果是什么呢?

image-20211220145821531

你看,即便我们用了statestate也确实是为了来做动态渲染的,但是我们页面上展示的还是两个一模一样的容器,那有人说我们写一个新的组件来放第二个容器。那我们组件话不就没有意义了嘛,一个组件只能给一个容器用得话我们的复用率为 0 啊。

那么我们的预期是不是就像函数一样,我们传入什么数据,就让react来渲染什么啊?那我们是不是就想我们能不能在ReactDOM.render(<Person />, document.getElementById("test1"));这一步我们做点什么文章来让这两个容器来渲染点不一样的东西?

不能用state该用什么

我们刚刚说要在如果在ReactDOM.render(<Person />, document.getElementById("test1"));这一步做文章,但是如果能从这里传入数据的话,我们的state接收不到,那这怎么办呢?有人说我们借助构造器,用构造器来接收我们就可以用state

那么好,我们回想一下,react中的构造器是怎么写的?

class Person extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
    }
}

这是什么意思?构造器接收到的其实是props,有人又说了,那我从propsstate的数据拿出来,然后再赋给state,那不是多此一举吗?

我们本身就有props属性啊,这不是我们react组件的三大属性之一嘛。那直接用props不就可以了嘛。那么好,我们怎么使用props呢?

props的使用

现在我们知道可以用props来写我们的需求,但是我们怎么使用呢?是不是也y用this来调用呢?我们先来看一下render方法中的this

render() {
    console.log(this);
    return ...;
}

打印一下this:

image-20211220151835676

首先,这里的this指向的是谁?是不是Person的实例对象?那么Person的实例对象上有什么?是不是有props在?而且props是一个空对象,因为我们确实没有传入任何东西进去。

其实props真的比state要简单得多,state还需要我们亲自来写里面的值,但是props不需要,因为props是我们传入进去的数据,这个数据在实际开发中是来自我们后端接口的,当然目前我们还没到那一步,我们先自己mock一部分然后传进来就行了。

但是怎么传呢?我们说了半天了要传数据传数据,但是到底要怎么传可是一句都没有提。先别着急,我们来思考一个问题。

HTML标签是不是可以写标签属性?比如我们的容器,<div id="test"></div>我们这个标签的标签名叫div,里面有一个id属性,那么这个属性的属性名叫id,属性值是test,那这个是不是类似于一对key-valueidkeytest就是value?那么HTML标签本身就可以写很多组key-value的组合。

我们再回头看一下渲染组件那一步,我们写的组件是以什么形式传进去的?是不是也是一个标签?那么这个标签能不能也写这种key-value的组合属性呢?那我们试试呗:

class Person extends React.Component {...}
ReactDOM.render(<Person name="jingxun"/>, document.getElementById("test1"));

这样一写,我们会得到什么结果呢?

image-20211220153219787

我们从图上来看,是不是我们已经接收到name这个属性了?而且还存放到了props中,也就是说,当我们想上面那段代码那么写的话react在渲染组件的时候就会把name作为keyname属性的值作为value传入了组件存放到了props中了。

那么以此类推,我们直接在标签里面来写我们要传的属性就行了啊,那么数据也传进去了,我们在render方法中就可以通过this来调用props了,就想调用state一样:

class Person extends React.Component {
    state = { name:"jingxun", age: 18, gender: "" }
    render() {
        return (
            <ul>
                <li>姓名: {this.props.name}</li>
                <li>性别: {this.props.gender}</li>
                <li>年龄: {this.props.age}</li>
            </ul>
        );
    }
}

ReactDOM.render(
    <Person name="jingxun" age="18" gender=""/>, 
    document.getElementById("test1")
);

这样的话我们再来看一下效果:

image-20211220153906691

信息也出来了,但是这里的优势就在于我能在组件标签那一步动态地去修改props的内容。而且再回到刚才我们说的

class Person extends React.Component {...}
ReactDOM.render(
    <Person name="jingxun" age="18" gender="男"/>,  
    document.getElementById("test1")
);
ReactDOM.render(
    <Person name="dschow" age="18" gender="女"/>,  
    document.getElementById("test2")
);

那这一步我们页面是什么样子呢?

image-20211220154234690

这一次,我渲染出来的就是两个完全不一样的信息,这样的话东西都是动态地传入标签的。

以上就是我们props最基本的使用

总结

  • props是一个对象
  • props是通过外面往组件内传入数据
  • props在组件的实例对象上可以通过this调用
  • props可以在组件标签处通过标签属性传入

Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.

Link of this article:https://work.lynchow.com/article/props_basic/