vuex使用教程

vuex核心思想

1、vuex应用的核心就是store(仓库)。可以把store看作一个容器,它包含着应用中大部分的状态state。

2、vuex和单纯的全局对象有一下两点不同:
(1)vuex的状态存储是响应式的,当vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会相应的得到高效更新。
(2)你不能直接改变store中的状态,改变store中的状态的唯一途径就是显式地提交(commit)mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

3、vuex中最关键的是store对象,这是vuex的核心。每个vue应用仅有一个store对象。

4、vuex 对其进行了 vue 的适配,借助 vue 的 细粒度响应机制(文档说的)进行高效的状态更新,基本上大型项目如果要进行状态管理,直接使用 vuex 就可以。
在这里插入图片描述
为了再vue组件中访问this.$store属性,需要为vue实例提供创建好的store,vuex提供了一个从根组件向所有子组件以store选项的方式注入该store的机制,npm的方式,系统自动生成,代码在main.js中:

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

使用npm项目,在根目录store文件夹下面有一个index.js文件,里面的内容自动生成如下:

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
    state: {
	count:20
},
    mutations: {},
    actions: {},
    modules: {},
});

一定要确保 Vue.use(Vuex); 在 new Vuex.Store({}) 之前调用。

调用方法:

(1)在组件中的js中调用方法:this.$store.state.xx

methods:{
	myCount(){
		console.log(this.$store.state.count);//输出结果20
	}
}

(2)在组件的页面中调用方法:$store.state.xx

<div>{{$store.state.count}}</div><!--显示结果20-->

(3)此时如果我们想要修改count的值怎么办呢?使用mutations

实例1,:
在mutations中写一个方法,名字自定义:

mutations:{
	increment(s){//变量默认表示的是state
		s.count=s.count+100;
	}
}

1.1全局修改count的值
在全局main.js中使用commit调用mutations中的方法

store.commit('increment')

组件中调用count,会发现count的值已经发生变化:

methods:{
	myCount(){
		console.log(this.$store.state.count);//输出结果120
	}
}

1.2局部修改count的值:
直接在vue组件页面中使用方法:

methods:{
	myCount(){
  		this.$store.commit('increment')
   		console.log( this.$store.state.count);
   	}
}

解释,我们为什么要通过mutation的方法去修改state中的值呢,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。

由于 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性computed中返回即可。触发变化也仅仅是在组件的 methods 中提交 mutation。


5个核心概念:

  • state存放状态

  • getters是state的计算属性

  • mutations更改状态的逻辑,同步操作

  • actions提交mutations,异步操作

  • mudules将store模块化

注意:

1.store中存储的状态是响应式的,当组件从store中读取状态时,如果store中的状态发生了改变,那么相应的组件也会得到更新。


2.不能直接改变store中的状态。改变store中的状态的唯一途径是提交(commit)mutations。这样使得我们可以方便地跟踪每一个状态的变化。


一个完整的store的结果是这样的

const store = new Vuex.Store({
  state: {
    // 存放状态
  },
  getters: {
    // state的计算属性
  },
  mutations: {
    // 更改state中状态的逻辑,同步操作
  },
  actions: {
    // 提交mutation,异步操作
  },
  // 如果将store分成一个个的模块的话,则需要用到modules。
   //然后在每一个module中写state, getters, mutations, actions等。
  modules: {
    a: moduleA,
    b: moduleB,
    // ...
  }
});

1.state 存放状态

简介:state上存放的,说的简单一些就是变量,也就是所谓的状态。没有使用 state 的时候,我们都是直接在 data 中进行初始化的,但是有了 state 之后,我们就把 data 上的数据转移到 state 上去了。另外有些状态是组件私有的状态,称为组件的局部状态,我们不需要把这部分状态放在store中去。

state是存储的单一状态,是存储的基本数据。

使用方法:

在store文件夹下面的index.js中定义state状态

export default new Vuex.Store({
  state: {
    count:"hello world",
    age:12
  }
})

调用:在home.vue中使用:
由于vuex的状态是响应式的,从store实例中读取状态最简单的方法就是在计算属性中返回某个状态。

//在computed中定义一下
computed:{
	getAge(){
		return this.$store.state.age;
	}
}
//在mounted中打印出来
mounted(){
	console.log(this.getAge);
}

打印结果:12
每当state中的count变化的时候,都会重新求取计算属性,并且触发更新关联的DOM。

直接在vue组件页面中调用:

<div>
{{$store.state.count}}
</div>

输出结果:hello world

1.1 mapState

当一个组件获取多种状态的时候,则在计算属性中要写多个函数。为了方便,可以使用mapState辅助函数来帮我们生成计算属性。

实例,在index.js中

  state: {
    count:"hello world",
    age:22
  },

在home.vue中,mapState可以写多个函数。
先在vue页面中导入mapState

import {mapState} from 'vuex'
computed:mapState({
  x:i=>i.age,//此处的i表示的是store里面的state
  countPlus(s){//此处的s表示的是store里面的state
    return s.age+s.count
  }
}),
mounted(){
	console.log(this.countPlus);//输出结果 22hello world
}

上面是通过mapState的对象来赋值的,还可以通过mapState的数组来赋值,这种方式很简洁,但是组件中的state的名称就跟store中映射过来的同名

computed:mapState(['age','count']),
  mounted(){
    console.log(this.age);//22
    console.log(this.count);//count
  }

实例2:
mapState 函数返回的是一个对象,为了将它里面的计算属性与组件本身的局部计算属性组合起来,需要用到对象扩展运算符

