一、组件传值
组件间的传值形式
父子传值:props、emit、$parent、$chidren、ref
兄弟之间传值:事件总线(on、emit)、Vuex
传值实例
(1)父组件传到子组件(props)
一个组件默认能够领有任意数量的 prop,任何值都能够传递给任何 prop。
// 父组件<template> <div> <ceshi @test="test"></ceshi> </div></template><script>export default { data() { test: '测试' }}</script>// 子组件接管 ceshi<template> <div> {{test}} </div></template><script>export default { props: { test: String } data() { }}</script>
(2)子组件传到父组件(emit)
子组件通过emit触发事件给父组件,父组件通过on去监听数据的变动。
// 父组件<template> <div> <ceshi :test="test" @change="change"></ceshi> </div></template><script>export default { data() { test: '测试' }, methods: { change(val){ console.log(val) } }}</script>// 子组件接管 ceshi<template> <div> {{test}} <button @click="getTitle"></button> </div></template><script>export default { `props: { test: String }` data() { title: '子组件' }, methods: { getTitle(){ this.$emit('change', this.title) // 将值绑定到change上传递过来 } }}</script>
二、prop
prop类型
以字符串模式列出:
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
通常咱们都须要每个 prop 都有指定的值类型,因而通过对象的模式列出、别离表明prop的名称和类型以及默认值
props: { test: String, likes: { type: Number, default: () => [] }, isPublished: { type: Boolean, default: false }}
传递动态或动静 Prop
// 动态传值<blog-post title="My journey with Vue"></blog-post>// 动静赋予一个变量的值<blog-post v-bind:title="post.title"></blog-post>// 动静赋予一个简单表达式的值<blog-post v-bind:title="post.title + ' by ' + post.author.name"></blog-post>
单向数据流
所有的 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 选项能够用来防止这样的抵触:
// 子组件<template> <div> <el-input v-model="price" @input="updateVal"></el-input> </div></template><script>export default { // model用于扭转v-model绑定的属性和抛出事件(实时监听) model: { prop: 'price', event: 'change' }, props: { price: Number }, methods: { updateVal(val){ this.$emit('change', val) // 监听price值变动,传递给父组件 } }}</script>
在父组件应用v-model,通过该语句实现price变量与输出值双向绑定
<ceshi @change="change" v-model="price"></ceshi>// 等同于<ceshi @change="change" :value="price" @input="price=$event.target.value"></ceshi>
执行流程:
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的值
// 子组件<el-input v-model="title" @input="updateVal"></el-input>props: ['title'],updateVal(val) { this.$emit('update:dtitle', val)}
// 父组件<ceshi @update:dtitle="title = $event" :title.sync="title"></ceshi>
注意事项:
1、 .sync 修饰符的 v-bind 不能和表达式一起应用
2、组件外部须要$emit触发的事件名,格局为update:prop
同时在应用sync的时候,简化了绑定prop
和绑定update:prop
事件