vue学习记录二十二:vuex学习记录
一、为什么有Vuex
在vue中,父子传值是v-bind属性绑定,子向父传值是事件绑定,
兄弟组件之间共享数据值EventBus,这是适合小范围内数据共享,大范围中要用其他技术,即vuex
注意的是刷新网页会刷新vuex里state的数据。
二、什么是vuex
vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。本质上就是组件之间实现数据共享。可以把vuex看作一个仓库,所有的组件都可以把数据存在这里,也可以从这里拿取数据。
三、vuex的作用
1.能够在vuex中集中管理共享数据,易于开发和后期维护。
2.能够高效的实现组件之间的数据共享,提高开发效率。
3.存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步。这也是vuex最重要的一点,浏览器本地存储的数据还需进一步操作才能改变页面。
四、什么时候使用vuex
当组件之间有共享数据时,可以使用vuex,组件私有的数据存放在data中,但这不是绝对的,视情况而定。
五、安装vuex
1.安装vuex
npm install vuex --save
2.导入vuex
新建一个store.js文件用来配置store
//在store.js文件中
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(vuex)
//Vue的use其实是调用来vuex方法里的install方法
3.创建store对象
//在store.js文件中
const store =new Vuex.Store({
state:{ count :0}
})
export default store
//将这个实例对象暴露出去
4.将store对象挂载到vue实例中
import Vue from 'vue'
import App from './PP.vue'
import store from './store'
//入口文件main.js中,引入这个store对象,挂载到vue实例中
new Vue({
el:"#app",
render:h=>h(app),
router,
store
//将创建的共享数据对象,挂载到vue实例中,
//这样所有的组件,就可以直接从store对象中获取对象了。
})
六、vuex的组成
1.state
state就是存放的公共数据源,所有共享的数据都要统一放到Store的state中进行存储。
驱动应用的数据源(也就是状态)
1.创建store数据源
还是在刚才的store.js文件中配置
const store = new Vuex.Store({
state:{
count:0,
}
})
//这个count就是共享的数据
2.组件访问state中数据的方式
1.this.$store.state
在某个组件中使用
this.$store.state.全局数据名称
//this.$store.state.count就能访问这个组件0 了。
2.从vuex中按需导入mapState函数
某个组件中
import { mapState } from 'vuex'
//mapState时vuex中自带的
通过这个mapState函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性
computed:{
...mapState(['count'])
//count变成了计算属性。
//直接在这个组件使用count即可。相当于在data里面了。
}
2.Mutation
在vuex中直接修改state里的数据
this.$store.state.count++
//这种方式是不对的
不要使用组件直接修改state中 的数据。
虽然能用,但是不安全,以后想找谁修改的都找不到。
使用Mutation来变更修改数据,可以方便后期的维护,找到谁能修改这个数据。方便追溯
1.修改state数据,先定义好方法
还是在store.js文件中先配置Mutation
const store = new Vuex.Store({
state:{
count:0,
},
mutations:{
add(state){
state.count++
}
//state形参就是store 对象中的state对象,可以通过这个对象访问store中的数据,
}
})
//这个count就是共享的数据
2.在组件中通过调用方法修改数据
某个组件中
methods:{
handle(){
this.$store.commit('add')
//commit就是调用哪个方法的函数,参数就是那个方法的名字
//add就是你要调用的那个方法名字
}
}
3.修改数据时携带参数
需要携带参数时,必须现在store中定义好形参,mutations里的方法,默认第一个参数是state,而第二个参数就是要携带的参数,一般我们都写上,不管用不用的到。
const store = new Vuex.Store({
state:{
count:0,
},
mutations:{
add2(state,step){
state.count+=step
}
某个组件中
methods:{
handle(){
this.$store.commit('add2',3)
//commit第二个参数就是要传过去的参数
}
}
4.第二种触发mutations的方法
从vuex中导入mapMutation函数
import {mapMutation} from 'vuex'
通过刚才导入的mapMutation函数,将需要的函数,映射为当前组件的methods方法
在某个组件中
methods:{
...mapMutation(['add','add2'])
//这样就能直接创建store中定义在mutations的方法了。
hande(){
this.add()
//再通过这样的方式调用对应的方法名即可。
this.add2(3)
//需要传递的参数直接放在这个方法中就能把参数传递过去了。
//当然对应的mutations中已经定义好了这个方法
}
}
3.action
1.定义异步函数
在mutations函数中,不能写异步函数,定时器之类的。
要执行异步任务,使用aciton属性来执行,但其实是在aciton中触发mutations中的函数来间接变更数据的。
const store = new Vuex.Store({
state:{
count:0,
},
mutations:{
add2(state){
state.count++
}
actions:{
addAsync(context){
setTimeout(()=>{
context.commit('add2')
//这边就是调用mutations的方法,这样才能异步,不要直接调用state中的数据。
})
,1000}
}
2.触发异步函数
在某个组件中
methos:{
handle(){
this.$store.dispatch('addAsync')
//这样即可触发actions中的对应的函数,通过store对象的dispatch方法,来触发action中的函数
}
}
3.触发异步函数携带参数
const store = new Vuex.Store({
state:{
count:0,
},
mutations:{
add3(state,step){
state.count+=step
}
actions:{
addAsync(context,step){
setTimeout(()=>{
context.commit('add3',step)
//这边就是调用mutations的方法,这样才能异步,不要直接调用state中的数据。
})
,1000}
}
在某个组件中
methos:{
handle(){
this.$store.dispatch('addAsync',5)
这样即可把参数传递过去。
}
4.触发action的第二种方式
先导入vuex中的一个函数
import { mapAction } from 'vuex'
通过这个函数,将需要的action函数,映射为当前组件的methods方法.
组件中
methods:{
...mapAction ([ 'addAsync' ])
//将这个函数映射为这个组件的一个方法
hande(){
this.addAsync()
//通过这种方式调用
//需要传递的参数直接写在()里即可
}
}
4.Getter
Getter用于对Store中的数据进行加工和处理,形成新的数据。
1.Getter可以对Store中已有的数据,进行加工处理之后形成新的数据,类似于vue的计算属性。
2.Store中数据发送变化,Getter的数据也会跟着改变。
1.创建getters
//定义Getter
const store = new Vuex.Store({
state:{
count :0,
}
getters:{
showNum:state=>{
return '当前最新的数量是' + state.count
//state就是store对象中的state
//getters不会修改state中的数据,只会进行一个包装的作用。
}
}
})
2.触发getters
this.store.getters.名称
//this.store.getters.showNum就能调用getters的方法,把返回的内容显示出来
3.触发getters的第二种方法
import {mapGetters} from 'vuex'
computer:{
...mapGetters(['showNum'])
//可以把showNum映射为组件的一个计算属性。可以当作计算属性进行调用即可。
//相当于data里的一个变量了。
}
5.module
每个模块用来管理一部分特点的功能,每个模块可以看做是一个小vuex,是根vuex来管理这些小vuex,这是模块里的属性和根vuex里的属性一致
//根store中
const store = new Vuex.Store({
//这里定义了两个模块user和setting
modules:{
usesr:{
state:{
token :'123'
}
},
setting:{
state:{
username:'我'
}
}
}
})
在某组件中获取这个模块里的数据
this.$store.state.user.token
//省略了根vuex的modules和子modules的state两个属性
可以通过getters来简化这个语句
const store = new Vuex.Store({
modules:{
usesr:{
state:{
token :'123'
}
},
setting:{
state:{
username:'我'
}
}
//getters是根级别的state
getters:{
token :state=>{
return state.user.token
}
username:state=>{
return state.setting.username
}
//这样就能使用this.store.getters.名称来获取token了。
//或者映射到组件的computed属性中
//computed:{
...mapGetters(['token','username'])
}
})
6.namespaced
模块化命名空间
默认情况下,模块内部的action,mutation,getters,默认挂在在根vuex下的
可以直接使用
const store = new Vuex.Store({
modules:{
usesr:{
//加了这句话就是加来一把锁
//namespaced:true,
state:{
token :'123'
},
mutations:{
setstate:state=>{
//子模块中mutations中的state参数是子模块中state
state.token = '456'
}
},
setting:{
state:{
username:'我'
},
mutations:{
setstate:state=>{
//子模块中mutations中的state参数是子模块中state
state.username= '789'
}
}
}
某组件中
this.$store.commit('setstate')
//可以直接使用,和使用根vuex中的mutations一致。
但这种不能保证模块的高封闭性。可以直接访问属性。所以引申出namespaced,命名空间。这样就不能直接调用了。它是boolean值,写了之后,就不能挂载到全局vuex中 了。
需要调用时,需写
this.$store.commit('user/setstate ')
//加上模块的名称即可。
//或者
...mapMutations(['user/setstate'])
//使用时,就写this['user/setstate']()就能调用了。
//或者导入辅助函数
import {createNamespacedHelpers} from 'vuex'
const {mapMutations} = createNamespacedHelpers('user')
//这个mutations就是子模块里的mutations
//然后写
...mapMutations(['setstate'])
//就能获取到这个方法了
//要是mapMutations和根vuex的mapMutations冲突
//可以const mapMutations2= createNamespacedHelpers('user').mapMutations
//这样就正常些了。