React学习笔记五-props

此文章是本人在学习React的时候,写下的学习笔记,在此纪录和分享。此为第五篇,主要介绍react中的props。

目录

1.props的基本使用

 2.props的批量传递

2.1展开运算符的复习

2.1.1数组中的展开运算符

 2.1.2函数中的展开运算符

 2.1.3构造字面量对象时使用展开语法

2.2展开运算符与props 

3.对props进行限制

4.props的简写方式

5.类式组件中构造器和props

6.函数式组件与props

6.1函数式组件中使用props

 6.2函数式组件内限制props

7.props的总结


1.props的基本使用

我们先来写一个小案例,将一个人的姓名,性别和年龄分别以li的形式渲染到页面上,要渲染多个人的。

这时候我先写好类式组件,在render函数内写上const {name,age,sex} = this.props,将实例中的props解构赋值,方便我们构建虚拟dom时候渲染props内的name,age和sex。

最后在ReactDOM.render内,我们写组件名字的时候,在组件内把name,age和sex传进去。

就像是<Person name='张三' sex='男' age='18'/>的形式。如此我们组件创建的实例中的props属性内就存在了name,sex和age三个数据,在render函数生成虚拟dom时会直接拿取props内的数据。

代码如下:

<!-- 准备好容器 -->
    <div id="test1"></div>
    <div id="test2"></div>
    <div id="test3"></div>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel">
        class Person extends React.Component {
            render(){
                console.log(this);//打印this指向的实例对象,查看props属性
                const {name,age,sex} = this.props//解构赋值
                return(//构建虚拟dom
                    <ul>
                        <li>姓名:{name}</li>
                        <li>性别:{sex}</li>
                        <li>年龄:{age}</li>    
                    </ul>
                )
            }
           
        }
        //分别渲染dom到三个容器内
        ReactDOM.render(<Person name='张三' sex='男' age='18'/>, document.getElementById('test1'))
        ReactDOM.render(<Person name='李四' sex='女' age='19'/>, document.getElementById('test2'))
        ReactDOM.render(<Person name='王五' sex='男' age='20'/>, document.getElementById('test3'))
    </script>

效果如下:

 2.props的批量传递

2.1展开运算符的复习

在学习props的批量转递的时候,我们要先复习一下展开运算符,也就是三点运算符。

2.1.1数组中的展开运算符

如下两个数组,展开运算符可以将一个数组中的每一项展开显示,也可以将两个数组拼接在一起成为一个新的数组。

代码如下:

let arr1 = [1, 3, 5, 7, 9]
let arr2 = [2, 4, 6, 8, 10]
console.log(...arr1);//展开数组
let arr3 = [...arr1, ...arr2]
console.log(arr3);//拼接数组

效果如下:

 2.1.2函数中的展开运算符

我们写一个求和函数,在传参的时候使用展开运算符。首先打印一下参数,发现用展开运算符传承的时候,传递的参数会变成一个数组。然后我们正常运行函数,输出结果保证函数求和功能没有问题。

代码如下:

function sum(...numbers) {
            console.log(numbers);
            return numbers.reduce((preValue, currentValue) => {
                return preValue + currentValue
            })
        }
        console.log(sum(1, 2, 3, 4));

效果如下:

 2.1.3构造字面量对象时使用展开语法

我们先写这样的代码:

let person = {name:'tom', age:18}
console.log(...person);//报错。展开运算符不可以展开对象

效果如下:

 所以,展开运算符不可以展开对象。

但是看下面的代码:

 let person = {name:'tom', age:18}
 let person2 = {...person}
 console.log(person2);

效果如下:

 我们使用展开运算符展开了person,并赋值给person2,实现了深拷贝。即使我们再去更改person里的内容,person2的内容也不会改变。

代码如下:我们再写一个person3.

 let person3 = {...person,name:'jack',address:'地球'}
        console.log(person3);

效果如下:person3是person和新的属性产生了合并,一致的属性产生了覆盖。

2.2展开运算符与props 

还是上面的案例,我们尝试使用展开运算符在ReactDOM.render内的组件内使用。

代码如下:我们直接写一个对象存储name,sex和age,并赋值给p。在ReactDOM.render内的组件props内,我们使用了展开运算符,把name,sex和age三个数据一次性批量传入,简单快捷。

ReactDOM.render(<Person name='李四' sex='女' age={19} />, document.getElementById('test2'))
       
const p = { name:'王五', sex:'男', age:19 }
ReactDOM.render(<Person {...p}/>, document.getElementById('test3'))

3.对props进行限制

上面基本使用的案例,如果我们对name,sex和age的类型分别限定为string,string和number,并且规定name属性不可为空,sex和age都有默认值,那该怎么办呢?

代码如下:

先引入propTypes库,这个依赖包就是限定props需要的包。

 <!-- 新引入的库,用于限定props传入值的类型,propTypes -->
    <script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>

然后我们使用Person.propTypes为Person内的各种属性设置类型限定和不可为空。

使用Person.defaultProps为Person内的属性设置默认值。

注意,设置属性的时候,string,number这些类型都是小写的,function类型写为func。

