vue2[初级]消息订阅与发布组件

这篇博客探讨了在Vue2中实现消息订阅与发布的三种方式:数据直接传递、调用父组件方法和自定义事件。重点讲解了使用自定义事件的详细步骤,包括在父组件中注册事件和子组件通过`this.$emit`调用。最后提到了使用pubsub-js库进行多级组件间通信的准备工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本节内容

vue中的消息订阅与发布组件 pubsub

– 回顾下父子两个组件之间的交互方式

  • 方式1 数据直接传递
    – 父组件定义data方法中定义数据 将数据名称绑定到标签中
    – 子组件通过props接收 然后通过for循环遍历数据或直接取值操作

方式1 代码思路

父组件
// 标签中绑定属性
<Menu222 :menus="menus" :webSide="webSide" />
// 定义数据
data(){
   return {
     webSide:{// logo图片连接
       url:'http://www/sun.com/',
       title:'Java官方网站'
     },
     menus:[
       {id:1,name:'科技2'},
       {id:2,name:'体育2'},
       {id:3,name:'财经2'},
       {id:4,name:'医疗2'},
       {id:5,name:'政治2'},
       {id:6,name:'教育2'}
     ]
   }
 }

子组件
// 直接取值或通过遍历取值
<a :href="webSide.url" :title="webSide.title" target="_blank">
 <img src="../assets/logo.jpg" alt="SUN JAVA" >
 </a>
 <ul>
   <!-- 这里必须要加上key 以免后期出现数据混乱 -->
   <li v-for="(menu,index) in menus" :key="menu.id">
     <a :href="'http://localhost/ment/'+menu.id">{{menu.name}}</a>
   </li>
 </ul>

// 接收父组件的属性
props:['menus','webSide']
  • 方式2 调用父组件中的方法
    – 首先父组件中定义方法并绑定到标签中
    – 然后子组件通过props接收
    – 子组件接收到父组件的方法后 在methods中通过this.父组件中的方法名来调用父组件中的方法

方式2 代码思路

// 父组件
// 绑定方法到标签中 addMenus
<Menu222 :menus="menus" :webSide="webSide" :addMenus="addMenus"/>

// 定义方法
 methods:{
    addMenus(menu){// 接收子组件调用时传递过来的值
      this.menus.push(menu);// 在menus数组的最后位置添加元素
    }
  }
  
// 子组件
// 页面传值操作
// input中双向绑定数据content
<input type="text" v-model="content" key="Math.random()"><br>
<button @click="add">添加</button>
// 接收父组件传递的属性
props:['menus','webSide','addMenus'],
  data(){ // 接收当前页面输入的值
    return {
      content:''
    }
  },
methods:{
    add(){
      const content = this.content.trim();
      if(!content){
        alert("菜单名称不能为空");
        return;
      }
      let menuu = {id:Math.random(),name:content};
     this.addMenus(menuu);
    }
  }

方式3 自定义事件

– 3.1 父组件通过注册事件方式将方法传递到子组件
– 3.1 子组件无法使用props接收了 因为父组件是注册事件 不是绑定属性
– 3.1 子组件可以使用this.$emit来调用

3.1 代码思路

父组件
// 注册@addMenus事件
<Menu222 :menus="menus" :webSide="webSide" @addMenus="addMenus"/> 

// 创建接收子组件的值并添加到当前组件的数据集合中的方法
methods:{
    addMenus(menu){
      this.menus.push(menu);// 在menus数组的最后位置添加元素
    }
  }
--------------------------------------------------
子组件
  <input type="text" v-model="content" key="Math.random()"><br>
  <button @click="add">添加</button>

// 子组件方法中接收页面的值并拼装成对象然后通过this.父组件中注册的方法名传递参数给父组件
 methods:{
    add(){
      const content = this.content.trim();
      if(!content){
        alert("菜单名称不能为空");
        return;
      }
      let menuu = {id:Math.random(),name:content};
	this.$emit('addMenus2',menuu); // 参数1 调用的是父组件中@addMenus2 参数2是需要传递值到父组件的属性

    }
  }

– 3.2 父组件中 使用mounted函数注册事件
– 3.2 mounted函数是vue生命周期中的页面加载完毕执行的函数,且只会执行一次
– 3.2 父组件中通过mounted函数注册时需要先获取所有引用标签
– 3.2 父组件中标签使用ref添加引用
– 3.2 父组件中mounted勾子函数中通过this. r e f s 获取引用标签 − − 3.2 子组件还是通过 t h i s . refs获取引用标签 -- 3.2 子组件还是通过this. refs获取引用标签3.2子组件还是通过this.emit调用父组件中的事件

3.2 代码思路

父组件
// ref指定引用
  <Menu222 :menus="menus" :webSide="webSide" ref="mm2"/>
  //当页面加载完毕后获取指定的引用标签并注册事件
  mounted () {
    // 生命周期中页面初始化后执行的勾子函数,且只执行一次
    // $refs可以获取到左右带有引用的标签 前提是标签中添加了ref
    // 获取到mm2的标签引用 添加注册事件 即 $on
    // $on 参数1 注册事件的名字,参数2是具体要注册的事件
    this.$refs.mm2.$on('addMenus2',this.addMenus);// 这句话的意思是给标签引用为mm2的标签注册addMenus2的addMenus事件 相当于@addMenu321='addMenus'
  }

