6.1 Prop
学习:状态选项props 以及 实例属性 $attrs
一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute
props 需要使用 props 选项来定义:
{
props: ['foo'],
created() {
// props 会暴露到 `this` 上
console.log(this.foo)
}
}
除了使用字符串数组来声明 prop 外,还可以使用对象的形式:
{
props: {
title: String,
likes: Number
}
}
对于以对象形式声明中的每个属性,key 是 prop 的名称,而值则是该 prop 预期类型的构造函数。比如,如果要求一个 prop 的值是 number
类型,则可使用 Number
构造函数作为其声明的值。
如果一个 prop 的名字很长,应使用 camelCase 形式,因为它们是合法的 JavaScript 标识符,可以直接在模板的表达式中使用,也可以避免在作为属性 key 名时必须加上引号。
虽然理论上你也可以在向子组件传递 props 时使用 camelCase 形式 (使用 DOM 模板时例外),但实际上为了和 HTML attribute 对齐,我们通常会将其写为 kebab-case 形式
<my-com :likeNum="100"></my-com>
===><my-com :like-num="100"></my-com>
对于组件名我们推荐使用 PascalCase,因为这提高了模板的可读性,能帮助我们区分 Vue 组件和原生 HTML 元素。然而对于传递 props 来说,使用 camelCase 并没有太多优势,因此我们推荐更贴近 HTML 的书写风格-短横线。
所有的 props 都遵循着单向绑定原则(
单项数据流
),props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。另外,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。
6.1.1 父组件给子组件传值1
完整案例:29_parent_child_component_value1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>29_父组件给子组件传值 方式1 - 数组</title>
</head>
<body>
<div id="app">
<my-parent></my-parent>
</div>
</body>
<template id="parent">
<div>
我是父组件
<!-- 父组件调用子组件的地方,添加自定义的属性,如果属性的值是变量,boolean类型,number类型,对象,数组,null,undefined,需要使用绑定属性 -->
<my-child :msg="msg" :flag="true" :num="100" :obj="{a: 1, b: 2}" :arr="['a', 'b', 'c']"></my-child>
</div>
</template>
<template id="child">
<div>
我是子组件 - {
{ msg }} - {
{ flag }} - {
{ num }} - {
{ obj }} - {
{ arr }}
</div>
</template>
<script src="lib/vue.global.js"></script>
<script>
// 在定义子组件的地方,添加props选项,
// props的数据类型为数组,数组的元素即为 自定义的属性名, 之后就可以直接在子组件中通过 自定义的属性名 使用 传递的值
const Child = {
props: ['msg', 'flag', 'num', 'obj', 'arr'],
template: '#child'
}
const Parent = {
template: '#parent',
components: {
MyChild: Child
},
data () {
return {
msg: 'hello parent'
}
}
}
const { createApp } = Vue
const app = createApp({
components: {
MyParent: Parent
}
})
app.mount('#app')
</script>
</html>
虽然上述案例已经完成了父组件给子组件传值,但是不够严谨
可能A负责父组件的编写,B负责了子组件的编写,容易造成 不知道 自定义的属性名的 数据类型
6.1.2 父组件给子组件传值2
完整案例:30_parent_child_component_value2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>30_父组件给子组件传值 方式2 - 对象-数据类型</title>
</head>
<body>
<div id="app">
<my-parent></my-parent>
</div>
</body>
<template id="parent">
<div>
我是父组件
<!-- 父组件调用子组件的地方,添加自定义的属性,如果属性的值是变量,boolean类型,number类型,对象,数组,null,undefined,需要使用绑定属性 -->
<my-child :msg="msg" :flag="true" :num="100" :obj="{a: 1, b: 2}" :arr="['a', 'b', 'c']"></my-child>
</div>
</template>
<template id="child">
<div>
我是子组件 - {
{ msg }} - {
{ flag }} - {
{ num }} - {
{ obj }} - {
{ arr }}
</div>
</template>
<script src="lib/vue.global.js"></script>
<script>
// 在定义子组件的地方,添加props选项,
// 方式1:props的数据类型为数组,数组的元素即为 自定义的属性名, 之后就可以直接在子组件中通过 自定义的属性名 使用 传递的值
// 方式2:props的数据类型为对象,对象的key值为自定义的属性名,value值为数据类型(不会阻碍程序运行,警告代码不严谨)
// 如果一个自定义的属性的值既可以是 String 类型,也可以是 Number类型 key: String | Number
const Child = {
// props: ['msg', 'flag', 'num', 'obj', 'arr'],
props: {
msg: String,
flag: Boolean,
num: String | Number,
obj: Object,
arr: Array
},
template: '#child'
}
const Parent = {
template: '#parent',
components: {
MyChild: Child
},
data () {
return {
msg: 'hello parent'
}
}
}
const { createApp } = Vue
const app = createApp({
components: {
MyParent: Parent
}
})
app.mount('#app')
</script>
</html>
现在只能知道哪一个属性是哪一种数据类型,但是有时候我们可以不需要设置 自定义的属性(. )
<input />
<===><input type="text" />
6.1.3 父组件给子组件传值3
完整案例: 31_parent_child_component_value3.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>31_父组件给子组件传值 方式3 - 对象-数据类型-默认值</title>
</head>
<body>
<div id="app">
<my-parent></my-parent>
</div>
</body>
<template id="parent">
<div>
我是父组件
<!-- 父组件调用子组件的地方,添加自定义的属性,如果属性的值是变量,boolean类型,number类型,对象,数