引用官网的一句话:父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。
以字符串数组形式列出的 prop:
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
但是,通常你希望每个 prop 都有指定的值类型。这时,你可以以对象形式列出 prop,这些属性的名称和值分别是 prop 各自的名称和类型:
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
这不仅为你的组件提供了文档,还会在它们遇到错误的类型时从浏览器的 JavaScript 控制台提示用户。你会在这个页面接下来的部分看到类型检查和其它 prop 验证。
单向数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
有两种常见的试图改变一个 prop 的情形:
1.这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
2.这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
为了定制 prop 的验证方式,你可以为 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
}
}
}
})
当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
父组件
<template>
<div>
父组件:<input type="text" v-model="inputName"/>
<child :inputName='inputName'></child>
</div>
</template>
<script>
import child from '@/page/child';
export default {
components: {
child
},
data() {
return {
inputName:''
};
}
};
</script>
子组件
<template>
<div>
子组件:<span>{{inputName}}</span>
</div>
</template>
<script>
export default {
// 接收父组件的值,props里面值不能改变
// props:['inputName',] // 写法一
props: { // 对象写法
inputName: {
type: String,
require: true
}
}
};
</script>
方法一:在父组件v-on监听子组件传过来的值
父组件
<template>
<div>
父组件:<input type="text" v-model="inputName"/>
<child :inputName='inputName' v-on:child-by-value="childByValue"></child>
</div>
</template>
<script>
import child from '@/page/child';
export default {
components: {
child
},
data() {
return {
inputName:''
};
},
methods: {
childByValue(childValue) {
this.inputName = childValue;
}
}
};
</script>
子组件
<template>
<div>
子组件:<span>{{inputName}}</span>
<div>
<input type="button" value="给父组件传值" @click="childClick"/>
</div>
</div>
</template>
<script>
export default {
// 接收父组件的值,props里面值不能改变
// props:['inputName',] // 写法一
props: { // 对象写法
inputName: {
type: String,
require: true
}
},
data() {
return {
childValue: '我是子组件的数据'
};
},
methods: {
childClick () {
// child-by-value是在父组件on监听的方法
// 第二个参数this.childValue是需要传的值
this.$emit('child-by-value', this.childValue);
}
}
};
</script>
方法二:在父组件上使用.sync
https://www.jianshu.com/p/6b062af8cf01
父组件
<template>
<div>
父组件:<input type="text" v-model="inputName"/>
<child :inputName.sync='inputName'></child>
</div>
</template>
<script>
import child from '@/page/child';
export default {
components: {
child
},
data() {
return {
inputName:''
};
}
};
</script>
子组件
<template>
<div>
子组件:<span>{{inputName}}</span>
<div>
<input type="button" value="给父组件传值" @click="childClick"/>
</div>
</div>
</template>
<script>
export default {
// 接收父组件的值,props里面值不能改变
props: { // 对象写法
inputName: {
type: String,
require: true
}
},
data() {
return {
childValue: '我是子组件的数据'
};
},
methods: {
childClick() {
this.$emit('update:inputName',this.childValue);
}
}
};
</script>
event bus