如何在 Vuex 中正确混合和隔离对象

How to correctly mix and isolate objects in Vuex

我正在尝试使用模块为 Vuex 创建一种 mixin,但动作在模块中混合:

这是子事件模块:

import Form from '../../classes/Form'

import * as mutationsMixin from './mixins/mutations.js'
import * as actionsMixin from './mixins/actions.js'
import * as statesMixin from './mixins/states.js'

const state = merge_objects(statesMixin.common, {
    data: {},

    event: null,

    form: new Form({
        name: null,
    }),
})

const actions = merge_objects(actionsMixin, {
    select() {
        dd('subevent select')
    },
})

const mutations = merge_objects(mutationsMixin, {
    mutateSetEvent(state, payload) {
        state.event = payload
    },
})

dd('subEvents')

export default {
    state,
    actions,
    mutations,
}

这是商店

/**
 * Imports
 */
import Vue from 'vue'
import Vuex from 'vuex'

/**
 * Vuex
 */
Vue.use(Vuex)

/**
 * Global state
 */
import * as actions from './actions'
import * as getters from './getters'
import * as mutations from './mutations'

/**
 * Modules
 */
import gate from './modules/gate'
import events from './modules/events'
import subEvents from './modules/subEvents'
import categories from './modules/categories'
import people from './modules/people'
import roles from './modules/roles'
import institutions from './modules/institutions'
import environment from './modules/environment'

/**
 * State
 */
const state = {
    mounted: false,
}

/**
 * Store
 */
let store = new Vuex.Store({
    state,
    actions,
    getters,
    mutations,
    modules: {
        events,
        people,
        categories,
        environment,
        subEvents,
        gate,
        roles,
        institutions,
    },
})

store.dispatch('environment/absorbLaravel')

export default store

这是 merge_object 助手:

window.merge_objects = (target, ...sources) => {
    return Object.assign(target, ...sources)
}

因此,如果您查看商店导入,您会看到子事件是在事件之后加载的,并且上面的子事件商店中的操作 select()(最初来自 mixin)正在加载超载,但是当我调用未超载的 events/select() 时,我在控制台中收到 'subevent select' 消息(dd() 是一个帮助程序)

这张图片稍微解释一下

问题是 Object.assign 没有创建副本,而是修改了作为第一个参数传递给它的对象。该函数将 return 第一个对象。

const a = {};
Object.assign(a, { a: 1 });
console.log(a); // { a: 1 }

在你的情况下,我认为你不需要对象的深度克隆。您只是不想直接修改 mixin。如果您使用新创建的对象作为第一个参数调用 Object.assign,您将对下一个参数中的所有对象进行浅表复制。

Object.assign({}, target, ...sources)

const a = {};
Object.assign({}, a, { a: 1 });
console.log(a); // {}

如果您需要深度克隆(例如,因为您的对象中有您不想在实例之间共享的嵌套对象,我建议您使用 lodash.merge.