组件是可以复用的 vue 实例
在通过 new Vue 创建的 Vue 根实例中,组件作为自定义元素使用
每用一次组件,就会有一个它的新实例被创建
组件的 data 必须是函数
一个网页可以看作是一颗嵌套的组件树:
组件名
- 使用全小写并用短横线分割 (推荐)
/* 定义 */
Vue.component('component-name', {/* ... */})
/* 使用 */
<component-name>
- 使用首字母大写
/* 定义 */
Vue.component('ComponentName', { /* ... */ })
/* 使用 */
<ComponentName>
<component-name>
全局注册
注册后可用在任何新创建的 Vue 实例(new Vue)的模板中与所有子组件中
Vue.component('component-name', {
// 选项
})
局部注册
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB,
}
})
在组件 ComponentC
中使用局部注册的 ComponentA
, ComponentB
:
推荐使用模块系统:创建一个 components
目录,并将每个组件放置在其各自的文件中。
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentA.vue'
export default {
components: {
ComponentA, // 析构赋值,相当于 {ComponentA: ComponentA}
ComponentB
}
}
由于有些操作系统不分大小写,因此推荐文件名使用全小写,组件名使用大驼峰
选项 Props
- props 用于存放外部属性,即从父组件中获得数据
- 类型:Array | Object
- 由于 HTML大小写不敏感,因此在模板中使用 kebab-case (短横线分隔命名) 命名
传递值和函数:通过父组件改变子组件的 props 值
子组件 props.vue 中:
<template>
<div>
{{ number }}
<button @click="fn">+1</button>
</div>
</template>
<script>
export default {
name: "Prop",
// props 为对象,可设置类型检验
props: {
number: Number,
fn: Function,
},
// props 为数组
// props: ["number", "fn"],
};
</script>
<style lang="scss">
</style>
父组件中:
<template>
<div id="app">
<Prop :number="n" :fn="add" />
</div>
</template>
<script>
import Prop from "./components/prop.vue";
export default {
name: "App",
data() {
return {
n: 0,
};
},
components: {
Prop,
},
methods: {
add() {
console.log(1);
this.n += 1;
},
},
};
</script>
<style lang="scss">
</style>
- 使用
v-bind
动态赋值
父组件中:
<!-- 传递静态值,number 为字符串 n -->
<Prop number="n" />
<!-- 动态赋值使用 v-bind,双引号内为 js 代码, number 为变量 n 的值 -->
<Prop :number="n" />
<!-- 以下两个等价,都传递字符串 'n' -->
<Prop number="n" />
<Prop :number=" 'n' " />
- props 可传递的 type : String, Number, Boolean, Array, Object, Date, Function, Symbol, 自定义构造函数
- 需要规定每个 prop 的类型与类型检验时,可使用对象
- props 验证:为 props 中的值提供带有验证需求的对象,若验证失败则产生警告
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
- 验证自定义构造函数
function Person (firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
Vue.component('blog-post', {
props: {
author: Person
}
})
修饰符 .sync
- 父子 props 之间单向下行绑定,即只能通过父组件改变子组件的 props 属性,反过来则不行
- 若要在子组件中改变自身的 props 值,同时父组件同步更新,即实现双向绑定,则可使用
update:myPropName
的模式触发事件,父组件中使用v-on
监听事件,为了方便,为这种模式提供简写.sync
- 带有
.sync
修饰符的v-bind
不能和表达式一起使用,只能提供你想要绑定的属性名
子组件:
<template>
<div class="child">
<!-- 更改父组件属性 -->
<button @click="$emit('update:number', number + 1)">+1</button>
</div>
</template>
<script>
export default {
name: "Child",
props: ["number"],
};
</script>
<style></style>
父组件:
<template>
<div class="app">
{{ n }}
<hr />
<!-- $event 可获取子组件中 $emit 的参数-->
<Child :number="n" v-on:update:number="n = $event" />
<!-- 简写 <Child :number.sync="n" /> -->
</div>
</template>
<script>
import Child from "./components/child.vue";
export default {
name: "Father",
data() {
return {
n: 0,
};
},
components: { Child },
};
</script>
<style></style>