//在引入相应的依赖包后,才能使用本代码对数据类型进行限定
        Person.propTypes = {//为Person的数据设置类型限定
            name:PropTypes.string.isRequired,//限定name必须为string类型,并且不得为空
            sex:PropTypes.string,//限制sex为string类型
            age:PropTypes.number,//限定age为number类型
            speak:PropTypes.func//限定speak为function类型
        }
        Person.defaultProps = {//为Person的数据设置默认数据
            sex:'性别未知',//为sex设置默认值
            age:18//设置age默认值为18
        }
        //分别渲染dom到三个容器内
        ReactDOM.render(<Person name='张三' sex='男' age={18} speak={speak}/>, document.getElementById('test1'))
        ReactDOM.render(<Person name='李四' sex='女' age={19}/>, document.getElementById('test2'))
        ReactDOM.render(<Person name='王五' sex='男' age={19}/>, document.getElementById('test3'))

        function speak() {
            console.log('我说话了');
        }

写完后,可以尝试违反类型限制为属性传入不同类型的值,这时候在控制台会清楚的指出因为数据类型不同的报错。

4.props的简写方式

代码如下:我们把对数据设置类型限定和设置默认数据的代码,加上static关键字,转移到创建组件的类里面。注意不要写到render函数内。这样props代码部分,放在组件内,比较简洁规范。

//创建组件
        class Person extends React.Component {
            static propTypes = {//为Person的数据设置类型限定
                name: PropTypes.string.isRequired,//限定name必须为string类型,并且不得为空
                sex: PropTypes.string,//限制sex为string类型
                age: PropTypes.number,//限定age为number类型
                speak: PropTypes.func//限定speak为function类型
            }
            //指定默认标签属性值
            static defaultProps = {//为Person的数据设置默认数据
                sex: '性别未知',//为sex设置默认值
                age: 18//设置age默认值为18
            }
            render() {
                console.log(this);//打印this指向的实例对象,查看props属性
                const { name, age, sex } = this.props//解构赋值
                return (//构建虚拟dom
                    <ul>
                        <li>姓名:{name}</li>
                        <li>性别:{sex}</li>
                        <li>年龄:{age}</li>
                    </ul>
                )
            }

        }

5.类式组件中构造器和props

constructor在类式组件的作用是什么?我们来看react官网的解释:

通常,在React中,构造函数仅用于以下两种情况:

        1.通过给this.state赋值对象来初始化内部state

        2.为事件处理函数绑定实例。

其实在书写类式组件的时候,可以不写构造器。如果写了构造器,也可以不接收props这个参数,super()内也可以不写,但如果如此,console.log('constructor',this.props);这行代码就会打印undefined,就是在构造器中没有办法通过实例.props去取得值。

代码如下:

constructor(props){
      console.log(props);
      super(props)
      console.log('constructor',this.props);
}

结果:

 不接收props的情况:

constructor(){ 
     super()
     console.log('constructor',this.props);
}

结果:

 所以,构造器是否接收props,是否传递props给super关键字,这就取决于:是否希望在构造器中通过this,访问props。但这个场景及其罕见,如果没有这个需求,构造器都可以直接省略,能省就省。

6.函数式组件与props

对于实例三大属性,函数式组件不可以使用state和ref,但可以使用props,因为它可以接收参数。

6.1函数式组件中使用props

我们在函数式组件内直接接收参数props,在ReactDOM.render(<Person name='张三' sex='男' age={18} />, document.getElementById('test1'))渲染组件到界面时接收参数,name='张三' sex='男' age={18} 这三条传入的数据会自动保存到函数式组件内的props里面,以对象的形式存在。我们使用解构赋值对props解构后,直接拿到虚拟dom里面使用。

代码如下:

function Person(props) {
            const { name, age, sex } = props
            return (//构建虚拟dom
                <ul>
                    <li>姓名:{name}</li>
                    <li>性别:{sex}</li>
                    <li>年龄:{age}</li>
                </ul>
            )
        }
        //渲染组件到界面
        ReactDOM.render(<Person name='张三' sex='男' age={18} />, document.getElementById('test1'))

效果如下:

 6.2函数式组件内限制props

与类式组件类似,我们写 组件名.propTypes和组件名.defaultProps来限制props的数据类型和设置默认数据。写完后可以传入任意类型数据,或者不写数据,看看控制台的输出,发现限制和默认设置没有问题。

代码如下:

function Person(props) {
            const { name, age, sex } = props
            return (//构建虚拟dom
                <ul>
                    <li>姓名:{name}</li>
                    <li>性别:{sex}</li>
                    <li>年龄:{age}</li>
                </ul>
            )
        }
        Person.propTypes = {//为Person的数据设置类型限定
            name: PropTypes.string.isRequired,//限定name必须为string类型,并且不得为空
            sex: PropTypes.string,//限制sex为string类型
            age: PropTypes.number,//限定age为number类型
        }
        Person.defaultProps = {//为Person的数据设置默认数据
            sex: '性别未知',//为sex设置默认值
            age: 18//设置age默认值为18
        }
        //渲染组件到界面
        ReactDOM.render(<Person name='张三'/>, document.getElementById('test1'))

7.props的总结

理解:

1.每个组件对象都会有props属性。

2.组件标签的所有属性都报存到props属性中。

作用:

1.通过标签属性从组件外向组件内传递变化的数据。

2.注意:组件内部不要修改props数据。

猜你喜欢

转载自blog.csdn.net/zhangawei123/article/details/130751307