本文共 7324 字,大约阅读时间需要 24 分钟。
在开发过程中,父子组件传递数据,我们用props和$emit可以解决问题,那么非父子组件之间的数据传递我们要怎么解决呢,一般有两个方案,一个event bus(事件总线)和 vuex。我们先来说event bus。
一、用vue脚手架构建一个简单的项目
# 全局安装 vue-clinpm install --global vue-cli# 创建一个基于 webpack 模板的新项目vue init webpack vuexdemo# 安装依赖,走你cd vuexdemonpm installnpm run dev
二、使用event bus实现跨组件通信
event bus事件总线,组件之间的通信需要使用一个中介来实现,在event bus里面使用一个空的Vue实例来做为通信的桥梁,下面是使用event bus来实现改变登录状态的demo。
// 把busVue.prototype.bus = new Vue();
data() { return { loginStatus: false }; }, created() { // 监听事件 this.bus.$on("login", (data) => { this.loginStatus = data; }); }
修改后的Index.vue代码如下:
登录状态:{ { loginStatus?'已登录':'未登录' }}
去登录
还没有账号,
立即注册
import Vue from 'vue'import Router from 'vue-router'import Index from '@/components/Index'import Login from '@/components/Login'Vue.use(Router)export default new Router({ routes: [ { path: '/', name: 'index', component: Index }, { path: '/login', name: 'login', component: Login } ]})
三、使用vuex实现跨组件通信
跨组件通信,使用event bus的做法,对于简单的应用来讲,但是对于复杂的应用来讲,event bus对于事件的管理就可能力不从心了,你不一定记得你有多少个组件监听了该事件,你可能会担心,那个组件到底挂载了没有。所以在复杂的应用中我们推荐使用vuex。
什么是vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。vuex包含以下几个元素state(存放数据),action(动作,我把它理解为指令,用户派发action,可以看做是用户发出指令),mutation(改变,用来改变state里面的数据)一个完整的过程是视图(用户)派发 action,action提交修改,mutation负责修改state里的数据,state里的数据被修改了,对应的视图就被刷新,见下图。
一个vuex demo
npm i vuex --save
组件名称:{ {title}}
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({ // 存储数据 state: { title: '根组件' }, // 读取数据 getters: { title: state => state.title }, // 动作 actions: { // 修改标题的action 'UPDATE_TITLE_ACTION'({ commit }, payload) { commit('UPDATE_TITLE', payload); } }, // 变化;转变 mutations: { // 修改state里的title 'UPDATE_TITLE'(state, payload) { state.title = payload; } }})
当涉及的数据比较多的时候,getters、actions、mutations可以用单独的文件导出。
import store from './store'new Vue({ el: '#app', // 新增代码 store, router, template: '', components: { App }})
beforeRouteEnter: (to, from, next) => { next(vm => { vm.$store.dispatch('UPDATE_TITLE_ACTION','登录组件') }) },
同理,我们可以新建一个Register组件,做相关操作,当我们访问/register时改变组件的名称,Register组件代码如下,同时需要在router里面配置添加/register:
已有账号?
立即登录
router/index.js里面的代码如下:
import Vue from 'vue'import Router from 'vue-router'import Index from '@/components/Index'import Login from '@/components/Login'import Register from '@/components/Register'Vue.use(Router)export default new Router({ routes: [ { path: '/', name: 'index', component: Index }, { path: '/login', name: 'login', component: Login }, { path: '/register', name: 'register', component: Register } ]})
7.modules,当我们需要管理很多的状态时,会使用modules来进行分割,具体做法如下:
在store的文件夹新建modules文件夹,里面封装某个具体组件的state、getters、actions和mutations,一下新建一个Foot组件,设置关于该组件的状态信息,其他组件可以修改它的状态,从而改变Foot组件显示的内容(统计浏览过的路由的次数)。浏览过的路由个数 10
export default { state: { routeNum: '1' }, getters: { routeNum: state => state.routeNum }, actions: { 'UPDATE_ROUTENUM_ACTION'({ commit }, payload) { commit('UPDATE_ROUTENUM',payload); } }, mutations: { 'UPDATE_ROUTENUM'(state, payload) { state.routeNum = state.routeNum + payload; } }}
import Vue from 'vue'import Vuex from 'vuex'import foot from './modules/footer'Vue.use(Vuex)// import getters from './getters'// import mutations from './mutations'// import actions from './actions';export default new Vuex.Store({ // 存储数据 state: { title: '根组件' }, // 读取数据 getters: { title: state => state.title }, actions: { // 修改标题 'UPDATE_TITLE_ACTION'({ commit }, payload) { commit('UPDATE_TITLE', payload); } }, mutations: { 'UPDATE_TITLE'(state, payload) { state.title = payload; } }, modules: { foot, }})
beforeRouteEnter: (to, from, next) => { next(vm => { vm.$store.dispatch("UPDATE_TITLE_ACTION", "登录组件"); vm.$store.dispatch("UPDATE_ROUTENUM_ACTION",1); }); },
当然这个是比较笨的方法,更好的办法是,在main.js里面加上以下这段代码,那么当每一次变换路由的时候我们给底部加圆圈的小数字加1了。
router.beforeEach((to, from, next) => { store.dispatch('UPDATE_ROUTENUM_ACTION',1); next();})
在开始的event bus的例子里我们通过event bus改变组件的登录状态,在这里我们也可以使用vuex轻松实现,我们用state用loginState来保存登录的状态,当我们登录成功的时候,就修改loginState的值,具体实现过程如下。
import { mapActions } from "vuex";export default { state: { loginState: false }, getters: { loginState: state => state.loginState }, actions: { 'UPDATE_LOGINSTATE_ACTION'({ commit }, payload) { // UPDATE_LOGINSTATE为对应的mutation commit('UPDATE_LOGINSTATE', payload); } }, mutations: { 'UPDATE_LOGINSTATE'(state, payload) { state.loginState = payload; } }}
import Vue from 'vue'import Vuex from 'vuex'import foot from './modules/footer'import login from './modules/login'Vue.use(Vuex)export default new Vuex.Store({ // 存储数据 state: { title: '根组件' }, // 读取数据 getters: { title: state => state.title }, actions: { // 修改标题 'UPDATE_TITLE_ACTION'({ commit }, payload) { commit('UPDATE_TITLE', payload); } }, mutations: { 'UPDATE_TITLE'(state, payload) { state.title = payload; } }, modules: { foot, login }})
还没有账号,
立即注册
登录状态:{ { loginState?'已登录':'未登录' }}
去登录
探讨问题:
转载地址:http://xjukx.baihongyu.com/