学习尚硅谷天禹老师主讲的Vue,现将学习心得分享如下:
Props是用来向子组件传递数据的。在父组件中使用子组件时,可以在子组件的标签上添加自定义属性名和属性值,通过这个属性名就可以把父组件中的数据传递给子组件了。在子组件内部,Vue2中需要配置props选项,而Vue3中建议使用defineProps函数来接收父组件传递过来的数据。
一、Vue2中props配置项
1. 传递静态数据
子组件中的数据是通过父组件传递的。在父组件中使用子组件时,在子组件标签内额外添加一些自定义属性(props),就像书写HTML标签属性一样,采用“属性名=‘属性值’”的形式,传递数据给子组件本身,然后必须在子组件内部声明props配置项来接收这个属性值(数据)。
在父组件中,复用子组件,传递不同的数据,实现了在同一个子组件中展示不同数据的功能。上图中的代码传递的是静态数据(字符串形式的值),如何传递动态数据?答案是在属性前添加冒号,此时,属性值被解析为JS表达式。
子组件VC实例中,props属性的k被添加到组件实例vc上。在控制台观察子组件实例部分结构,如下图:
2. 传递动态数据
在父组件使用子组件时,子组件标签的自定义属性前添加英文冒号。
下面的代码是静态字符串数据,给子组件传递字符串数据“18”:
若在age前添加英文冒号,则静态字符串“18”被解析为动态JavaScript表达式(数字18):
3. 限制类型
子组件如果对父组件传递的数据不做限制,采用字符串“18”参与运算,例如:年龄+1运算,则会得到字符串类型数据“181”,而不是期望的结果19。如果在子组件中做了数据类型限制,则参考的props配置代码如下:
此时,传递字符串数据给age之后,控制台提示报错:
4. 类型限制+必要性限制+默认值
【几个细节】
第一、外部传入的数据是不能修改的。即使修改了,页面可以显示更新,但是控制台报错
控制台错误信息:
如果一定要修改外部传入的数据,则应使用如下技巧:
第二、在props配置项中声明了多余的属性,而父组件并没有传递该属性,则多余的属性值为undefined。子组件声明接收的属性如下:
而父组件并没有传递phone属性,则在子组件VC上存在phone这个key,但是其value为undefined。如下图:
第三、子组件定义的数据data选项中,不要出现与外部传递过来的同名属性key,否则以外部传递过来的为准。如下是错误示例:
页面显示与控制台信息:
第四、被Vue使用的关键字不能作为props,例如在使用子组件时,key、ref等关键字就不能当作prop来传递数据。
【小结图】
二、Vue3中的defineProps函数
1. 利用props给子组件传递普通类型数据
如下是Vue3中的写法:
如何使用数据呢?在子组件的模版语法中,直接写属性名即可,如下:
上面的写法并不推荐,因为在单纯的模板语法中,插值语法中的a会出现如下几种可能:
上图中,a可能是图中的任何一种情况之一,而且在defineProps中的实参数组中,元素a是字符串,而到了模板语法中却又是变量a了,但是在setup函数里面,直接输出变量a却提示a未定义而报错,如下图,这是何故?原因是子组件隐含了对Props的处理。
defineProps函数接收的实际参数是必须是数组,该函数返回一个JSON对象,里面以键值对的形式包含了父组件传递过来的所有的props数据,在键值对中,k就是组件标签上写的属性名,比如上面的a就是k,v就是传递的属性值(数据),如下代码示例:
浏览器控制台输出结果如下图:
x是JSON对象,在里面包含的键值对中,a就是k,a的属性值“哈哈”就是v,如下:
当给子组件传递了实质上的b属性“嘿嘿”时,代码如下:
浏览器控制台输出结果:
如果defineProps的参数数组中,没有写属性“b”,则即使父组件传递了b属性,但是因子组件没有定义与之对应的b属性名而导致无法接收b属性的数据。如下图:
浏览器控制台输出结果:只有a这一组键值对,没有b这个k。
可见,defineProps函数的返回值中的键值对数量取决于你传递的实参数组中的元素数量。即使父组件不传递属性数据,而子组件defineProps函数参数数组中又定义了一些属性,则这些属性的值是undefined。
2. 利用props给子组件传递对象
正常渲染结果如下图:
但是在子组件中,只接受对象而不处理是有风险的,一旦父组件在props传参中发生错误,如下图:
则子组件也能渲染,而且不报错,如下是渲染结果:
在子组件代码中,接收属性时做限制,如下是代码:
控制台显示信息如下:
子组件中添加限制约束条件:接收+限制类型(泛型)+限制必要性(父组件可传?可不传?)+指定默认值
出现新的需求:父组件可以给子组件传递list,也可以不传list,而前面的代码如果在父组件中不传递list给props,则飘红报错!如何实现父组件不传时而不飘红报错呢?如下代码解决:
此时,父组件没有传递list给子组件,即使子组件使用了v-for指令,也不报错,不会渲染到页面。如下图:
前面的泛型和必要性限制,使得v-for很健壮,但是也给用户带来不好的体验,当父亲不传数据时,网页页面上没有任何显示,此时可以在子组件中指定默认值来显示,使用withDefaults函数,如下是示例代码:
此时,父组件不传递数据,页面上显示默认数据,如下图:
【小结图】
【注】Vue3中,凡是以define***的函数无需手动导入,这些是Vue3中的宏函数,可直接使用。