Vue 组件Props

Prop简介

  • Prop 是子组件用来接受父组件传递过来的数据的一个自定义属性,一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
  • 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 “prop”:
1
2
3
4
5
6
7
8
9
10
props: {
propName1: propType1,
propName2: {
type: propType2,
default: propDefaultValue, // 可选
required: propRequired, // 可选
validator: propValidator // 可选
},
// ...更多属性声明
}

下面是对上述格式中各个选项的解释:

  • propName1, propName2, …:属性名称,用于接收从父组件传递的数据。

  • propType1, propType2, …:属性的类型,可以是以下之一:

    • String
    • Number
    • Boolean
    • Object
    • Array
    • Function
    • Symbol
    • 自定义构造函数(通常是自定义对象的构造函数)
  • default(可选):指定属性的默认值。如果父组件没有传递该属性,将使用默认值。

  • required(可选):如果设置为 true,则表示该属性是必需的,父组件必须传递该属性。如果未传递,Vue 会发出警告。

  • validator(可选):一个自定义验证函数,用于验证属性的值是否有效。该函数应返回 truefalse

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
props: {
propA: String, // 字符串类型
propB: Number, // 数字类型
propC: {
type: Boolean,
default: false // 默认值为 false
},
propD: {
type: Array,
required: true // 必需属性
},
propE: {
type: Object,
validator: function(value) {
// 自定义验证函数
return value && typeof value === 'object' && 'name' in value;
}
}
}

这样的 props 声明允许子组件接收来自父组件的数据,并对数据进行类型验证、默认值设置以及自定义验证。

prop使用案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - prop</title>
<script src="https://cdn.staticfile.org/vue/3.2.36/vue.global.min.js"></script>
</head>
<body>
<div id="app">
<sutune city="长沙"></sutune>
<sutune city="上海"></sutune>
<sutune city="北京"></sutune>
</div>

<script>
const app=Vue.createApp({})
app.component('sutune',{
props:['city'],
template:'<h1>{{city}}</h1>'
}
)

app.mount('#app')
</script>
</body>
</html>

代码的解释:

  1. 在HTML中,有一个具有 id 为 “app” 的 div 元素,它将用于挂载Vue应用。
  2. 在Vue应用的JavaScript部分,首先通过 Vue.createApp({}) 创建了一个Vue应用实例。
  3. 使用 app.component 方法注册了一个全局组件,该组件名为 “sutune”。这个全局组件接受一个名为 “city” 的 props 属性,用于接收从父组件传递的城市名称。这里 city 是一个单一的属性,没有指定特定的类型。因此,Vue 3 不会强制检查传递给 city 的值的类型,而会接受任何类型的值。
  4. 在组件的模板中,使用 {{ city }} 插值将城市名称显示在 <h1> 元素中。
  5. 最后,使用 app.mount('#app') 将Vue应用实例挂载到具有 id 为 “app” 的HTML元素上。
  6. 在HTML中,我们使用了三次 “sutune” 组件,并为每个组件传递了不同的城市名称,分别是 “长沙”、”上海” 和 “北京”。每个 “sutune” 组件都会接收到相应的城市名称,并在其模板中显示出来。

动态prop

类似于用v-bind绑定 HTML 特性到一个表达式,也可以用v-bind动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:

下面这个示例演示了如何在 Vue 3 中创建和使用全局组件,以及如何在父组件中使用 v-for 循环来动态渲染多个子组件,并通过 props 将数据传递给子组件,实现了城市信息的动态展示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 动态prop</title>
<script src="https://cdn.staticfile.org/vue/3.2.36/vue.global.min.js"></script>
</head>
<body>
<div id="app">
<sutune v-for="site in sites" :id="site.id" :title="site.title"></sutune>
</div>

<script>
const Site={
data(){
return {
sites: [
{id:1,'title':'武汉'},
{id:2,'title':'长沙'},
{id:3,'title':'深圳'}
]
}
}
}

const app=Vue.createApp(Site)
app.component('sutune',{
props: ['id','title'],
template: `<h4>{{id}}-{{title}}</h4>`
}
)
app.mount('#app')

</script>
</body>
</html>

这段代码演示了如何在 Vue 3 中创建一个简单的应用,其中包括一个父组件(site)和一个子组件(sutune)。在父组件中,使用 v-for 指令动态地渲染多个子组件,并通过 props 将数据传递给子组件以渲染不同的内容。以下是代码的解释:

  1. 在 HTML 部分,有一个具有 id 为 “app” 的 div 元素,它将用于挂载 Vue 应用。
  2. 在 Vue 应用的 JavaScript 部分,首先创建了一个 site 对象。在 data 选项中,定义了一个名为 sites 的数组,其中包含了三个对象,每个对象都有 idtitle 属性,代表了不同城市的信息。
  3. 使用 Vue.createApp(site) 创建了一个 Vue 应用实例,并将其赋给 app 变量。
  4. 使用 app.component 方法注册了一个全局组件,该组件名为 “sutune”。这个组件接受两个 props 属性,分别是 idtitle,用于接收从父组件传递的城市信息。
  5. 在组件的模板中,使用 {{ id }}{{ title }} 插值将城市的 idtitle 属性显示在 <h4> 元素中。
  6. 在父组件中,使用 v-for 循环遍历 sites 数组,并为每个数组元素创建一个 “sutune” 子组件。这样,每个子组件都会接收到不同的城市信息,并在页面上显示出来。

prop验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue Prop Validator 示例</title>
<script src="https://cdn.staticfile.org/vue/3.2.36/vue.global.min.js"></script>
</head>
<body>
<div id="app">
<my-component :number="6"></my-component>
</div>

<script>
const app = Vue.createApp({});

app.component('my-component', {
props: {
number: {
type: Number,
validator(value) {
// 自定义验证函数,检查是否为偶数
return value % 2 === 0;
}
}
},
template: `
<div>
<p v-if="numberIsValid">偶数: {{ number }}</p>
<p v-else>不是偶数: {{ number }}</p>
</div>
`,
computed: {
numberIsValid() {
// 在模板中使用验证结果
return this.number % 2 === 0;
}
}
});

app.mount('#app');
</script>
</body>
</html>

defineProps

  • defineProps 是 Vue 3 Composition API 中的一个函数,用于在一个组件中定义可接收的 props。在函数式组件和setup函数内部使用它。
  • <script setup> 中必须使用 defineProps API 来声明 props ,它们具备完整的类型推断并且在 <script setup> 中是直接可用的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div>
<h1>name:{{ name }}</h1>
<p>age:{{ age }}</p>
</div>
</template>

<script setup>
import { defineProps } from 'vue';

// const props = defineProps(['name', 'age']); //列表形势定义props

//定义prop属性
const props = defineProps({
name: String,
age: {
type:Number,
default:20
},
});

</script>

在父组件中直接传值如下

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<div>
<Child :name="parentname" :age="parentage" />
</div>
</template>

<script setup>
import Child from './Child.vue';

const parentname = 'sutune';
const parentage = 32;
</script>

参考资料