laydate组件 无法传值_vue组件通信
vue组件通信方式主要有5种:
- 父子组件:props,$emit。缺点:组件嵌套层次多的话,传递数据比较麻烦。
- 祖先组件向所有后代传数据:依赖注入(inject和provide)。缺点:无法监听数据修改的来源,不支持响应式。
- $root / $parent / $children / ref。缺点:要求组件之间要有传递性。
- 兄弟组件常用:事件总线even bus,引出后面的vuex。缺点:不支持响应式。
- 任意两个组件:vuex 状态管理模式。推荐
1.props和$emit
props是父组件向子组件传值,使用v-bind属性绑定
$emit为子向父传值,使用v-on事件绑定
- 首先,通过在父组件中自定义属性绑定的形式(v-bind:属性名)(语法糖为:属性名),把需要传递给子组件的数据,通过绑定给属性,传递给子组件使用。
- 那么,把参数传给子组件之后呢,我们是不是就可以在子组件中调用啦?现在还不行的,我们刚刚只把父组件中传过来,还需要在子组件中接收。
- 在子组件中,利用props接收这个自定义属性,在props:["属性名1","属性名2"...]中定义一下,子组件就能使用了
注意:
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
默认props中的参数只读,无法改变值,否则控制台会报错
<div id="app">
<div>{{num}}</div>
//父组件中定义自定义属性sub-num,给子组件传值
<blog-count :sub-num="num" :sub-user="user"></blog-count>
</div>
<script>
const blogCount={
//子组件中通过props属性接收父组件传递过来的数据
props:["subNum","subUser"],
template:`<div>
<p>这是从父组件传进来的数字:{{subNum}}</p>
<p>这是从父组件传进来的对象:{{subUser.name}}-{{subUser.age}}</p>
</div>`,
}
var vm=new Vue({
el:"#app",
data:{
num:2,
user:{
name:"zhangsan",
age:18
}
},
components:{
blogCount
}
})
</script>
前面写的是父组件向子组件传参,那么父组件中的方法是不是也可以传给子组件呢?
可以的。使用$emit即可。
$emit(参数1,参数2...)
- 在父组件中定义一个方法,然后通过v-on(语法糖为@)绑定这个方法,传给子组件。和传参一样的步骤(传参是通过v-bind绑定自定义属性)。
- 然后在子组件中,通过一些事件,如click点击事件,接收父组件传递来的方法。先在子组件中定义好click点击事件以及事件监听。然后通过$emit来拿到并触发父组件传递过来的方法
- 其中参数1为方法,参数234为参数,子组件向父组件传参便是用这个方法
子组件向父组件传递数据,通过 $emit派发事件,父组件中通过 v-on 接收该事件,拿到传递的数据。
<div id="app">
<div>{{num}}</div>
//父组件中定义方法father,通过v-on,传给子组件
<blog-count @son="father"></blog-count>
</div>
<script>
const blogCount={
template:`<button @click="clickHandle">点击接收子组件传递过来的数据</button>`,
data(){
return {num:6}
},
methods: {
clickHandle(){
//点击事件,使用 $emit派发事件son,顺便把子组件中的num传递给父组件
this.$emit("son",this.num);
}
}
}
var vm=new Vue({
el:"#app",
data:{
num:0
},
methods: {
//父组件中定义方法father,data为接收子组件传递的参数
father(data){
this.num=data;
}
},
components:{
blogCount
}
})
</script>
2.inject和provide
这两个需要配合使用。
在父组件中增加provide属性,里面是要给子组件传递的数据。provide的属性值是一个对象或者返回值是对象的函数
在子组件中增加inject属性,用于接收父组件传递过来的数据,它的属性值是字符串数组或者对象。
<div id="app">
<div>{{num}}</div>
<blog-count></blog-count>
</div>
<script>
const blogCount={
//子组件中使用inject属性来接收数据num
inject:["num"],
template:`<div>{{num}}</div>`
}
var vm=new Vue({
el:"#app",
data:{
num:10
},
//父组件中使用provide属性存放要传递的数据num
provide:function(){
return {
num:this.num
}
},
components:{
blogCount
}
})
</script>
缺点
- 这个方法不局限于父子组件,可以给任意后代传递数据,但是也因为在任意层级都能访问,导致数据追踪比较困难。
- 会将应用程序中的组件与它们当前的组织方式耦合起来,使重构变得更加困难。
- 所提供的属性是非响应式的。
3.$root / $parent / $children / ref
$root和$parent都能实现访问父组件的属性和方法,区别在于,如果有多级子组件,$parent访问得到最近一级父组件中的内容,$root访问得到根组件。
父组件:
data() {
return {
parent: 1,
};
},
methods: {
//父组件的方法
add() {
this.parent = this.parent + 1;
}
}
子组件:
mounted() {
console.log(this.$parent.parent) //直接通过this.$parent.parent得到父组件里的parent值 也可以通过该方法去调用里面的方法
},
methods: {
add() {
this.$parent.add(); //子组件里调用父组件的方法add
}
}
$children
返回的是子组件的集合,我们如果知道子组件的顺序,可以在父组件中直接用下标进行操作,例如:$children[0]
父组件中:
methods:{
FatherBtn(){
//changMsg为子组件中的方法
this.$children[0].changeMsg();
},
}
ref
- ref属性使用在普通DOM元素上,获取的是原生DOM元素
- ref属性使用在组件上,获取就是组件的实例对象
先给子组件标签加上ref属性
<son ref = "son"></son>
然后在父组件中:
this.$refs.son.子组件方法或者属性
但是这个是非响应的,所以应该避免在模板或计算属性中使用 $refs ,它仅仅是一个直接操作子组件的应急方案;
4.事件总线even bus
我们可以把这种方法可以看作是,把一个空的实例new Vue()
作为事件总线(事件中心),用它来派发和监听事件,可以实现任何组件间的通信,包括父子、兄弟、跨级。
- 使用$emit发送数据
- 使用$on接收数据
首先,我们先实例化一个even bus对象
var eventBus = new Vue()
然后假设我们有两个兄弟组件a和b,需要实现点击a中的按钮A向b传值
a中:
<!-- 组件a -->
<template>
<button @click="sendMsg()">按钮A, 向B传值</button>
</tempalte>
<script>
//引入even bus
import {eventBus} from "./EventBus.js"
export default {
data(){
return {
msg: "组件A的值"
}
}
methods: {
sendMsg(){
//语法:EventBus.$emit("msgName", msg),msg的值赋给msgName,传给事件总线
eventBus.$emit("fromA2B", this.msg)
}
}
}
</script>
b组件中:
<!-- 组件B -->
<template>
<button @click="reset()">{{msg}}</button>
</tempalte>
<script>
import {eventBus} from "./EventBus.js"
export default {
data(){
return {
msg: "按钮B,准备接收A的值"
}
}
mounted(){
//接收事件:EventBus.$on("msgName", function),从事件总线拿到叫msgName的数据
eventBus.$on("fromA2B", e => {
this.msg = e
})
}
}
</script>
移除:在vue页面销毁后,要将事件监听移除
import { eventBus } from './Event-bus.js'
eventBus.$off('fromA2B', {})
5.vuex
前面说到的父子组件,兄弟组件通信方式都只适合与小范围内数据共享,如果是一个大项目,需要频繁数据共享,则需要用到vuex。
可以通过下图清晰看出vuex的方便之处
vuex是实现组件全局状态管理的一种机制,可以方便地实现组件之间的数据共享。
优点
- 能在vuex中集中管理共享的数据,便于开发和维护
- 高效实现组件之间数据共享,提高开发效率
- 存储在vuex中的数据都是响应式的,能够实时保持数据与页面同步
vuex详细使用方法下一篇再写~~