Vue3页面刷新后watch失效:多语言切换仅Navbar组件生效
问题描述
我正在开发一款支持两种语言的Vue应用,用localStorage和Vuex Store保存用户选择的语言。登录后默认语言能在Navbar和Home组件正常显示,切换语言时两个组件的watch都能触发并更新文本。但页面刷新后,切换语言只有Navbar组件内容更新,Home组件的watch没触发,尽管mutations里的setter能打印出选中的语言。退出登录并刷新后重新操作又能恢复正常,直到再次刷新。请问问题出在哪里?
Vuex Store 代码
const localLanguage = localStorage.getItem('xx-user-language') const state = () => ({ userLanguage: undefined, }); const getters = { getUserLanguage(state) { if(localLanguage !== null && localLanguage !== undefined){ return localLanguage } return state.userLanguage; }, }; const mutations = { setUserLanguage(state, data) { localStorage.setItem('xx-user-language', data) console.log("setter " + data) state.userLanguage = data; }, };
Navbar 组件
HTML 部分
<div title="deutsch" class="icon-container"> <img @click="setLanguage('de')" src="german.png" alt="deutsch"> </div> <div title="english" class="icon-container"> <img @click="setLanguage('en')" src=".english.png" alt="english"> </div>
JS 部分
computed:{ ...mapGetters('language',{ getUserLanguage:"getUserLanguage" }) }, watch:{ getUserLanguage: function(newValue){ this.setLanguage(newValue) } }, methods: { setLanguage(lang){ this.setUserLanguage(lang) this.text = text.navbar[lang] }, ...mapMutations('language',{ setUserLanguage:"setUserLanguage" }) }
Home 组件 JS 部分
computed: { ...mapGetters('language',{ getUserLanguage:"getUserLanguage" }) }, watch: { getUserLanguage: function(newValue){ console.log("home watcher" + newValue) this.setLanguage(newValue) } }, methods: { setLanguage(lang){ this.text = text.homepage[lang] }, },
问题根源
问题出在Vuex Store的getUserLanguage getter逻辑上:
localLanguage是Store模块初始化时从localStorage读取的常量,只会在页面加载时读取一次。- 页面刷新前,
state.userLanguage有值,getter会返回state.userLanguage;刷新后state.userLanguage重置为undefined,getter就固定返回初始化时读取的localLanguage常量。 - 切换语言时,虽然
state.userLanguage和localStorage都被更新,但getter返回值始终是初始化时的常量,没有变化,所以Home组件的watch不会触发。而Navbar组件是直接在点击事件里更新文本,所以看起来正常。
另外,Navbar组件的watch存在循环调用问题:watch到getUserLanguage变化后调用setLanguage,而setLanguage又会触发mutation更新state,再次触发watch,形成死循环。
解决方案
1. 修复Vuex Getter逻辑
有两种可行方案:
方案1:每次调用getter时实时读取localStorage
const getters = { getUserLanguage(state) { const currentLocalLang = localStorage.getItem('xx-user-language') if(currentLocalLang !== null && currentLocalLang !== undefined){ return currentLocalLang } return state.userLanguage; }, };
方案2:初始化state时从localStorage取值,getter直接返回state
const state = () => ({ userLanguage: localStorage.getItem('xx-user-language') || undefined, }); const getters = { getUserLanguage(state) { return state.userLanguage; }, };
2. 修复Navbar组件的循环调用问题
修改watch逻辑,只更新文本,不再触发mutation:
watch:{ getUserLanguage: function(newValue){ this.text = text.navbar[newValue] } }, methods: { setLanguage(lang){ this.setUserLanguage(lang) this.text = text.navbar[lang] }, ...mapMutations('language',{ setUserLanguage:"setUserLanguage" }) }
内容的提问来源于stack exchange,提问作者Issam Jourhbiri
相关产品推荐
相关产品推荐

