zoukankan      html  css  js  c++  java
  • [Vue] vuex进行组件间通讯

    vue 组件之间数据传输(vuex)

    初始化 store

    src/main.js

    import Vuex from "vuex";
    Vue.use(Vuex);
    
    new Vue({
      ...,
      store,
      ...,
    });
    

    src/store/index.js

    import mutations from "./mutations";
    
    const initStore = {
      state: {
        userBasicInfo: {},
        siteBaseInfo: {
          download: "",
          invitation: "",
          register_enable: "",
          service_qq1: "",
          service_qq2: "",
          service_wechat: "",
        },
      },
      mutations
    };
    
    export default initStore;
    
    

    src/store/mutations.js

    const SET_USER_BASIC_INFO = 'SET_USER_BASIC_INFO';
    const SET_SITE_BASE_INFO = 'SET_SITE_BASE_INFO';
    
    export default {
      [SET_USER_BASIC_INFO](state, payload) {
        state.userBasicInfo = payload.data;
      },
      [SET_SITE_BASE_INFO](state, payload) {
        state.siteBaseInfo = Object.assign({}, state.siteBaseInfo, payload);
      },
    }
    

    state

    正常使用 state

    Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态。每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
    Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中。

    const app = new Vue({
      el: '#app',
      // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
      store,
      components: { Counter },
      template: `
        <div class="app">
          <counter></counter>
        </div>
      `
    })
    

    在子组件中使用

    const Counter = {
      template: `<div>{{ count }}</div>`,
      computed: {
        count () {
          return this.$store.state.count
        }
      }
    }
    

    mapState 辅助函数

    按官网的案例

    import { mapState } from 'vuex'
    
    export default {
      // ...
      computed: mapState({
        // 箭头函数
        siteBaseInfo: state => state.siteBaseInfo,
        // 传字符串参数
        siteBaseInfo: "siteBaseInfo",
        // 为了能够使用 `this` 获取局部状态,必须使用常规函数
        download_ios (state) {
          return state.siteBaseInfo.download + this.prefix
        },
        download: state => state.siteBaseInfo.download
      })
    }
    

    当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组

    computed: mapState([
      // 映射 this.count 为 store.state.count
      'count'
    ])
    

    mapState 与局部计算属性混合使用

    使用对象展开运算符将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。

    computed: {
      localComputed () { /* ... */ },
      // 使用对象展开运算符将此对象混入到外部对象中
      ...mapState({
        // ...
      })
    }
    

    getter 的使用

    有时候我们需要从通过 state 得到一些新的状态,因为这一状态可能其他很多组件都要使用这一状态.比如余额这一参数,我们当前只有盈利和亏损额,但是很多页面都要使用余额进行显示,那么每个引入页面都要进行一次计算吗?想想就麻烦,还是只计算一次,然后直接获取这个余额值来的方便

    store/getters.js

    export default {
      balance: (state) => {
        return Number(state.userBasicInfo.profit) - Number(state.userBasicInfo.loss);
      },
      download: (state) => {
        return state.siteBaseInfo.download;
      }
    }
    

    mapGetters 辅助函数

    辅助函数仅仅是将 store 中的 getter 映射到局部计算属性

    import { mapGetters } from 'vuex'
    
    export default {
      // ...
      computed: {
      // 使用对象展开运算符将 getter 混入 computed 对象中
        ...mapGetters([
          'balance',
          'download',
          // ...
        ])
      }
    }
    

    getter 的使用

    //直接使用
    store.getters.download
    //组件中使用
    computed: {
     download () {
        return this.$store.getters.download
      }
    }
    //使用辅助函数
    ...mapGetters([
          'download',
          'balance',
    ])
    //和mapState一起用
    computed: {
      ...mapState({
        siteBaseInfo: "siteBaseInfo",
      }),
      ...mapGetters({
        download: 'download'
      })
    },
    

    Getter 也可以接受其他 getter 作为第二个参数

    getters: {
      // ...
      doneTodosCount: (state, getters) => {
        return getters.doneTodos.length
      }
    }
    

    总之,getter 就是一个将一些需要进行再次计算的 state 计算好,然后将其作为 state 进行快捷的引用

    mutation 使用

    • 最好提前在你的 store 中初始化好所有所需属性
    • 当需要在对象上添加新属性时,你应该使用 Vue.set(obj, 'newProp', 123)或以新对象替换老对象(对象展开符)
    • mutation 必须是同步函数

    每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler),会接受 state 作为第一个参数

    //设置
    mutations: {
       SET_USER_BASIC_INFO(state) {
        state.userBasicInfo = {a:1,b:2};
      },
    }
    
    //使用
    store.commit('SET_USER_BASIC_INFO')
    

    提交载荷(Payload)

    //设置
    mutations: {
       SET_USER_BASIC_INFO(state, payload) {
        state.userBasicInfo = Object.assign({},payload);
      },
    }
    
    //使用
    store.commit('SET_USER_BASIC_INFO', {
      a:1,
      b:2
    })
    

    对象风格的提交方式

    提交 mutation 的另一种方式是直接使用包含 type 属性的对象

    store.commit({
      type: 'SET_USER_BASIC_INFO',
      data:{
          a:1,
          b:2,
      }
    })
    
    //mutations的效果
    mutations: {
      increment (state, payload) {
        state.userBasicInfo = Object.assign({},payload.data);
      }
    }
    

    使用常量替代 Mutation 事件类型

    // mutation-types.js
    export const SET_USER_BASIC_INFO = 'SET_USER_BASIC_INFO';
    
    // mutations.js
    import { SET_USER_BASIC_INFO } from './mutation-types';
    
    mutations: {
        // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
        [SET_USER_BASIC_INFO] (state) {
          // mutate state
        }
      }
    

    mapMutations 辅助函数

    //正常
    this.$store.commit('SET_USER_BASIC_INFO');
    
    //mapMutations
    import { mapMutations } from 'vuex';
    
    export default {
        ...,
        methods:{
            ...mapMutations({
                setUserBasicInfo: 'SET_USER_BASIC_INFO' // 将 `this.setUserBasicInfo()` 映射为 `this.$store.commit('SET_USER_BASIC_INFO')`
            })
        }
    }
    

    action

    用来提交一个 mutation,还可以进行异步操作

    //注册
    const store = new Vuex.Store({
      state,
      mutations,
      actions: {
        //解构context.commmit
        GET_HOME_INFO({commit}) {
            commit("SET_USER_BASIC_INFO");
        },
      }
    })
    
    //触发
    store.dispatch('GET_HOME_INFO')
    //载荷形式
    store.dispatch('GET_HOME_INFO',{})
    //对象形式
    store.dispatch({
        type:'GET_HOME_INFO',
        data:{}
    })
    

    mapActions 辅助函数

    import { mapActions } from 'vuex'
    
    export default {
      ...
      methods: {
        ...mapActions({
          getHomeInfo: 'GET_HOME_INFO' // 将 `this.getHomeInfo()` 映射为 `this.$store.dispatch('GET_HOME_INFO')`
        })
      }
    }
    

    异步的 action

    action 中的中支持的异步 ajax,setTimeout,acync/await,promise...

    store.dispatch('actionA').then(() => {
      // ...
    })
    

    其他的传值还有一些方式

    比如 props,seventBus,slocalStorage,sessionStorage,router 传参,cookie(不推荐,虽然就跟之前做购物车差不多的传递形式)

    vue 组件之间数据传输(props 传值方式)

    这个多用于父子组件之间的传值,是最基本的传值方式

    父亲组件进行绑定,将数据绑定,其中 personal,personalData,imgUrl 是绑定的数据,@updata 是绑定的事件

    <template>
          ...
          <slideBar
            @updata="updata"
            :personal="personal"
            :personalData="personalData"
            :imgUrl="imgUrl"
          ></slideBar>
          ...
    <template>
    

    子组件进行获取数据通过 props 进行获取,可以设置一些静态类型检查,类似于 react 的 proptypes,同时子组件想要向父组件进行传值,可以通过 emit 进行传值就行了

      export default {
        props: {
          slideMsg: Array,
          personal: Object,
          personalData: Object,
          imgUrl: String
        },
        ...
        methods:{
          submitEvent(){
            ...
            this.emit("updata","我是获取的数据");
            ...
          }
        }
      }
    

    vue 组件之间数据传输(eventBus 进行组件传递)

    事件 bus 通过一个新的 vue 实例,来进行事件监听和事件分发
    commom/bus.js

    //极简单的vue实例
    import Vue from 'vue';
    // 使用 Event Bus
    const bus = new Vue();
    export default bus;
    

    在 game 组件中引入

    import bus from "@/common/bus";
    
    ...
    bus.$emit("moneyChange", {....});
    ...
    

    在用 money 组件中引入

    import bus from "@/common/bus";
    
    ...
    bus.$on("moneyChange", msg => {
        msg && this.initHomeData();
    });
    ...
    

    在最初的项目阶段这是一个不错的选择,但是随着项目体积的增大,事件触发和数据流向变得越来越不可见,后续开发和维护变得越来越困难.

    sessionstorage

    项目中使用的 sessionStorage

    sessionStorage.setItem("msg", JSON.stringify(res.data)); //为了兼容之前的代码,有用到msg这个本地缓存的数据
    sessionStorage.setItem("isMobile", res.data.mobile);
    sessionStorage.setItem("invi", res.data.invitation);
    sessionStorage.setItem("isLogin", res.data.trier);
    sessionStorage.setItem("setPwd", res.data.fundpwd);
    sessionStorage.setItem("isShow", res.data.bankcard);
    

    localStorage

    项目中关于声音的开关,样式选择,背景切换等,用来将用户的一些操作一直保存

    //组件userSetting
    localStorage.setItem("audio", this.switchValue);
    //组件audioPlay
    let audio = localStorage.getItem("audio");
    

    sessionstorage 和 localStorage 看情况使用就好,sessionstorage 是浏览器关闭没了,localStorage 是一直存储不删除就在存在

    params

    依赖于 vue-router

    this.$router.push({
      name: "Main",
      params: {
        id: this.setting_id,
        type: "3"
      }
    });
    

    Vuex
    Vuex - 标签 - 掘金
    浪里行舟 从头开始学习 Vuex
    VueJS 中学习使用 Vuex 详解
    到底 vuex 是什么?
    基于 vue2 + vuex 构建一个具有 45 个页面的大型单页面应用

  • 相关阅读:
    6.7
    6.5
    6.4随笔
    js 插件
    js插件
    web中集成jdbc
    jsp
    web容器中的servlet
    web服务器的监听器,过滤器
    几款js工具的使用
  • 原文地址:https://www.cnblogs.com/mybilibili/p/10456346.html
Copyright © 2011-2022 走看看