3.Vue2组件间的通信方式

1.组件通信的分类

        1.父子组件通信(props、$emit、ref、v-model、具名插槽、作用域插槽)

        2.兄弟组件通信($bus、$parent、消息订阅与发布)

        3.祖孙与后代之间的通信($attrs、$listener、provide、inject)

        4.非关系组件之间的通信(vuex)

2.组件通信方法

2.1 Vue2组件通信方式

2.1.1 通过props传值

//Child.vue
<template>
  <div class="about">
    <p>{{ name }}</p>
    <p>{{ age }}</p>
  </div>
</template>

<script>
export default {
  // 第一种写法
  // props: ['name', 'age']
  props: {
    name: {
      type: String,
      default: '默认值'
    },
    age: {
      type: Number,
      default: 18
    }
  }
}
</script>

//Farther.vue
<template>
  <div class="home">
    <ChildView name="aDong" age="21"></ChildView>
  </div>
</template>

<script>
import ChildView from './ChildView.vue'
export default {
  name: 'FatherView',
  components: {
    ChildView
  }
}
</script>

  2.1.2 使用v-model传值

vue中,v-model 的值相当于默认传递了一个名为 value 的 prop 和一个名为 input 的方法(注意,这个valueprop是需要在自定义组件内声明的)

//Father.vue
<template>
  <div >
    <ChildView v-model="value"></ChildView>
    {{ value }}
  </div>
</template>

<script>
import ChildView from './ChildView.vue'
export default {
  name: 'FatherView',
  components: {
    ChildView
  },
  data () {
    return {
      value: '我是父组件aDong'
    }
  }
}
</script>

//Child.vue
<template>
  <div class="about">
    <input type="text" :value="obj" @input="handlerChange">
  </div>
</template>

<script>
export default {
  // 这里的值一定要与上面:value后面绑定的名称一致
  props: ['obj'],
  methods: {
    handlerChange (e) {
      this.$emit('input', e.target.value)
    }
  }
}
</script>

  2.1.3 使用$emit传值

//Father.vue
<template>
  <div >
    <ChildView @add="changeNum($event)"></ChildView>
    {{ num }}
  </div>
</template>

<script>
import ChildView from './ChildView.vue'
export default {
  name: 'FatherView',
  components: {
    ChildView
  },
  data () {
    return {
      num: 21
    }
  },
  methods: {
    changeNum () {
      this.num++
    }
  }
}
</script>

//Child.vue

<template>
  <div class="about">
    <button @click="handler">点击我年龄+1</button>
  </div>
</template>

<script>
export default {
  methods: {
    handler () {
      this.$emit('add')
    }
  }
}
</script>

2.1.4 使用ref传值

//Father.vue
<template>
  <div >
    <ChildView ref="child"></ChildView>
    <button @click="getAge">点击我获取子组件数据</button>
  </div>
</template>

<script>
import ChildView from './ChildView.vue'
export default {
  name: 'FatherView',
  components: {
    ChildView
  },

  methods: {
    getAge () {
      console.log('父组件拿到了子组件数据', this.$refs.child.age)// 父组件拿到了子组件数据 21
    }
  }
}
</script>

//Child.vue
<template>
  <div class="about">
  </div>
</template>

<script>
export default {
  data () {
    return {
      age: 21
    }
  }
}
</script>


2.1.5 全局事件总线EventBus

主要应用于兄弟组件

// 定义一个全局事件总线
export class Bus {
  constructor () {
    this.callbacks = {} //
  }

  $on (name, fn) {
    this.callbacks[name] = this.callbacks[name] || []
    this.callbacks[name].push(fn)
  }

  $emit (name, args) {
    if (this.callbacks[name]) {
      this.callbacks[name].forEach((cb) => cb(args))
    }
  }
}

//一定要在main.js文件中将bus挂载到vue实例原型身上
Vue.prototype.$bus = new Bus()

//child1.vue
this.$bus.$emit('foo')//触发事件

//child2.vue
this.$bus.$on('foo',this.handler)//绑定事件

