组件注册方式
一个组件在使用之前,必须先注册,否则会报错。而注册组件的方式有两种,分别是全局注册和局部注册。
在 Vue3 中,我们可以通过 app.component 方法来注册一个全局组件,该方法接收两个参数,第一个参数是组件的名称,第二个参数是组件的选项对象。
而局部注册则是通过 components 选项来实现的,该选项接收一个对象,对象的键是组件的名称,值是组件的选项对象。
全局注册
通过修改 main.js 文件,我们可以在全局注册一个组件。
1 2 3 4
| app.component('my-component', { template: '<div>my component</div>' })
|
e.g.
1 2 3 4 5 6 7 8 9 10 11 12
| import { createApp } from 'vue' import App from './App.vue'
const app = createApp(App)
app.component('my-component', { template: '<div>my component</div>' })
app.mount('#app')
|
全局注册的组件可以在任何组件中使用,但是如果组件过多,会导致全局变量过多,不利于维护。并且如果被注册的组件没有被使用,也会被打包到最终的代码中,增加了代码的体积。
局部注册
局部注册的组件只能在当前组件中使用,但是不会污染全局变量。
1 2 3 4 5 6 7 8 9 10
| import { createApp } from 'vue' import App from './App.vue' import MyComponent from './components/MyComponent.vue'
const app = createApp(App)
app.component('my-component', MyComponent)
app.mount('#app')
|
组件传递数据
组件与组件间并非孤立的,它们之间是可以相互通信的。
在 Vue3 中,组件之间的数据传递方式与 Vue2 中有所不同。
在 Vue2 中,我们可以通过 props 选项来实现父子组件之间的数据传递,而在 Vue3 中,我们同样可以通过 props 选项来实现父子组件之间的数据传递,但是 props 选项的使用方式与 Vue2 中有所不同。
props 使用
我们在 components 文件夹中创建一个 ParentComponent.vue 文件,该文件是父组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <template> <div> <p>父组件</p> <p>{{ name }}</p> <ChildComponent :name="name" /> </div> </template>
<script> import ChildComponent from './ChildComponent.vue'
export default { components: { ChildComponent }, data() { return { name: 'a' } } } </script>
|
在父组件中,我们通过 data 选项定义了一个 name 属性,并将其绑定到了模板中。
然后我们在 components 文件夹中创建一个 ChildComponent.vue 文件,该文件是子组件。
1 2 3 4 5 6 7 8 9 10 11 12
| <template> <div> <p>子组件</p> <p>{{ name }}</p> </div> </template>
<script> export default { props: ['name'] } </script>
|
在子组件中,我们通过 props 选项定义了一个 name 属性,该属性的值是一个数组,数组中的元素就是我们要接收的数据的名称。
组件传递多种类型数据
在上一节中,我们通过 props 选项实现了父子组件之间的数据传递,但是我们只传递了一个字符串类型的数据,那么如果我们要传递多种类型的数据,该怎么办呢?
我们在 components 文件夹中创建一个 ParentComponent.vue 文件,该文件是父组件。
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
| <template> <div> <p>父组件</p> <p>{{ name }}</p> <p>{{ age }}</p> <p>{{ height }}</p> <p>{{ favorite }}</p> <ChildComponent :name="name" :age="age" :height="height" :favorite="favorite" /> </div> </template>
<script> import ChildComponent from './ChildComponent.vue'
export default { components: { ChildComponent }, data() { return { name: 'a', age: 18, height: 1.88, favorite: ['a', 'b', 'c'] } } } </script>
|
在父组件中,我们通过 data 选项定义了三个属性,并将其绑定到了模板中。
然后我们在 components 文件夹中创建一个 ChildComponent.vue 文件,该文件是子组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <template> <div> <p>子组件</p> <p>{{ name }}</p> <p>{{ age }}</p> <p>{{ height }}</p> <ul> <li v-for="(item, index) in favorite" :key="index">{{ item }}</li> </ul> </div> </template>
<script> export default { props: ['name', 'age', 'height', 'favorite'] } </script>
|
在子组件中,我们通过 props 选项定义了四个属性,该属性的值是一个数组,数组中的元素就是我们要接收的数据的名称。
上面的例子中,我们传递了字符串、数字、浮点数和数组四种类型的数据,但是如果我们要传递对象类型的数据,该怎么办呢?
修改 ParentComponent.vue 文件,如下所示。
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
| <template> <div> <p>父组件</p> <p>{{ info }}</p> <ChildComponent :info="info" /> </div> </template>
<script> import ChildComponent from './ChildComponent.vue'
export default { components: { ChildComponent }, data() { return { info: { name: 'b', age: 19, height: 1.77 } } } } </script>
|
修改 ChildComponent.vue 文件,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <template> <div> <p>子组件</p> <p>{{ info.name }}</p> <p>{{ info.age }}</p> <p>{{ info.height }}</p> </div> </template>
<script> export default { props: ['info'] } </script>
|
我们还可以通过 type 选项来指定接收的数据的类型。
使用上面例子的 ParentComponent.vue 文件。修改 ChildComponent.vue 文件,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <template> <div> <p>子组件</p> <p>{{ info.name }}</p> <p>{{ info.age }}</p> <p>{{ info.height }}</p> </div> </template>
<script> export default { props: { info: { type: Object } } } </script>
|
传递的数据类型不是对象,那么就会报错。
我们还可传递 boolean 类型的数据。
修改 ParentComponent.vue 文件,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <template> <div> <p>父组件</p> <p>{{ isShow }}</p> <ChildComponent :isShow="isShow" /> </div> </template>
<script> import ChildComponent from './ChildComponent.vue'
export default { components: { ChildComponent }, data() { return { isShow: true } } } </script>
|
修改 ChildComponent.vue 文件,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <template> <div> <p>子组件</p> <p>{{ isShow }}</p> </div> </template>
<script> export default { props: { isShow: { type: Boolean default() { return false } } } } </script>
|
props 验证
上面我们通过 type 选项来指定接收的数据的类型,其实可以用做简单的验证,但是还有更强大的验证方式。
我们可以通过 required 选项来指定接收的数据是否必须传递。
修改 ParentComponent.vue 文件,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <template> <div> <p>父组件</p> <p>{{ name }}</p> <ChildComponent :name="name" /> </div> </template>
<script> import ChildComponent from './ChildComponent.vue'
export default { components: { ChildComponent }, data() { return { name: 'a' } } } </script>
|
修改 ChildComponent.vue 文件,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <template> <div> <p>子组件</p> <p>{{ name }}</p> </div> </template>
<script> export default { props: { name: { type: String, required: true } } } </script>
|
添加 required: true 选项后,如果父组件没有传递 name 属性,那么就会报错。
props 是只读的,我们不能在子组件中修改 props 中的数据。
此外,我们还可以通过 validator 选项来指定自定义验证函数。
保持 ParentComponent.vue 文件不变。修改 ChildComponent.vue 文件,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <template> <div> <p>子组件</p> <p>{{ name }}</p> </div> </template>
<script> export default { props: { name: { type: String, required: true, validator(value) { return value.length > 0 } } } } </script>
|