Limit reactivity vue / vuex

Suppose we have some array of objects and these objects never change. For example, it can be search results obtained from google maps api points - each result is a rather complex object with an identifier, name, address, coordinates, photos and a number of other properties and methods.

We want to use vue / vuex to display search results on a map. If some new results will be carried over to the store, we want to draw their markers on the map. If any result is removed, we want to remove its marker. But internally, each result never changes.

Is there a way to tell vue to keep track of the array (push, splice, etc.), but not go deep and keep track of any properties of its element?

Currently I can only imagine some ugly data - keep an array of ids in vue and have a separate cache key outside of the store. I'm looking for a more elegant solution (like knockout.js observableArray).

+3


source to share


2 answers


You can use Object.freeze()

for these objects. This is associated with (really tiny!) Success, but it should be negligible unless you add hundreds or thousands of objects at once.

edit: Alternatively, you can freeze the array (much better performance), which will cause Vue to skip over "reusing" its contents.

And when you need to add objects to this array, create a new one to replace the old one:



state.searchResults = Object.freeze(state.searchResults.concat([item]))

      

It would be pretty cheap even for large arrays.

+5


source


At second glance, data splitting does not seem to be such an ugly solution for this task. All we need is to use getters instead of the original vuex state. We assume that the incoming results are an array with any objects that have a unique field id

. Then the solution might look like this:



const state = {
    ids: []
}

let resultsCache = {};

const getters = {
    results: function(state) {
        return _.map(state.ids,id => resultsCache[id]);
    }
}

const mutations = {
    replaceResults: function(state,results) {
        const ids = [];
        const cache = {};
        (results||[]).forEach((r) => {
            if (!cache[r.id]) {
                cache[r.id] = r;
                ids.push(r.id);
            }
        });
        state.ids = ids;
        resultsCache = cache;
    },
    appendResults: function(state,results) {
        (results||[]).forEach((r) => {
            if (!resultsCache[r.id]) {
                resultsCache[r.id] = r;
                state.results.push(r.id);
            }
        });
    }
}

export default {
    getters,
    mutations,
    namespaced: true
}

      

0


source







All Articles