vue非父子组件通信问题及解决方法


Posted in Javascript onJune 11, 2018

问题描述:

最近在做登录部分时遇到一个场景,当点击 “用户”按钮时,首先渲染login组件,在用户登录后直接跳转到用户信息界面(user组件)。这里遇到了需要将login组件通过异步请求获得的用户信息传向 user组件,但是login和login组件不是父子组件,就暂称为兄弟组件吧。 简而言之,我要解决的就是兄弟组件之间的信息传递问题。

//位于login.vue 中 
export default { 
 methods:{ 
 login(){ 
  this.$axios({ 
  method: 'post', 
  url: '/student/login/', 
  data: { 
  username: this.username, 
  password: this.password 
  } 
  }) 
  .then(function (response) { 
  this.$router.replace({path: 'user'}); 
  }.bind(this)) 
  .catch(function (error) { 
  console.log(error); 
  alert('用户名或密码错误'); 
  }); 
 } 
 } 
}

在异步请求完成后,就跳转到user组件中,但是response的请求返回信息就无法传到非父子组件的user组件中。

.............................................................................................................................................................................................................

解决问题:

一、首先我想到了将login组件 和 user组件放到一起(两个组件合2为1),加避免了组件间的信息传递,但是这种解决方案太low,破坏了项目原有的结构。

二、查文档得知了

非父子关系的两个组件之间也需要通信。在简单的场景下,可以使用一个空的 Vue 实例作为事件总线: 

var bus = new Vue() 
// 触发组件 A 中的事件 
bus.$emit('id-selected', 1) 
// 在组件 B 创建的钩子中监听事件 
bus.$on('id-selected', function (id) { 
 // ... 
})

以自己遇到的问题为例,写出具体的实现:(warning:  我自己遇到的情况不能用这种简单的方式解决)

最好先新建一个js文件,来创建出我们的eventBus,我们把它命名为bus.js

import Vue from 'vue'; 
export default new Vue();

然后在 login.vue 文件中:

//位于login.vue 中 
import Bus from '../bus.js'; 
export default { 
 methods:{ 
 login(){ 
  this.$axios({ 
  method: 'post', 
  url: '/student/login/', 
  data: { 
  username: this.username, 
  password: this.password 
  } 
  }) 
  .then(function (response) { 
  /* 
  * 这里的 'login-on'是在Bus中自己构造的一个事件(不需要在别处申明),通过emit()函数 
  * 手动触发这个事件,然后在user.vue 中可以监听这个事件,一旦发现事件触发,就可以利用 
  * 回调函数接收 response 这个对象,达到信息传递的目的 
  * */ 
  Bus.$emit('login-on',response); 
  this.$router.replace({path: 'user'}); 
  }.bind(this)) 
  .catch(function (error) { 
  console.log(error); 
  alert('用户名或密码错误'); 
  }); 
 } 
 } 
}

在user.vue文件中:

//位于user.vue 中 
import Bus from '../bus.js'; 
export default { 
 mouted : { 
  Bus.$on('login-on', message => { // 这里的message就是从login.vue中传来的数据 
  console.log(message); 
 }); 
 } 
}

这样就完成了数据传递。

但是在测试时发现在user.vue组件的监听 没有被触发

分析:在我遇到的情境中,login.vue组件和user.vue 组件是互相替代的关系,即需要从login组件通过vue-router跳转到user组件,在login.vue销毁后才开始渲染user.vue组件,所以在user.vue中的

