Vue.js 3不使用Vuex时如何将共享store关联到多个单文件组件?
只需先导出store实例,再在需要用到状态的组件中引入并暴露到模板上下文即可,无需额外引入Vuex等第三方状态管理库,具体修改如下:
1. 调整store.js,导出共享状态实例
首先给store添加导出语句,让其他文件可以引入同一个reactive实例:
import { reactive} from 'vue'; const store = reactive({ startingAmount: 0, targetAmount: 0 }); // 新增导出语句 export default store
2. 调整app.vue,绑定输入到全局状态
引入store并暴露到模板,将输入框的v-model直接绑定到store的属性:
<template> <div> <div>How much money do you have?</div> <input type="number" v-model="store.startingAmount" /> <br /> <div>How much money do you want?</div> <input type="number" v-model="store.targetAmount" /> <!-- 补充子组件引用,否则子组件不会渲染 --> <ComponentA /> <ComponentB /> </div> </template> <script> import ComponentA from './component-a.vue'; import ComponentB from './component-b.vue'; // 引入store import store from './store.js' export default { components: { ComponentA, ComponentB }, data() { return { // 将store暴露到模板上下文 store } }, } </script>
3. 调整component-a.vue,响应式计算剩余金额
引入store后通过计算属性动态获取剩余金额:
<template> <div> <div>You have {{ remainingAmount }} to reach your goal.</div> </div> </template> <script> import store from './store.js' export default { data() { return { store } }, computed: { remainingAmount() { // 目标金额小于当前金额时返回0 return Math.max(0, this.store.targetAmount - this.store.startingAmount) } } } </script>
4. 调整component-b.vue,实现进度计算与状态修改
引入store后直接操作实例属性即可同步所有组件的状态:
<template> <div> <div>You are {{ progress }}% of the way there!</div> <button @click="increaseGoal">increase goal by $10</button> </div> </template> <script> import store from './store.js' export default { data() { return { store } }, computed: { progress() { // 避免目标金额为0时除以0报错 if(this.store.targetAmount === 0) return 0 return Math.min(100, (this.store.startingAmount / this.store.targetAmount * 100).toFixed(1)) } }, methods: { increaseGoal() { // 直接修改store属性即可全局同步 this.store.targetAmount += 10; } } } </script>
原理说明:ES模块导出的是引用类型的单例,所有组件引入的都是同一个reactive响应式实例,任意组件修改实例属性都会触发所有用到该属性的组件更新,天然实现全局状态同步。
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

