vuex-asr
Version:
* Version: 0.7.52 * License M.I.T. * [Online Documentation](https://vuex-asr.github.io/vuex-asr/) * author: Joris Wenting * email: vuex.asr@gmail.com * [linkedIn](https://www.linkedin.com/in/joriswenting/). * [contribute](https://vuex-asr.github.io/vuex-a
389 lines (342 loc) • 9.87 kB
JavaScript
import { mapGetters, mapState } from "vuex";
export default class PopulateComputed {
constructor(Router) {
// Initialize dependencies
this.vueInstance = Router.vueInstance;
this.Report = Router.Report;
this.RemoveOldBindings = Router.RemoveOldBindings;
this.Resolve = Router.Resolve;
this.routingProps = Router.routingProps;
}
createMappings(bindersArray, passesArray) {
// Here we terminate the inserted items with a start and end registration.
// The next (!!) instance that is rendered needs to delete the bindings
// that are going to be set below.
// See './asr-remove-old-bindings.js' (method: unSetAsrComputed)
this.unsetDataItemsInVueInstanceThatAreOverwrittenByBindings(bindersArray);
this.setEmptyComputedMethod("asrRegisterStart", "Here the register starts");
this.createMappingsFromBindersArray(bindersArray);
this.createMappingsFromPassesArray(passesArray);
this.setEmptyComputedMethod("asrRegisterEnd", "Here the register ends");
}
// Helper method for register termination
setEmptyComputedMethod(registerName, registerMessage) {
const mapStateObject = {
...mapState({
[registerName]: () => registerMessage
})
};
this.vueInstance.$options.computed[registerName] =
mapStateObject[registerName];
}
// Unset local variables in data() object to overwrite them with store bindings
//
unsetDataItemsInVueInstanceThatAreOverwrittenByBindings(bindersArray) {
const clone = { ...this.vueInstance };
const dataFunction = clone.$options.data;
function isFunction(functionToCheck) {
return (
functionToCheck &&
{}.toString.call(functionToCheck) === "[object Function]"
);
}
if (isFunction(dataFunction)) {
this.unsetLocalVariables(bindersArray);
}
}
unsetLocalVariables(bindersArray) {
const clone = { ...this.vueInstance };
const dataFunction = clone.$options.data;
const dataFunctionDataBefore = dataFunction();
let dataFunctionDataAfter = { ...dataFunctionDataBefore };
bindersArray.forEach(item => {
const bindName =
item.alias !== null && item.alias.length > 0 ? item.alias : item.bind;
if (dataFunctionDataBefore.hasOwnProperty(bindName)) {
delete dataFunctionDataAfter[bindName];
}
});
const newDataFunctionForVueInstance = function() {
return dataFunctionDataAfter;
};
this.vueInstance.$options.data = newDataFunctionForVueInstance;
const messageObject = {
before: dataFunctionDataBefore,
after: dataFunctionDataAfter
};
this.Report.pushMessage(
`Local Data has been overwritten by store items:`,
messageObject
);
}
// In this method we iterate over the bindersArray
createMappingsFromBindersArray(bindersArray) {
bindersArray.forEach(item => {
let mapStateObject = {};
// Verbosity below is intentionally, to try and keep an overview of the options
const noNamespace = item.namespace === null;
const state = this.vueInstance.$store.state;
const noAlias = item.alias === null;
const hasAlias = item.alias !== null;
const isVModel = item.isVModel === true;
const notAVModel = item.isVModel === false || item.isVModel === null;
// We split the the mapping into notNamespaced and namespaced for sanity
if (noNamespace) {
this.mapNotNamespaced(
item,
state,
mapStateObject,
hasAlias,
noAlias,
isVModel,
notAVModel
);
} else {
this.mapNamespaced(
item,
state,
mapStateObject,
hasAlias,
noAlias,
isVModel,
notAVModel
);
}
});
}
// Map passes
createMappingsFromPassesArray(passesArray) {
passesArray.forEach(item => {
const hasAlias = item.alias !== null;
if (hasAlias) {
this.vueInstance.$options.computed[item.alias] = {
get() {
return this.$parent[item.bind];
},
set(value) {
this.$parent[item.bind] = value;
}
};
} else {
this.vueInstance.$options.computed[item.bind] = {
get() {
return this.$parent[item.bind];
},
set(value) {
this.$parent[item.bind] = value;
}
};
}
});
}
// ...
mapNotNamespaced(
item,
state,
mapStateObject,
hasAlias,
noAlias,
isVModel,
notAVModel
) {
// NO alias NOT a v-model
if (noAlias && notAVModel) {
if (item.binderType === "getters") {
mapStateObject = {
...mapGetters([item.bind])
};
} else {
mapStateObject = {
...mapState([item.bind])
};
}
this.vueInstance.$options.computed[item.bind] = mapStateObject[item.bind];
this.reportMapping(
"noNamespace && noAlias && notAVModel",
mapStateObject,
item
);
}
// NO alias IS v-model
else if (noAlias && isVModel) {
mapStateObject = {
[item.bind]: {
get() {
return state[item.bind];
},
set(value) {
state[item.bind] = value;
}
}
};
this.vueInstance.$options.computed[item.bind] = mapStateObject[item.bind];
this.reportMapping(
"noNamespace && noAlias && isVModel",
mapStateObject,
item
);
}
// WITH alias NOT a v-model
else if (hasAlias && notAVModel) {
if (item.binderType === "getters") {
mapStateObject = {
...mapGetters({
[item.alias]: item.bind
})
};
} else {
mapStateObject = {
...mapState({
[item.alias]: state => state[item.bind]
})
};
}
this.vueInstance.$options.computed[item.alias] =
mapStateObject[item.alias];
this.reportMapping(
"noNamespace && hasAlias && notAVModel",
mapStateObject,
item
);
}
// WITH alias IS v-model
else if (hasAlias && isVModel) {
mapStateObject = {
[item.alias]: {
get() {
return state[item.bind];
},
set(value) {
state[item.bind] = value;
}
}
};
this.vueInstance.$options.computed[item.alias] =
mapStateObject[item.alias];
this.reportMapping(
"noNamespace && hasAlias && isVModel",
mapStateObject,
item
);
}
}
// ...
mapNamespaced(
item,
state,
mapStateObject,
hasAlias,
noAlias,
isVModel,
notAVModel
) {
const namespace = this.resolveNamespace(state, item.namespace);
const namespacedBinding = item.namespace + "/" + item.bind;
// NO alias NOT a v-model
if (noAlias && notAVModel) {
if (item.binderType === "getters") {
mapStateObject = {
...mapGetters({
[item.bind]: namespacedBinding
})
};
} else {
mapStateObject = {
...mapState(item.namespace, [item.bind])
};
}
this.vueInstance.$options.computed[item.bind] = mapStateObject[item.bind];
this.reportMapping(
"hasNamespace && noAlias && notAVModel",
mapStateObject,
item
);
}
// NO alias IS v-model
else if (noAlias && isVModel) {
mapStateObject = {
[item.bind]: {
get() {
return namespace[item.bind];
},
set(value) {
namespace[item.bind] = value;
}
}
};
this.vueInstance.$options.computed[item.bind] = mapStateObject[item.bind];
this.reportMapping(
"hasNamespace && noAlias && isVModel",
mapStateObject,
item
);
}
// WITH alias NOT a v-model
else if (hasAlias && notAVModel) {
if (item.binderType === "getters") {
mapStateObject = {
...mapGetters({
[item.alias]: namespacedBinding
})
};
} else {
mapStateObject = {
...mapState({
[item.alias]: () => namespace[item.bind]
})
};
}
this.vueInstance.$options.computed[item.alias] =
mapStateObject[item.alias];
this.reportMapping(
"hasNamespace && hasAlias && notAVModel",
mapStateObject,
item
);
}
// WITH alias IS a v-model
else if (hasAlias && isVModel) {
mapStateObject = {
[item.alias]: {
get() {
return namespace[item.bind];
},
set(value) {
namespace[item.bind] = value;
}
}
};
this.vueInstance.$options.computed[item.alias] =
mapStateObject[item.alias];
this.reportMapping(
"hasNamespace && hasAlias && isVModel",
mapStateObject,
item
);
}
}
// Return a namespace in the state
resolveNamespace(state, namespaceString) {
// first create array of namespace items
const namespaceArray = namespaceString.split("/");
let resolvedState = state;
namespaceArray.forEach(nameSpaceSegment => {
resolvedState = resolvedState[nameSpaceSegment];
});
return resolvedState;
}
// Helper method to report the mapping to the Report bus
reportMapping(mappingSwitch, mapStateObject, item) {
const data = {};
data.item = item;
const itemRoute = item.namespace
? `${item.namespace}/${item.bind}`
: item.bind;
this.Report.pushMessage(
`Mapping done for state bin "${itemRoute}" with directives: ${mappingSwitch}`,
item,
"array",
"PopulateComputed (class procedure)"
);
}
}