一、组件传值
组件间的传值方式
父子传值:props、emit、$parent、$chidren、ref
兄弟之间传值:事件总线(on、emit)、Vuex
传值实例
(1)父组件传到子组件(props)
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
// 父组件
// 子组件接收 ceshi
{{test}}
(2)子组件传到父组件(emit)
子组件通过emit触发事件给父组件,父组件通过on去监听数据的变化。
// 父组件
// 子组件接收 ceshi
{{test}}
二、prop
prop类型
以字符串形式列出:
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
通常我们都需要每个 prop 都有指定的值类型,因此通过对象的形式列出、分别标明prop的名称和类型以及默认值
props: {
test: String,
likes: {
type: Number,
default: () => []
},
isPublished: {
type: Boolean,
default: false
}
}
传递静态或动态 Prop
// 静态传值
// 动态赋予一个变量的值
// 动态赋予一个复杂表达式的值
单向数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定
:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
需要改变prop时,可以通过
(1)子组件内需要将prop作为本地数据进行使用,可以在data中将这个prop作为初始值
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
(2)这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。
三、自定义事件(v-model)
双向绑定v-model
一个组件上的 v-model 默认会利用名为 value 的 prop
和名为 input
的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。model 选项可以用来避免这样的冲突:
// 子组件
在父组件使用v-model,通过该语句实现price变量与输入值双向绑定
// 等同于
执行流程:
1、子组件通过通过 prop 接收父组件的数据price
2、当input进行输入时,会触发input事件
3、通过 $emit 提交事件,将值传递给父组件
4、父组件的input事件被触发,将会更新变量price的值
5、父组件在通过props传值给子组件
v-bind 实现单向绑定
v-model 实现双向绑定
.sync修饰符
真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件两侧都没有明显的变更来源。因此推荐update:myPropName
的模式触发事件
vue事件名可以updata:prop去定义,用于处理prop传递的新值
组件内部将通过$emit('update:dtitle', val)触发事件,修改title的值
// 子组件
props: ['title'],
updateVal(val) {
this.$emit('update:dtitle', val)
}
// 父组件
注意事项:
1、 .sync 修饰符的 v-bind 不能和表达式一起使用
2、组件内部需要$emit触发的事件名,格式为update:prop
同时在使用sync的时候,简化了绑定prop
和绑定update:prop
事件