【问题标题】:VueX: How to architecture my store with nested objectsVueX:如何使用嵌套对象构建我的商店
【发布时间】:2017-09-17 08:36:34
【问题描述】:

我目前正在用 VueJS(尤其是 Vuex)编写一个应用程序。但是,我的问题与这个库没有密切的联系,而是与 Flux/redux/Vuex 之类的商店所具有的架构有关。

简单地说,我有几个 API(每个团队一个 API/数据库),对于每个团队/API,我有几个用户。这些团队和用户由简单的对象表示,每个都有自己的 slug。重要提示:团队的 slug 当然是独一无二的,但 slug 用户对于他们自己的团队来说是独一无二的。用户的唯一性约束将是“teamSlug/userSlug”。并且鉴于用户数量众多,我无法简单地加载所有团队的所有用户。

我的问题是如何正确构建我的应用程序/存储以恢复给定用户 slug 的数据(与他的团队):如果我尚未加载此用户,请发出 API 请求以检索它。目前,我创建了一个返回用户对象的 getter,它从用户和团队那里获取 slug。如果它返回“null”或“.loading”为“false”,我必须运行“loadOne”操作来检索它:

import * as types from '../../mutation-types'
import users from '../../../api/users'

// initial state
const state = {
  users: {}
}

// getters
const getters = {
  getOne: state => (team, slug) => (state.users[team] || {})[slug] || null
}

// actions
const actions = {
  loadOne ({ commit, state }, { team, slug }) {
    commit(types.TEAM_USER_REQUEST, { team, slug })
    users.getOne(team, slug)
      .then(data => commit(types.TEAM_USER_SUCCESS, { team, slug, data }))
      .catch(error => commit(types.TEAM_USER_FAILURE, { team, slug, error }))
  }
}

// mutations
const mutations = {
  [types.TEAM_USER_REQUEST] (state, { team, slug }) {
    state.users = {
      ...state.users,
      [team]: {
        ...(state.users[team] || {}),
        [slug]: {
          loading: true,
          error: null,
          slug
        }
      }
    }
  },

  [types.TEAM_USER_SUCCESS] (state, { team, slug, data }) {
    state.users = {
      ...state.users,
      [team]: {
        ...(state.users[team] || {}),
        [slug]: {
          ...data,
          slug,
          loading: false
        }
      }
    }
  },

  [types.TEAM_USER_FAILURE] (state, { team, slug, error }) {
    state.users = {
      ...state.users,
      [team]: {
        ...(state.users[team] || {}),
        [slug]: {
          slug,
          loading: false,
          error
        }
      }
    }
  }
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
}

您想象一个团队不仅有用户,我还有许多其他类型的模型,我应该将它们链接在一起。这种方法有效,但我觉得实施起来相当麻烦(特别是它是一个简单的get,我会有很多其他此类操作)。您对我的架构有什么建议吗?

谢谢!

【问题讨论】:

    标签: javascript redux vuejs2 flux vuex


    【解决方案1】:

    我发现保持 Vuex 存储灵活的最佳方法是对其进行规范化并尽可能保持数据项平坦。这意味着将所有用户存储在一个结构中,并找到一种唯一标识他们的方法。

    如果我们将团队和用户 slug 结合起来创建一个唯一标识符会怎样?以下是我想象的红队和蓝队的用户:

    const state = {
      users: {
        allTeamSlugs: [
          'blue1',
          'blue2',
          'blue3',
          'red1',
          'red2',
          // etc...
        ],
        byTeamSlug: {
          blue1: {
            slug: 1,
            team: 'blue',
            teamSlug: 'blue1'
          },
          // blue2, blue3, etc...
          red1: {
            slug: 1,
            team: 'red',
            teamSlug: 'red1'
          },
          // red2, etc...
        }
      }
    }
    

    并且teamSlug 属性不需要为您的 API 中的每个用户都存在。当您将数据加载到存储中时,您可以在突变中创建它。

    const mutations = {
      [types.TEAM_USER_SUCCESS] (state, { team, slug, data }) {
        const teamSlug = [team, slug].join('')
        state.users.byTeamSlug = {
          ...state.users.byTeamSlug,
          [teamSlug]: {
            ...data,
            slug: slug,
            team: team,
            teamSlug: teamSlug
          }
        }
        state.users.allTeamSlugs = [
          ...new Set([ // The Set ensures uniqueness
            ...state.users.allTeamSlugs,
            teamSlug
          ])
        ]
      },
    
      // ...
    }
    

    那么你的吸气剂可能会像这样工作:

    const getters = {
      allUsers: state => {
        return state.users.allTeamSlugs.map((teamSlug) => {
          return state.users.byTeamSlug[teamSlug];
        });
      },
      usersByTeam: (state, getters) => (inputTeam) => {
        return getters.allUsers.filter((user) => user.team === inputTeam);
      },
      getOne: state => (team, slug) => { // or maybe "userByTeamSlug"?
        const teamSlug = [team, slug].join('');
        return state.users.byTeamSlug[teamSlug]; // or undefined if none found
      }
    }
    

    Redux 有一篇关于规范化的精彩文章,我总是发现自己会回到:https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape#designing-a-normalized-state

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-19
      • 1970-01-01
      • 2019-04-13
      • 2020-02-21
      • 1970-01-01
      • 2013-03-15
      相关资源
      最近更新 更多