【问题标题】:Maintain associated objects in Vue在Vue中维护关联对象
【发布时间】:2020-04-08 11:02:48
【问题描述】:

我是 vue 新手,但我也仔细阅读了 vue 和 vuex 的文档。但我坚持以下问题。我也确实认为我不会以某种方式完成它,但我想采用一种干净且可能是最实用的方法。

设置: - 我有一些实体 - 我有一些用户 - 假设一个实体可以属于多个用户

现在我想要完成的是显示所有已检查并分配给实体的用户的列表。

我有以下 vuex 商店:

export default new Vuex.Store({
    state: {
        users: [],
        entities: []
    },
    getters: {
        USERS: state => state.users,
        ENTITIES: state => state.entities,
        ENTITY: state => id => {
            return state.entities.find(entity => entity.id == id)
        }
    },
    mutations: {
        SET_USERS: (state, payload) => {
            state.users = payload
        },
        SET_ENTITIES: (state, payload) => {
            state.entities = payload
        },
        UPDATE_DEVICE: (state, payload) => {
            state.entities = state.entities.map(entity => {
                if(entity.id === payload.id){
                    return Object.assign({}, entity, payload.data)
                }
                return entity
            })
        }
    },
    actions: {
        GET_USERS: async (context) => {
            let { data } = await Axios.get('/api/v1/users')
            context.commit('SET_USERS', data)
        },
        GET_ENTITIES: async (context) => {
            let { data } = await Axios.get('/api/v1/entities')
            context.commit('SET_ENTITIES', data)
        },
        UPDATE_ENTITY: ({commit}, payload) => {
            Axios.put('/api/v1/entities/' + payload.id + '/', payload.data).then((response) => {
                commit('UPDATE_ENTITY', payload)
            });
        }
    }
})

我的实体组件在创建的钩子中从商店加载用户。实体的数据是从计算属性entity() 的存储中获取的。此外,所有用户的列表由计算属性 users() 提供服务。

created(){
   if(!this.$store.getters.USERS.length) this.$store.dispatch('GET_USERS')
},
computed: {
   entity(){
      const entityId = this.$route.params.id
      return this.$store.getters.ENTITY(entityId)
   },
   users(){
      return this.$store.getters.USERS
   }
}

然后在模板中显示所有用户和一个复选框:

<ul>
   <li v-for="(user, i) in users" :key="i">
      <input type="checkbox" :value="user" :id="'user_'+i" :name="'user_'+i" v-model="???" />
      <label :for="'user_'+i">{{user.name}}</label>
   </li>
</ul>

我还有属于同一组件模板中实体的所有用户的第二个列表,如下所示,我想与“可选列表”保持同步。因此,所有选中复选框的用户都应列在该列表中:

<ul>
   <li v-for="user in entity.users" :key="user.id">
      {{user.name}}
    </li>
</ul>

这就是我陷入困境的地方: 我应该使用 get() 和 set() 的 device.users 计算属性并将其用作复选框上的 v-model 吗?我试过了,但它没有奏效,因为所有用户列表的用户对象和 device.users 列表的对象不是相同的对象,即使它们代表同一个用户。在那一点上,我认为我正在以复杂的方式完成整个事情,而我只是忽略了熟练的 vue 用户会这样做的常见方式。

长话短说:解决此任务的最佳方法是什么? 我认为这是一项最常见的任务。

感谢您的每一个回答,如果需要更多代码/详细信息,我会提供给他们!

【问题讨论】:

    标签: javascript vue.js associations vuex


    【解决方案1】:

    实体的结构是怎样的?假设他们有一个数组“用户”,您可以通过提供一个基本的 javascript 函数来计算复选框的值,该函数检查该用户的唯一 ID 是否在该实体的列表中。

    在计算中创建一个新属性(因此您不会为 v-for 中的每个元素重新计算相同的数组):

    userIdsWithEntity() {
      if (!this.entity) return [];  // necessary in case entity hasn't been instantiated yet
      return this.entity.users.map(x => x.id)
    }
    

    然后为复选框值提供一个简单的函数,返回真或假::value="userIdsWithEntity.includes(user.id)"

    而不是 v-model(这是 :value 和 @input/@change 来更新 :value 提供的属性整合到一个指令中,因此您可能会与您的 :value 定义发生冲突),使用 @change 来处理(取消)选中复选框,向 vuex 发送操作以将该用户删除/添加到实体。

    【讨论】:

    • 谢谢,这基本上是一个很好的起点!我现在如何在同一组件上维护第二个列表,包含所有选定的用户?我将分别编辑我的问题。
    • 我进一步认为您的意思是 :checked 而不是 :value 在 ceckbox 上,对吧?
    • 是的,它应该是 :checked。 HTML 输入很奇怪 ;p 不同的问题,但可能最好使用v-for="id in userIdsWithEntity" 生成该列表,并为用户提供一个 getter,就像你对实体一样。 user: state =&gt; id =&gt; state.users.find(user =&gt; user.id === id).
    • 然后如何访问用户名?以及如何实现两个列表同步?
    • 更新实体时应自动进行同步。这两个列表都依赖于 userIdsWithEntity,因此如果您的添加/删除用户函数正确更新了您的实体,则此属性应该同时更新这两个列表。访问 user.name 的方式与访问 entity.id 的方式相同。
    猜你喜欢
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 2011-08-13
    相关资源
    最近更新 更多