# Props & Emits
# 父子组件传值
# 父传子
- 父组件传值
<template>
<child :data="data"></child>
</template>
<script>
export default {
// ...
data() {
return {
data: 'Hello Vue'
}
}
}
</script>
- 子组件通过
props属性接受
<template>
<span>{{ data }}</span>
</template>
<script>
export default {
// ...
props: ['data']
}
</script>
# 子传父
原理
父组件在编译模板后将自定义事件evName及其回调函数cb通过vm.$on(evName, cb)添加到子组件的事件中心Events。
子组件通过vm.$emit(evName, ...args)触发自身的事件中心Events上的对应的自定义事件
- 子组件通过
$emit触发自定义事件
<template>
<button @click="send"></button>
</template>
<script>
export default {
// ...
methods: {
send() {
this.$emit('update', 'hello world')
}
}
}
</script>
- 父组件
<template>
<child @update="message"></child>
</template>
<script>
export default {
// ...
data() {
return {
data: ''
}
}
methods: {
message(msg) {
this.data = msg
}
}
}
</script>
# v-model 原理
单向数据流
Vue 实现的双向绑定 其实就是:value与@input语法糖
- 父组件
<template>
<child v-model="data"></child>
</template>
<script>
export default {
data() {
return {
data: ''
}
}
}
</script>
子组件
<template>
<input type='text' :value="value" @input="update">
</template>
<script>
export default {
// ...
props: ['value'],
methods: {
update(event) {
this.$emit('input', event.target.value)
}
}
}
</script>
model 属性
<template>
<input type='text' :value="propName" @input="update">
</template>
<script>
export default {
// ...
props: ['propName'],
model: {
porp: 'propName', // 名字随便
event: 'eventName' // 可以是自定义事件也可以是input,click事件
}
methods: {
update(event) {
this.$emit('eventName', event.target.value)
}
}
}
</script>
如果希望将一个对象的所有属性作为prop传入
<template>
<child v-bind="props"><children>
</template>
<script>
export default {
// ...
data () {
return {
props: {
total
}
}
}
}
</script>
# Props 验证
- 概述:
props可以使用对象形式接受一下参数实现相应的验证 type:接受参数的数据类型,有以下类型StringNmuberBoolean(如果Boolean类型,则父组件传值没有参数默认为false)ObjectArrayMapRegexpDateFunctionSymbol
default:接受参数的默认值。如果父组件没有传入值则使用默认值,引用类型需要使用方法返回一个默认值required:必须要传的值validator:可以使用此函数达到枚举的效果
export default {
props: {
a: {
type: String, // 类型要是字符串
default: 'hello', // 默认值,一般不与 required 放在一起使用
validator(value) {
// 使用验证可以达到枚举的效果
// 这个值必须是下列字符串中的一个
return ['succescc', 'warning', 'danger'].includes(value); //includes()检查值是否在数组中存在
}
},
b: {
type: [String, Number], // 可以是多种类型
required: true, // 必传,一般不与 default 放在一起使用
},
c: {
type: Array,
default() {
return [1, 2, 3]
}
}
}
}
# .sync 修饰符
背景
在有些情况下,我们可能需要对一个prop进行双向绑定。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。
- 父组件
<template>
<child :text.sync="text"></child>
</template>
<script>
export default {
data() {
return {
text: 'hello vue'
}
}
}
</script>
- 子组件
<template>
<div @click="update">{{ text }}</div>
</template>
<script>
export default {
props: ['text'],
methods: {
update() {
// 使用了.sync 修饰符,可以直接使用 update:propsName 更新
this.$emit('update:text', 'hello')
}
}
}
</script>
.sync语法糖
.sync修饰符在模板编译以后会变成以下
<template>
<child :value="value" @update:value="update"></child>
</template>
<script>
export default {
data() {
return {
value: 'hello vue'
}
},
methods: {
update(value) {
this.value = value
// 子组件 this.$emit('update:value', value)
}
}
}
</script>