Я чувствую себя немного застенчивым в данный момент. Я спустился в маленькую кроличью нору, основываясь на некотором синтаксисе, который я увидел в вашем вопросе, и это привело к целому ряду ненужных вращений. Синтаксис был таким:
data() {
return {
enabled: settings.showOverlay
};
}
Что, по какой-то причине, я интерпретировал как «конечно, всякий раз, когда enabled
изменяется, settings.showOverlay
будет меняться, потому что Vue реактивен».
Да, нет.
В этом коде settings.showOverlay
— это просто начальное значение для свойства enabled
. Свойство enabled
будет реактивным, но оно никоим образом не будет передавать значения объекту настроек. По сути, функция данных возвращает объект с включенным свойством, начальное значение которого равно settings.showOverlay
, а затем этот объект превращается в реактивный объект.
Если вы хотите, чтобы изменения, сделанные в Vue, передавались в ваш объект настроек, все, что вам нужно сделать, — это открыть объект настроек в объекте данных Vue.
data() {
return {
settings,
};
}
Теперь, если у вас есть код, подобный
<div v-show="settings.showOverlay"> Some stuff </div>
<button @click="settings.showOverlay= !settings.showOverlay"></button>
settings.showOverlay
будет реагировать не только на Vue, но и на объект settings
. Нет необходимости в каких-либо обручах, через которые я прыгнул ниже (/facepalm).
FWIW Я считаю, что некоторые из ссылок, которые я упомянул в комментариях, относятся к самому объекту данных. Объект данных должен быть простым объектом javascript, а не обязательно всеми его свойствами.
Другими словами, в
data() {
return something
}
something
должен быть простым объектом javascript.
Исходный ответ
Я сделал это несколькими способами в своих приложениях Vue. В моем первом приложении я хотел сделать то же самое, сохранить настройки во внешнем модуле, который мог бы управлять сохранением настроек и отображать эти настройки в моем Vue. Я закончил тем, что написал класс, который выглядит так.
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
А затем использовал это в моем Vue вот так.
import Settings from "./settings"
new Vue({
data:{
someSetting: Settings.get("someSetting")
}
})
А затем через некоторое время вызовите set() и save(). Этот момент для меня заключался в том, что всякий раз, когда срабатывало изменение маршрута, я просто устанавливал все настройки обратно в объект «Настройки», а затем сохранял.
Похоже, что у вас есть экспорт объекта, который имеет свойства getter/setter, возможно, что-то вроде этого.
export const settings = {
overlay: stored.showOverlay,
get showOverlay(){
return this.overlay
},
set showOverlay(v){
this.overlay = v
}
}
Где вы, возможно, активируете сохранение, когда срабатывает set
. Мне нравится эта идея больше, чем решение, которое я описал выше. Но заставить его работать - немного больше работы. Сначала я попытался использовать вычисляемый.
new Vue({
computed:{
showOverlay: {
get(){ return settings.showOverlay }
set(v) { settings.showOverlay = v }
}
}
})
Но это не совсем работает, потому что не отражает изменений в Vue. Это имеет смысл, потому что Vue на самом деле не знает, что значение изменилось. Добавление $forceUpdate
к установщику тоже не работает, я полагаю, из-за кэширования вычисляемых значений. Однако использование вычисляемого в сочетании со свойством данных действительно работает.
new Vue({
data(){
return {
showOverlay_internal: settings.showOverlay
}
},
computed:{
showOverlay: {
get(){ return this.showOverlay_internal }
set(v) {
settings.showOverlay = v
this.showOverlayInternal = v
}
}
}
})
Это изменяет как состояние Vue, так и запускает изменение объекта настроек (что, в свою очередь, может вызвать его сохранение).
Но, черт возьми, это много работы.
Однако иногда важно помнить, что объекты, которые мы используем для создания экземпляров Vue, — это просто старые объекты javascript, и мы можем манипулировать ими. Я подумал, могу ли я написать какой-нибудь код, который создает для нас свойство данных и вычисляемое значение. Беря пример с Vuex, да, мы можем.
Что я закончил с этим.
import {settings, mapSetting} from "./settings"
const definition = {
name:"app"
}
mapSetting(definition, "showOverlay"
export default definition
mapSetting
делает за нас всю работу, которую мы сделали выше. showOverlay
теперь является вычисляемым свойством, которое реагирует на изменения в Vue и обновляет наш объект настроек. Единственным недостатком на данный момент является то, что он предоставляет свойство данных showOverlay_internal
. Я не уверен, насколько это важно. Это может быть улучшено, чтобы сопоставлять несколько свойств одновременно.
Вот полный код, который я написал, который использует localStorage
в качестве носителя сохраняемости.
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)
}
person
Bert
schedule
19.06.2017