Ich fühle mich im Moment ein bisschen verlegen. Ich bin ein kleines Kaninchenloch hinuntergegangen, basierend auf einer Syntax, die ich in deiner Frage gesehen habe und die zu einer ganzen Reihe unnötiger Wendungen geführt hat. Die Syntax war:
data() {
return {
enabled: settings.showOverlay
};
}
Welche, aus irgendeinem Grund, ich interpretiert als „gut sicher, wann immer enabled
Änderungen, settings.showOverlay
wird sich ändern, weil Vue reaktive ist“.
Ja, nein.
In diesem Code ist settings.showOverlay
nur der Anfangswert für die enabled
Eigenschaft. Die Eigenschaft enabled
wird reaktiv sein, aber in keiner Weise werden Werte an das Einstellungsobjekt übergeben. Grundsätzlich gibt die Datenfunktion ein Objekt mit einer aktivierten Eigenschaft zurück, die einen Anfangswert von settings.showOverlay
hat und dann das Objekt in ein reaktives Objekt verwandelt.
Wenn Sie möchten, dass die in Vue vorgenommenen Änderungen an Ihr Einstellungsobjekt übergeben werden, müssen Sie nur das Einstellungsobjekt auf dem Datenobjekt von Vue verfügbar machen.
data() {
return {
settings,
};
}
Jetzt wenn Sie Code wie
<div v-show="settings.showOverlay"> Some stuff </div>
<button @click="settings.showOverlay= !settings.showOverlay"></button>
settings.showOverlay
wird nicht nur in der Vue reaktiv sein, aber in dem settings
Objekt. Keine Notwendigkeit für einen der Reifen, die ich unten durchsprang (/ Facepalm).
FWIW Ich glaube, einige der Links, die ich in den Kommentaren erwähnte, beziehen sich auf das Datenobjekt selbst. Das Datenobjekt muss ein einfaches JavaScript-Objekt sein, nicht unbedingt alle Eigenschaften.
Mit anderen Worten, in
data() {
return something
}
something
muss eine einfache JavaScript-Objekt sein.
Original-Antwort
Ich habe in meinem Vue apps dies in ein paar Arten. In meiner ersten App wollte ich das gleiche tun, die Einstellungen in einem externen Modul speichern, das die Einstellungen beibehalten und diese Einstellungen auf meinem Vue verfügbar machen konnte. Ich habe am Ende eine Klasse geschrieben, die so aussieht.
class Settings {
constructor(){
// read settings from persisted solution
}
get(key){
// return "key" from settings
}
set(key){
// set "key" in settings
}
save(){
// save settings to persisted solution
}
}
export default Settings
Und dann verwendet, dass in meinem Vue so.
import Settings from "./settings"
new Vue({
data:{
someSetting: Settings.get("someSetting")
}
})
Und dann einen Punkt später, trigger set() und save(). Dieser Punkt war für mich immer dann, wenn eine Routenänderung ausgelöst wurde. Ich würde alle Einstellungen auf das Objekt "Einstellungen" zurücksetzen und dann speichern.
Es klingt wie das, was Sie haben, ist, dass Sie ein Objekt exportieren, das Getter/Setter-Eigenschaften möglicherweise so etwas hat.
export const settings = {
overlay: stored.showOverlay,
get showOverlay(){
return this.overlay
},
set showOverlay(v){
this.overlay = v
}
}
Wo Sie vielleicht auslösen ein speichern, wenn set
ausgelöst wird. Ich mag diese Idee besser als die oben beschriebene Lösung. Aber es zur Arbeit zu bringen ist ein bisschen mehr Arbeit. Zuerst habe ich versucht, eine berechnete zu verwenden.
new Vue({
computed:{
showOverlay: {
get(){ return settings.showOverlay }
set(v) { settings.showOverlay = v }
}
}
})
Aber das funktioniert nicht ganz, weil es keine Änderungen an der Vue widerspiegelt. Das macht Sinn, weil Vue den Wert nicht wirklich kennt. Das Hinzufügen einer $forceUpdate
zum Setter funktioniert auch nicht, ich erwarte aufgrund der Caching-Natur der berechneten Werte. Mit einer in Kombination mit einer Dateneigenschaft berechneten Funktion funktioniert jedoch.
new Vue({
data(){
return {
showOverlay_internal: settings.showOverlay
}
},
computed:{
showOverlay: {
get(){ return this.showOverlay_internal }
set(v) {
settings.showOverlay = v
this.showOverlayInternal = v
}
}
}
})
dass Änderungen sowohl den Zustand des Vue und löst die Änderung der Einstellungen Objekt (das wiederum kann es auslösen persistierenden).
Aber, verdammt, das ist eine Menge Arbeit.
Es ist jedoch wichtig, sich manchmal daran zu erinnern, dass die Objekte, die wir zur Instanziierung von Vue verwenden, nur einfache alte JavaScript-Objekte sind und wir sie manipulieren können. Ich fragte mich, ob ich etwas Code schreiben könnte, der die Dateneigenschaft und den berechneten Wert für uns erstellt. Ein Stichwort von Vuex, ja, wir können.
Was ich damit endete war dies.
import {settings, mapSetting} from "./settings"
const definition = {
name:"app"
}
mapSetting(definition, "showOverlay"
export default definition
mapSetting
erledigt die ganze Arbeit, die wir oben für uns getan haben. showOverlay
ist jetzt eine berechnete Eigenschaft, die auf Änderungen in Vue reagiert und unser Einstellungsobjekt aktualisiert. Der einzige Nachteil im Moment ist, dass es eine showOverlay_internal
Dateneigenschaft freilegt. Ich bin mir nicht sicher, wie wichtig das ist. Es könnte verbessert werden, um mehrere Eigenschaften gleichzeitig abzubilden.
Hier ist der vollständige Code, den ich geschrieben habe, der localStorage
als Persistenzmedium verwendet.
function saveData(s){
localStorage.setItem("settings", JSON.stringify(s))
}
let stored = JSON.parse(localStorage.getItem("settings"))
if (null == stored) {
stored = {}
}
export const settings = {
overlay: stored.showOverlay,
get showOverlay(){
return this.overlay
},
set showOverlay(v){
this.overlay = v
saveData(this)
}
}
function generateDataFn(definition, setting, internalName){
let originalDataFn = definition.data
return function(){
let data = originalDataFn ? originalDataFn() : {}
data[internalName] = settings[setting]
return data
}
}
function generateComputed(internalName, setting){
return {
get(){
return this[internalName]
},
set(v){
settings[setting] = v
this[internalName] = v
}
}
}
export function mapSetting(definition, setting){
let internalName = `${setting}_internal`
definition.data = generateDataFn(definition, setting, internalName)
if (!definition.computed)
definition.computed = {}
definition.computed[setting] = generateComputed(internalName, setting)
}
Ich glaube, Sie für einige Statusbehaftung suchen, ich einen Blick auf [vuex] nehmen würde (http://vuex.vuejs.org/en/intro.html) – dops
Einer der Gründe, begann ich mit Vue ist, weil es "leicht" sein soll und du es in der Lage sein solltest, es ein wenig zu adoptieren.Ich wollte meinen gesamten Anwendungszustand noch nicht auf einen Vue-spezifischen Speicher reduzieren (und ich denke, ich würde mehr Zeit darauf verwenden, zu einem globalen Nachrichtenbusmodell zu wechseln, als ich mit Vue sparen würde). Gibt es nicht einen Weg, "nur ein bisschen Vue" zu benutzen? – Coderer
Ich denke, das umfassendere Problem könnte sein, dass ich Objekte beobachten möchte, die Eigenschaften haben, die bereits einen Getter/Setter verwenden - ich glaube, dass exportierte Module unter der Haube eine schreibgeschützte Ansicht bieten, indem sie die tatsächlichen Eigenschaften verstecken und aussetzen nur ein generierter Getter. Also, wenn ich ein Objekt habe und einen Getter beobachten möchte, gibt es dann ein gutes Muster dafür? – Coderer