// 子组件
// 页面传值 双向绑定到content属性
  <input type="text" v-model="content" key="Math.random()"><br>
  <button @click="add">添加</button>

props:['menus','webSide'], // 无法接收 'addMenus'
  data(){ // 接收当前页面输入的值
    return {
      content:''
    }
  },
  methods:{
    add(){
      const content = this.content.trim();
      if(!content){
        alert("名称不能为空");
        return;
      }
      let menuu = {id:Math.random(),name:content};
      this.$emit('addMenus2',menuu); // 参数1 调用的是父组件中@addMenus2 参数2是需要传递值到父组件的属性
    }
  }

– 前边三节主要是父 子两个组件之间的交互,在日常开发中多级之间传递数据,方法是比较多的 本节主要探索多级之间的交互

开始今天的正文 消息订阅与发布组件

工欲善其事必先利其器 订阅与发布组件是在pubsub中的 因此需要安装组件先

– 安装指令: npm install --save pubsub-js

  • 安装完成后 在父组件中定义mounted函数 在页面加载完成后执行订阅组件

父组件中修改

<template>
<!-- 不需要在添加引用或添加事件又或者添加绑定方法 传递至到子组件中的还是需要绑定的-->
<Menu :addMenu="addMenu" :webSide="webSIde"/>
</template>

<script>
import PubSub from 'pubsub-js'
</script>

mounted:{
// 订阅组件 相当于绑定监听事件
// subscribe参数1 订阅组件的名称 即 需要监听的名称
// subscribe参数2 回调函数 这里使用箭头函数(箭头函数表示的是vm实例 相当于全局的)
// subscribe参数2中如果使用function方式作为回调函数 则只能表示PubSub当前本身(局部的)
// subscribe参数2中msg 就是接收的子组件中发布的对应的父组件中订阅的名称
// subscribe参数2中data才是子组件中封装的返回数据
PubSub.subscribe('add2',(msg,data)=>{
this.addMenu(data);
});
}

子组件中发布

methods:{
let menuu = {id:Math.random(),name:content};
// 发布组件 相当于this.$emit('组件名称',组件的值)
PubSub.publish('add2',menuu);
}

完整代码

APP.vue

<template>
<div>
  <Menu222 :menus="menus" :webSide="webSide" />
</div>
</template>

<script>
import Menu from './components/Menu.vue'
import PubSub from 'pubsub-js'
export default {
  name: 'App',
  components:{
    Menu222:Menu // 映射Menu标签 如果属性名与属性值不同 则属性名:属性值 如果相同可以省略:属性值
  },
  data(){
    return {
      webSide:{// logo图片连接
        url:'http://www.sun.com/',
        title:'Java官方网站'
      },
      menus:[
        {id:1,name:'科技2'},
        {id:2,name:'体育2'},
        {id:3,name:'财经2'},
        {id:4,name:'医疗2'},
        {id:5,name:'政治2'},
        {id:6,name:'教育2'}
      ]
    }
  },
  methods:{
    addMenus(menu){
      this.menus.push(menu);// 在menus数组的最后位置添加元素
    }
  },
  mounted () {
    /*
    订阅消息,相当于绑定监听事件 PubSub.subscribe
    subscribe  订阅 - 父组件订阅消息
    publish    发布 - 子组件发布消息

    */
    PubSub.subscribe('add2',(msg,data)=> {
      this.addMenus(data);
    });

  }
}
</script>

<style scoped>

</style>

Menu.vue

<template>
<div>
  <a :href="webSide.url" :title="webSide.title" target="_blank">
  <img src="../assets/logo.jpg" alt="SUN JAVA" >
  </a>
  <ul>
    <!-- 这里必须要加上key 以免后期出现数据混乱 -->
    <li v-for="(menu,index) in menus" :key="menu.id">
      <a :href="'http://localhost/ment/'+menu.id">{{menu.name}}</a>
    </li>
  </ul>
  <br>
  <!-- input框输入的值双向绑定到data方法中对应的属性上 -->
  <input type="text" v-model="content" key="Math.random()"><br>
  <button @click="add">添加</button>
</div>
</template>

<script>
import PubSub from 'pubsub-js'
export default {
  name: 'Menu',
  // peops 声明接收属性,这个属性就会成为组件对象的属性 接收父组件的属性
  props:['menus','webSide'], // ,'addMenus'
  data(){ // 接收当前页面输入的值
    return {
      content:''
    }
  },
  methods:{
    add(){
      const content = this.content.trim();
      if(!content){
        alert("菜单名称不能为空");
        return;
      }
      let menuu = {id:Math.random(),name:content};
     // this.$emit('addMenus2',menuu); // 参数1 调用的是父组件中@addMenus2 参数2是需要传递值到父组件的属性
      // this.addMenus(menuu);
      // 发布组件 参数1对应订阅组件中的名称,参数2需要传递的值
      PubSub.publish('add2',menuu);

    }
  }
}
</script>

<style scoped>
ul li{
  float: left;
  padding-left: 5px;
  list-style-type: none;
}

img{
  width: 300px;
}
</style>

Test

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值