组件之间共享数据的方式
-
父向子 使用属性绑定传值 v-bind
-
子向父 使用事件绑定传值 v-on
-
兄弟组件之间共享数据 :Event Bus
-
$on 接收数据 的那个组件
-
$emit 发送数据的哪个组件
-
Vuex是什么
vuex是专为vue.js应用程序开发的
状态管理模式。它采用集中式存储管理应用的所有组件的状态,可以更方便的实现组件之间的数据共享。
使用Vuex管理数据的优点
- 能够在Vue中集中管理共享数据 ,便于开发和有利于后期的维护
- 能够实现组件之间的数据共享,提高开发效率
- 存储在Vuex的数据是响应式的,只要数据发生改变,页面中的数据也会同步更新。
使用Vuex的场景
- 一般情况下,只有数组之间共享的数据 ,才有必要存储在Vuex中
- 组件的私有数据,存储在自身组件 的data中
Vuex的基本使用
- 安装 方案一
-
npm安装 Vuex依赖包
npm install vauex --save -
导入 Vuex 包
import Vuex from "vuex" Vue.use(Vuex) //挂载到vue上 -
创建
store对象const store=new Vuex.Store({ //state中存放的就是全局共享的数据 state:{count:0} })4.将store对象挂载到 Vue实例中
-
new Vue({ el:"#app", render:h=>(app), router, //所有组件,就可以直接从store中获取全局的数据 store }) -
安装 方案二
-
打开终端,输入命令:vue ui
-
创建项目,设置项目名称和包管理器
-
设置手动配置项目
-
设置功能项
-
标准配置 、创建项目。
Vuex中的核心特性
State (数据)
-
组件 访问State中数据 的
方式 一
State提供唯一的公共数据源,所有共享的数据都要统一放到State中进行存储
//创建 store数据源,提供唯一公共数据
const store= new Vuex.Store({
state:{ count:0 }
})
//组件中的插值表达式中访问State中数据的第一种方式
this.$store.state.全局数据名称
-
组件访问State中数据的
方式二
// 从vuex中按需导入mapState函数
import {mapState} from 'vuex'
//通过刚才导入的mapState函数,将当前组件需要的全局数据,映射为当前组件的computed 计算属性
computed:{
...mapState(['count']) //使用扩展运算符... 可使 mapState映射成当前组件的计算属性
}
Mutation (方法)
Mutation 里
不能执行 异步任务异步任务需要使用Action
-
Mutation用于变更Store中的数据
(方式一)- 只能通过Mutation变更Store数据,不可以直接操作Store中的数据
- 通过这种方式虽然 操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
- 在组件的methods中使用 this.$store.commit 可获取mutation的方法
- 可在触发mutation时传递参数
<script> //Store.vue文件中定义Mutation const store=new Vuex.Store({ state:{ count:0 }, mutations:{ //只改变数据,不会传参 add(state){ //变更状态 state.count++ }, //触发mutation时传递参数 step addN(state,step){ // 变更数据 state.count+=step } } }) <script><script> //在组件中使用 触发Mutation methods:{ handle1(){ //commit用于触发mutation的某个函数 this.$store.commit("add") } handle2(){ //commit用于触发mutation函数时并携带参数 this.$store.commit("addN",3) } } <script> -
触发mutation的第
方式二-
从Vuex中按需导入
mapMutations函数//从vuex中按需导入mapMutations函数 import {mapMutations} from "vuex" -
通过刚导入的mapMutations函数,将需要的mutations函数,映射为当前组件的methods方法
使用... 扩展运算符
同样可以传递参数<script> //在组件中将mutations函数,映射为当前组件的methods函数 methods:{ ...mapMutations(["add","addN"]) //add,与addN为mutation的方法 handle1(){ this.add() //使用mutation中的add方法 }, handle2(){ this.addN(3) //使用mutation中的addN方法 并传递参数 3 } } <script>
-
Action(执行异步任务)
Action用于处理异步任务
- 触发Action异步任务
方式一- 操作异步变更数据,必须通过Action,而不能使用Mutation,但是在Action中必须
通过触发Mutation的方式间接变更数据 - 在组件中使用
this.$store.dispatch(“方法名”)触发 Action
- 操作异步变更数据,必须通过Action,而不能使用Mutation,但是在Action中必须
<script>
// 在store.vue文件中
const store=new Vuex.store({
state:{
count:0
},
mutations:{
add(state){
state.count++
},
addN(state){
state.count++
}
},
actions:{ //actions处理异步操作
addAsync(context){
setTimeout(()=>{
context.commit("add") //commit触发mutation的add方法
},1000)
},
addNAsync(context,step){
setTimeout(()=>{
context.commit("addN",step)//commit触发mutation的addN并携带 参数step
},1000)
}
}
})
<script>
<script>
//在组件中使用 触发Action
methods:{
handle1(){
//触发actions的第一种方式
this.$store.dispatch("addAsync")
},
handle2(){
//dispatch触发 actions的异步 并携带参数
this.$store.dispatch("addNAsync",5)
}
}
<script>
-
触发 Action异步任务
方式二-
...mapActions(”方法名“)是触发Action的第二种方式// 从vuex 中按需导入 mapActions函数 import mapActions from "vuex" -
通过刚导入的mapActions函数,将需要的actions函数,映射为当前组件的methods方法
<script> //将指定的 actions函数,映射为当前组件的 methodes 函数 methods{ ...mapActions(["add","addN"]) handle1(){ this.add() //使用mutation中的add方法 }, handle2(){ this.addN(3) //使用mutation中的addN方法 并传递参数 3 } } <script>
-
Getter (处理形成新数据)
-
Getter用于对Store中的数据进行加工处理形成新的数据,
类似Vue的计算属性 -
Store的数据发生改变,Getter的数据也会发生改变
<script> // 在store文件中 定义 Getter const store= new Vuex.Store({ state:{ count:0 }, getters:{ // 定义了showNum函数 showNum:state=>{ return:"当前最新的数据是 ‘+state.count+’ " } } }) <script> -
在组件中使用 getters的第一种方式:
this.$store.getters.函数名称 -
使用getters的第二种方式 。映射 ....
-
注意 需要在computed的计算属性中使用import {mapGetters} from "Vuex" computed:{ ...mapGetters({"showNum"}) }
module(分割成模块)
应用场景:当项目变得非常复杂时,store ,mutation,action,getter。就有可能变得相当臃肿。而modules分割成模块方便于管理
-
全局定义
//全局定义 moduleA和moduleB模块最后在modules注册 const moduleA = { state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: () => ({ ... }), mutations: { ... }, actions: { ... } } const store = createStore({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA 的状态 store.state.b // -> moduleB 的状态
-
模块命名
注意不要在不同的,无命名空间的模块中定义两个相同的getter从而导致冲突-
添加
namespaced: true的方式使其成为带命名的模块,从而模块具有更高的复用性和封装度 -
当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。例如:
commit('account/login')const store = createStore({ modules: { //父模块 account: { namespaced: true, // 模块内容(module assets) state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响 getters: { isAdmin () { ... } // -> getters['account/isAdmin'] }, actions: { login () { ... } // -> dispatch('account/login') }, mutations: { login () { ... } // -> commit('account/login') }, // 嵌套模块 modules: { // 继承父模块的命名空间 myPage: { state: () => ({ ... }), getters: { profile () { ... } // -> getters['account/profile'] } }, // 进一步嵌套命名空间 posts: { namespaced: true, state: () => ({ ... }), getters: { popular () { ... } // -> getters['account/posts/popular'] } } } } } })
-
访问数据和修改数据的调整
-
访问模块中的数据,要加上模块名
获取数据项: {{$store.state.模块名.数据项名}} 获取getters: {{$store.getters['模块名/getters名']}} -
访问模块中的mutations/actions:
- 如果namespaced为true,则需要额外去补充模块名
- 如果namespaced为false,则不需要额外补充模块名
$store.commit('mutations名') // namespaced为false $store.commit('模块名/mutations名') // namespaced为true
「点赞、收藏和评论」
❤️关注+点赞+收藏+评论+转发❤️,鼓励笔者创作更好的文章,谢谢🙏大家。