2.1.6 parent或者root

适用于兄弟组件之间通信

//child1.vue
this.$parent.on('add',this.add)

//child2.vue
this.$parent.emit('add') 

2.1.7 attrs与listener

多层嵌套组件传递数据时,如果只是传递数据,而不做中间处理的话就可以用这个,比如父组件向孙子组件传递数据时

$attrs:包含父作用域里除 class 和 style 除外的非 props 属性集合。通过 this.$attrs 获取父作用域中所有符合条件的属性集合,然后还要继续传给子组件内部的其他组件,就可以通过 v-bind="$attrs"

$listeners:包含父作用域里 .native 除外的监听事件集合。如果还要继续传给子组件内部的其他组件,就可以通过 v-on="$linteners"

使用方式是相同的

// 父组件
<template>
  <div class="">
    <HelloWorld :name="name" val="你好s-r-d"></HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
  data() {
    return {
      name: "父组件数据",
    };
  },
  components: { HelloWorld },
};
</script>
// 子组件
<template>
  <div>
    <input type="text" />
     // 孙组件
    <SunChild v-bind="$attrs"></SunChild>
  </div>
</template>
<script>
import SunChild from "./sun-child.vue";
export default {
  data() {
    return {};
  },
  mounted() {
    console.log(this.$attrs); // 可以拿到父组件传来的数据
  },
  components: { SunChild },
};
</script>
// 孙组件
export default {
  mounted() {
    console.log(this.$attrs);
  },
};
​

listener的使用方式

 // 给Grandson隔代传值 
<Child2 msg="lalala" @some-event="onSomeEvent"></Child2>  

// Child2 做展开 
<Grandson v-bind="$attrs" v-on="$listeners"></Grandson>  

// Grandson使用 
<div @click="$emit('some-event', 'msg from grandson')">  
{{msg}}  
</div>

2.1.8 provide和inject

用于祖先给后代组件传值

provide(){  
    return {  
        foo:'foo'  
    }  
}


inject:['foo']

2.1.9 Vuex

// vuex 里定义共享的数据,在哪个组件都可以访问
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import vuexPersist from "vuex-persist";
export default new Vuex.Store({
  state: {
    data: 'vuex 的数据',
    a: 1,
    b: 2,
  },
  mutations: {},
  actions: {},
  modules: {},
  getters: {
    num(state) {
      return state.a + state.b
    }
  },
})

2.1.10 具名插槽和作用域插槽

具名插槽是在父组件中通过slot属性,给插槽命名,在子组件中通过slot标签,根据定义好的名字填充到对应的位置。

作用域插槽是带数据的插槽,子组件提供给父组件的参数,父组件根据子组件传过来的插槽数据来进行不同的展现和填充内容。在标签中通过 v-slot="value" 来接受数据。

// 父组件
<template>
  <div class="">
    <HelloWorld>
      <template v-slot:a="value">
        <h2>{{ name }}</h2> // 这个是具名插槽
         <!--  value 是子组件传过来的数据 -->
        <h2>{{ value.value }}</h2> // 这个是作用域插槽
      </template>
    </HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
  data() {
    return {
      name: "具名插槽 slot插槽传数据 父传子",
    };
  },
  components: { HelloWorld },
};
</script>
 
 
// 子组件
<template>
  <div>
    <slot name="a" :value="value"></slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      value: "我是子组件数据 作用域插槽子传父 srd",
    };
  },
  methods: {},
};
</script>

2.1.11 $root

$root 可以拿到 App.vue 里的数据和方法

// HelloWorld 子组件添加数据
<template>
  <div></div>
</template>
<script>
export default {
  data() {
    return {};
  },
  mounted() {
    // 写入根组件的数据
    this.$root.foo = 2;
  },
  methods: {},
};
</script>
 
// Home 父组件访问数据
<template>
  <div class="">
    <HelloWorld></HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
    data() {
        return {};
    },
    mounted() {
        // 获取根组件的数据
        console.log(this.$root.foo);
    },
    components: { HelloWorld }
};
</script>

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值