一、组件传值
组件间的传值形式
父子传值: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
事件