Bus.$on('login-on', message =>

监听是在事件以及触发之后才开始,自然不会产生回调函数。

由此可以看出,官方推荐的eventbus 解决方案的缺陷在于, 在数据传递过程中,两个组件必须都已经被渲染过。我的这种情景下,这种方法不适用。

 三、vuex解决方案:

 熟悉vuex的大佬们请直接跳过吧。

最好在src的根目录下新建一个文件,叫 store.js

//位于store.js 中 
import Vue from 'vue' 
import Vuex from 'vuex' 
Vue.use(Vuex); 
export default new Vuex.Store({ 
 /* 
 * state指的就是储存的数据, 
 * 下面的数据是我在项目中需要用的数据字段 
 * */ 
 state: { 
 has_login: false, 
 id: 1, 
 mobile_num: '', 
 name: '' 
 }, 
 /* 
 * mutations里面规定的就是想要改变state(数据)的动作函数, 
 * 下面的user_message 就是我将传入的message赋值给仓库中的 
 * state数据字段,达到更新数据的目的 
 * */ 
 mutations: { 
 user_message (state, message) { 
 state.has_login = true; 
 state.id = message.data.id; 
 state.mobile_num = message.data.mobile_num; 
 state.name = message.data.name; 
 } 
 } 
})

然后在login.vue组件中,提交收到的用户信息

//位于login.vue 中 
import userMessage from '../store'; 
export default new Vuex.Store({ 
 methods: { 
 loginSubmit () { 
 this.$axios({ 
  method: 'post', 
  url: '/student/login/', 
  data: { 
  username: this.username, 
  password: this.password 
  } 
 }) 
  .then(function (response) { 
  //这里调用 store.js中 mutations里面的user_message函数,从而改变仓库中的state数据 
  userMessage.commit('user_message', response); 
  this.$router.replace({path: 'user'}); 
  }.bind(this)) 
  .catch(function (error) { 
  console.log(error); 
  alert('用户名或密码错误'); 
  }); 
 } 
})

最后在user.vue组件中接收vuex仓库中存储的信息,即先引入仓库

//位于user.vue 中 
import userMessage from '../store';

然后可以直接将 userMessage.state 赋值给user.vue作用域中的数据字段,同时,vuex 的state有热更新的属性,对于数据的同步很有帮助,优点良多。

所以,中大型的项目还是在一开始就直接使用vuex是明智的决定,对于开发有很大的便利。

总结

以上所述是小编给大家介绍的vue非父子组件通信问题解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript 事件查询综合 推荐收藏
Mar 10 Javascript
jquery 简单的进度条实现代码
Mar 11 Javascript
js模仿hover的具体实现代码
Dec 30 Javascript
js获取当前时间显示在页面上并每秒刷新
Dec 24 Javascript
Node.js编写爬虫的基本思路及抓取百度图片的实例分享
Mar 12 Javascript
JS实现iframe自适应高度的方法(兼容IE与FireFox)
Jun 24 Javascript
JavaScript 中使用 Generator的方法
Dec 29 Javascript
js实现input密码框显示/隐藏功能
Sep 10 Javascript
关于element-ui的隐藏组件el-scrollbar的使用
May 29 Javascript
Vue向后台传数组数据,springboot接收vue传的数组数据实例
Nov 12 Javascript
基于Vant UI框架实现时间段选择器
Dec 24 Javascript
js仿淘宝放大镜效果
Dec 28 Javascript
Angular如何在应用初始化时运行代码详解
Jun 11 #Javascript
详解.vue文件解析的实现
Jun 11 #Javascript
vue filters的使用详解
Jun 11 #Javascript
Vue组件全局注册实现警告框的实例详解
Jun 11 #Javascript
jQuery实现的页面详情展开收起功能示例
Jun 11 #jQuery
Node.js中的cluster模块深入解读
Jun 11 #Javascript
详解vue-router 初始化时做了什么
Jun 11 #Javascript
You might like
一个简单的php加密解密函数(动态加密)
2013/06/19 PHP
PHP中error_log()函数的使用方法
2015/01/20 PHP
PHP简单操作MongoDB的方法(安装及增删改查)
2016/05/26 PHP
php判断str字符串是否是xml格式数据的方法示例
2017/07/26 PHP
Docker搭建自己的PHP开发环境
2018/02/24 PHP
PHP实现微信公众号验证Token的示例代码
2019/12/16 PHP
php多进程并发编程防止出现僵尸进程的方法分析
2020/02/28 PHP
PHP实现Snowflake生成分布式唯一ID的方法示例
2020/08/30 PHP
javascript 网页跳转的方法
2008/12/24 Javascript
extjs fckeditor集成代码
2009/05/10 Javascript
关于onScroll事件在IE6下每次滚动触发三次bug说明
2011/09/21 Javascript
jquery form 隐藏的input 选择
2014/04/29 Javascript
js通过location.search来获取页面传来的参数
2014/09/11 Javascript
JavaScript基础篇(6)之函数表达式闭包
2015/12/11 Javascript
JavaScipt中栈的实现方法
2016/02/17 Javascript
javascript 闭包详解及简单实例应用
2016/12/31 Javascript
超全面的javascript中变量命名规则
2017/02/09 Javascript
vue.js如何更改默认端口号8080为指定端口的方法
2017/07/14 Javascript
vue实现随机验证码功能的实例代码
2019/04/30 Javascript
Vue事件处理原理及过程详解
2020/03/11 Javascript
[01:01:13]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第三场
2018/04/06 DOTA
[50:24]VGJ.S vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
Python中使用item()方法遍历字典的例子
2014/08/26 Python
Python做文本按行去重的实现方法
2016/10/19 Python
浅谈python中get pass用法
2019/03/19 Python
python实现月食效果实例代码
2019/06/18 Python
css3学习之2D转换功能详解
2016/12/23 HTML / CSS
美国休闲服装品牌:J.Crew Factory
2017/03/04 全球购物
早晨薰衣草在线女性精品店:Morning Lavender
2021/01/04 全球购物
爱护公共设施倡议书
2014/08/29 职场文书
入党积极分子学习优秀共产党员先进事迹思想汇报
2014/09/13 职场文书
2014年社区矫正工作总结
2014/11/18 职场文书
先进班集体事迹材料
2014/12/25 职场文书
感恩节寄语2015
2015/03/24 职场文书
2015入党个人自传范文
2015/06/26 职场文书
MySQL中rank() over、dense_rank() over、row_number() over用法介绍
2022/03/23 MySQL