Vuex的多种写法

  1. 官方推荐:

    src/vuex/getters.js:

    const getters = {
      //这里还可以有第二个参数getters,用来获取getters里面的其他getters
      friend: (state) => {
        return state.data.friends.filter(x => x._id === state.activeId)[0];
      },
      ......
    };
    
    export default getters;
    

    src/vuex/mutations.js:

    const mutations = {
      getData: (state, data) => {
        state.data = data;
        ......
      },
    };
    
    export default mutations;
    

    src/vuex/actions.js

    import axios from 'axios';
    const actions = {
      // 这里结构里面不止有commit,也可以有dispatch等,这个也是最常用的;当然也有state、getters
      getAllData: async ({commit}) => {
        let self = {};
        let friends = [];
        await axios.get('../../static/mockdata.json').then(response => {
          self = response.data.self;
          friends = response.data.friend;
          console.log(response.data);
        }, response => {
          console.log("error");
        });
        commit('getData', {
          self, friends
        })
      },
    };
    
    export default actions;
    

    src/vuex/store.js:

    import Vue from 'vue';
    import Vuex from 'vuex';
    import mutations from "./mutations";
    import getters from "./getters";
    import actions from "./actions";
    
    Vue.use(Vuex);
    
    let state = {
        data: { 
             self: {}, 
             friends: [] 
        },
        ......
    };
    
    export default new Vuex.Store({
      state,
      mutations,
      actions,
      getters
    })
    
  2. Vuex多模块写法:

    src/store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    import { $fetch } from '../plugins/fetch'
    import router from '../router'
    
    import maps from './maps'
    import posts from './posts'
    
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
      strict: process.env.NODE_ENV !== 'production',
    
      state () {
        return {
          user: null,
        }
      },
    
      getters: {
        user: state => state.user,
    
        userPicture: (state, getters) => {
          const user = getters.user
          if (user) {
            const photos = user.profile.photos
            if (photos.length !== 0) {
              return photos[0].value
            }
          }
        },
      },
    
      mutations: {
        user: (state, user) => {
          state.user = user
        },
      },
    
      actions: {
        async init ({ dispatch }) {
          await dispatch('login')
        },
    
        async login ({ commit, dispatch }) {
          try {
            const user = await $fetch('user')
            console.log('user', user)
            commit('user', user)
    
            if (user) {
              // Redirect to the wanted route or home
              router.replace(router.currentRoute.params.wantedRoute || { name: 'home' })
    
              dispatch('logged-in')
            }
          } catch (e) {
            console.warn(e)
          }
        },
    
        logout ({ commit, dispatch }) {
          commit('user', null)
    
          $fetch('logout')
    
          // If the route is private
          // We go to the login screen
          if (router.currentRoute.matched.some(r => r.meta.private)) {
            router.replace({ name: 'login', params: {
              wantedRoute: router.currentRoute.fullPath,
            }})
          }
        },
      },
    
      // 引入其他的store
      modules: {
        posts,
      },
    })
    
    export default store
    

    src/store/posts.js

    import { $fetch } from '../plugins/fetch'
    
    let fetchPostsUid = 0
    
    export default {
      namespaced: true,
    
      state () {
        return {
          // New post being created
          draft: null,
          // Bounds of the last fetching
          // To prevent refetching
          mapBounds: null,
          // Posts fetched in those map bounds
          posts: [],
          // ID of the selected post
          selectedPostId: null,
          // Fetched details for the selected post
          selectedPostDetails: null,
        }
      },
    
      getters: {
        draft: state => state.draft,
        posts: state => state.posts,
        // The id field on posts is '_id' (MongoDB style)
        selectedPost: state => state.posts.find(p => p._id === state.selectedPostId),
        selectedPostDetails: state => state.selectedPostDetails,
        // The draft has more priority than the selected post
        currentPost: (state, getters) => state.draft || getters.selectedPost,
      },
    
      mutations: {
        addPost (state, value) {
          state.posts.push(value)
        },
    
        addComment (state, { post, comment }) {
          post.comments.push(comment)
        },
    
        draft (state, value) {
          state.draft = value
        },
    
        likePost (state, { post, userId }) {
          const index = post.likes.indexOf(userId)
          if (index !== -1) {
            post.likes.splice(index, 1)
          } else {
            post.likes.push(userId)
          }
        },
    
        posts (state, { posts, mapBounds }) {
          state.posts = posts
          state.mapBounds = mapBounds
        },
    
        selectedPostId (state, value) {
          state.selectedPostId = value
        },
    
        selectedPostDetails (state, value) {
          state.selectedPostDetails = value
        },
    
        updateDraft (state, value) {
          Object.assign(state.draft, value)
        },
      },
    
      actions: {
        clearDraft ({ commit }) {
          commit('draft', null)
        },
    
        createDraft ({ commit }) {
          // Default values
          commit('draft', {
            title: '',
            content: '',
            position: null,
            placeId: null,
          })
        },
    
        async createPost ({ commit, dispatch }, draft) {
          const data = {
            ...draft,
            // We need to get the object form
            position: draft.position.toJSON(),
          }
    
          // Request
          const result = await $fetch('posts/new', {
            method: 'POST',
            body: JSON.stringify(data),
          })
          dispatch('clearDraft')
    
          // Update the posts list
          commit('addPost', result)
          dispatch('selectPost', result._id)
        },
    
        async fetchPosts ({ commit, state }, { mapBounds, force }) {
          let oldBounds = state.mapBounds
          if (force || !oldBounds || !oldBounds.equals(mapBounds)) {
            const requestId = ++fetchPostsUid
    
            // Request
            const ne = mapBounds.getNorthEast()
            const sw = mapBounds.getSouthWest()
            const query = `posts?ne=${
              encodeURIComponent(ne.toUrlValue())
            }&sw=${
              encodeURIComponent(sw.toUrlValue())
            }`
            const posts = await $fetch(query)
    
            // We abort if we started another query
            if (requestId === fetchPostsUid) {
              commit('posts', {
                posts,
                mapBounds,
              })
            }
          }
        },
    
        async likePost ({ commit, rootGetters }, post) {
          const userId = rootGetters.user._id
          commit('likePost', {
            post,
            userId,
          })
          await $fetch(`posts/${post._id}/like`, {
            method: 'POST',
          })
        },
    
        'logged-in': {
          handler ({ dispatch, state }) {
            if (state.mapBounds) {
              dispatch('fetchPosts', {
                mapBounds: state.mapBounds,
                force: true,
              })
            }
            if (state.selectedPostId) {
              dispatch('selectPost', state.selectedPostId)
            }
          },
          root: true,
        },
    
        // 这样写的话dispatch('logout')不仅可以触发index.js中的logout,也可以触发这里的logout,也就是状       // 态提升
        logout: {
          handler ({ commit }) {
            commit('posts', {
              posts: [],
              mapBounds: null,
            })
          },
          root: true,
        },
    
        async selectPost ({ commit, getters }, id) {
          commit('selectedPostDetails', null)
          commit('selectedPostId', id)
          const details = await $fetch(`posts/${id}`)
          commit('selectedPostDetails', details)
        },
    
        async sendComment({ commit, rootGetters }, { post, comment }) {
          const user = rootGetters.user
          commit('addComment', {
            post,
            comment: {
              ...comment,
              date: new Date(),
              user_id: user._id,
              author: user,
            },
          })
    
          await $fetch(`posts/${post._id}/comment`, {
            method: 'POST',
            body: JSON.stringify(comment),
          })
        },
    
        setDraftLocation ({ dispatch, getters }, { position, placeId }) {
          if (!getters.draft) {
            dispatch('createDraft')
          }
          dispatch('updateDraft', {
            position,
            placeId,
          })
        },
    
        unselectPost ({ commit }) {
          commit('selectedPostId', null)
        },
    
        updateDraft ({ dispatch, commit, getters }, draft) {
          commit('updateDraft', draft)
        },
      },
    }
    

    在 .vue 中使用(推荐):

    <script>
    import { createNamespacedHelpers } from 'vuex'
    
    // Vuex mappers
    // posts module
    const {
      mapGetters: postsGetters,
      mapActions: postsActions,
    } = createNamespacedHelpers('posts')
    
    export default {
      computed: {
        ...postsGetters([
          'draft',
          'posts',
          'currentPost',
        ]),
    
        mapOptions () {
          return {
            fullscreenControl: false,
          }
        },
      },
    
      methods: {
        ...postsActions([
          'selectPost',
          'setDraftLocation',
        ]),
    
        onIdle () {
          this.setBounds(this.$refs.map.getBounds())
        },
    
        onMapClick (event) {
          this.setDraftLocation({
            position: event.latLng,
            placeId: event.placeId,
          })
        },
      },
    }
    </script>
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351