data(){
localState: 1
}
computed: {
  localState () { 
  ... mapState ({
      
    })
  }

这样,mapState中的计算属性就与localState计算属性混合一起了。

2. getters 是state的计算属性

作用:有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数。此时可以用到getters,getters可以看作是store的计算属性,其参数为state。

getters是store的计算属性,对state的加工,是派生出来的数据。就像computed计算属性一样,getter返回的值会根据它的依赖被缓存起来,且只有当它的依赖值发生改变才会被重新计算。

实例:
在store的index.js中如下:

state: {//state中定义了一个数字todos,数组里面有两个对象
    todos:
    [{id:1,text:'reading',done:true},{id:2,text:'reading',done:false}]
    },
getters:{
//在getters中定义一个方法,其中参数s表示的是state,对state中的todos进行过滤,过滤done为true的数据
    doneTodos:s=>{
      return s.todos.filter(d=>d.done)
    }
  },

如何在vue页面使用呢,在home.vue中如下:

computed:{
  dd(){
    return this.$store.getters.doneTodos;
  }
},
  mounted(){//在mounted中打印出来
    console.log(this.dd);//[{id:1,text:'reading',done:true}]
  }

还可以再home.vue页面中使用mapGetter中获取:

import {mapGetters} from 'vuex'//导入mapGetters
computed:{//computed中使用扩展运算符获取
...mapGetters(['doneTodos'])
},
mounted(){
 console.log(this.doneTodos)//打印出来[{id:1,text:'reading',done:true}]
  }

3. mutations 更改状态的逻辑,同步操作

简介:
1、mutations里面是如何更改state中状态的逻辑。更改Vuex中的state的唯一方法是,提交mutation,即store.commit(‘increment’)。

2、更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

3、那么mutation应该在哪里提交呢? 因为js是基于事件驱动的,所以改变状态的逻辑肯定是由事件来驱动的,所以store.commit(‘increment’)是在组件的methods中来执行的。

4、mutations提交更改数据,使用store.commit方法更改state存储的状态。(mutations同步函数)

注:mutations里面的参数可以有多个,第一个默认是state,第二个及后面为自定义的参数,参数可以是对象。

3.1提交载荷(payload)

可以向commit传入额外的参数,即mutation的载荷。
实例:
在store文件夹里面的index.js中如下:

  state: {
    count:3
  },
mutations: {
//一个方法increacount,有两个参数,其中第一个参数s表示的是state
    increment(s,n)
    {
      s.count+=n;
    }
  },

在home.vue中调用:
你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

methods:{
	myCrease(){
		this.$store.commit('increment',20);
		console.log(this.$store.state.count)
	}
}
mounted(){
	this.myCrease();//输出结果23
}

上面的如果不在home中调用,可以直接写在main.js中:

store.commit('increacount', {amount: 10});//13

实例二:mutations里面的方法第2个参数还可以是一个对象。

state: {
    count:3
},
mutations: {
    increment(s,p)
    {
      s.count+=p.amount;
    }
  },

vue页面中调用:

methods:{
	myMet(){
    this.$store.commit('increment',{amount:90})
    	console.log(this.$store.state.count)
  	}
},
mounted(){
 this.myMet();//93
  }

注意:mutation必须是同步函数,不能是异步的,这是为了调试的方便。

同步和异步的概念

定义:同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)。同步,就是调用某个东西是,调用方得等待这个调用返回结果才能继续往后执行。异步,和同步相反 调用方不会理解得到结果,而是在调用发出后调用者可用继续执行后续操作,被调用者通过状体来通知调用者,或者通过回掉函数来处理这个调用

比方说:你去商城买东西,你看上了一款手机,能和店家说你一个这款手机,他就去仓库拿货,你得在店里等着,不能离开,这叫做同步。现在你买手机赶时髦直接去京东下单,下单完成后你就可用做其他时间(追剧、打王者、lol)等货到了去签收就ok了.这就叫异步。

4. action 提交mutations,异步操作,使用dispatch分发

作用:因为mutations中只能是同步操作,但是在实际的项目中,会有异步操作,那么actions就是为了异步操作而设置的。这样,就变成了在action中去提交mutation,然后在组件的methods中去提交action。只是提交actions的时候使用的是dispatch(派遣,发送)函数,而mutations则是用commit函数。

actions像一个装饰器,提交mutation,而不是直接变更状态。(actions可以包含任何异步操作)

在 mutation 中混合异步调用会导致你的程序很难调试。例如,当你调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?这就是为什么我们要区分这两个概念。在 Vuex 中,mutation 都是同步事务:

Action 类似于 mutation,不同在于:
1、Action 提交的是 mutation,而不是直接变更状态。
2、Action 可以包含任意异步操作。

实例:
在store的index.js中

state:{
count:20
},
mutations:{
	increment(s){
		s.count=s.count+100;
	}
},
actions:{
	myin(c){
		c.commit('increment')
	}
}

在组件中调用:

methods:{
	myfun(){
	//Action 通过 store.dispatch 方法触发
		this.$store.dispatch('myin');
		console.log( this.$store.state.count);//输出结果120
	}
}

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。

5.Module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

简介:Module是store分割的模块,每个模块拥有自己的state、getters、mutations、actions。

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

6.辅助函数

Vuex提供了mapState、MapGetters、MapActions、mapMutations等辅助函数给开发在vm中处理store。

Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:

应用层级的状态应该集中到单个 store 对象中。

提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。

异步逻辑都应该封装到 action 里面。

只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。

对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值