组件是可以复用的 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 = firstNamethis.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>
