vuex的学习

1.为什么要学习vuex

vuex是一种对状态做到响应式管理的工具

<script>
    const objShare = {
      name: 'guodong'
    }

    Vue.prototype.objShare= objShare

    Vue.component('cpn1',{
      // this.objShare.name)   在这里拿到
    })
    Vue.component('cpn2',{
      // this.objShare.name)  
    })

    new Vew({
      el:'#app'
    })

  </script>

这里定义一个objShare来管理共享的变量,因为所有的组件都是继承自Vue.prototype,所以所有的组件都可以拿到这个。但此时的变量不是响应式的,也就是说如果cpn2修改了name,此时cpn1里面的name是不跟着改的,因为它并没有放到响应式系统里。

2.管理什么样的状态

1)比如用户的登录状态,用户的名称、头像、地理位置信息等
2)比如商品的收藏和购物车

3.单页面的状态管理

在这里插入图片描述
代码:

<template>
  <div id="app">
  <h2>{{msg}}</h2>
  <span>{count}</span>
  <button @click="count++">+</button>
  <button @click="count--">-</button>
  </div>
</template>

<script>

export default {
  name: 'app',
  components: {
  },
  data () {
    return {
      msg: '我是App组件',
      count: 0
    }
  }
}
</script>

<style>

</style>

这里的data就相当于这个组件的state,{{count}}就相当于view,@click就是action

4.vuex的环境配置

1)创建一个store的文件夹,再 创建一个index.js
2)导入vuex,并且安装

import Vuex from 'vuex'
import Vue from 'vue'
/**
 * 1.安装插件
 */
Vue.use(Vuex)

3)创建变量,并且导出(注意:这里new的是Store对象)

const store = new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {}

})

export default store

4)在main.js中导入 ,并且挂载到vue实例中

import store from './store'
import './plugins/element.js'

Vue.config.productionTip = false

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

挂载到vue实例中之后,就相当于Vue.prototype. s t o r e = s t o r e , 到 时 候 在 所 有 的 组 件 中 就 可 以 通 过 store=store,到时候在所有的组件中就可以通过 store=store,store拿到index.js中定义的store

vuex的机制
在这里插入图片描述
–可以看到在引用vuex中的内容是,可以直接的进行插值,但不推荐直接的修改vuex中的内容,因为到时候可能会有很多的组件要修改vuex的内容,如果中间有一个改错了,就不知道是哪一个组件改错,就不能监听到,所以这里就需要devtools,devtools是vue开发的一个浏览器插件,它可以用来记录每一次状态改变。

=而action是用来进行异步操作的,因为mutation是不能监听到异步操作的

5.安装devtools的插件:

插件包在h://devtools中

在mutation中定义改变属性的方法:

const store = new Vuex.Store({
  state: {
    counter: 100
  },
  mutations: {
    increase (state) {
      state.counter++
    },
    decrease (state) {
      state.counter--
    }
  },
  actions: {},
  getters: {},
  modules: {}

})

其中每一个方法都会默认的传递一个参数state,通过state拿到定义的数据

之后在使用的时候是需要调用this.store.commit(‘方法名’),是用来提交一个方法

methods: {
    btnClick1 () {
      this.$store.commit('increase')
    },
    btnClick2 () {
      this.$store.commit('decrease')
    }
  }

6.state的单一状态树:

如果状态保存到多个store对象中,那么之后的管理和维护都会变得很困难,所以在使用的时候,我们只用一个store来存储所有的状态。

7.getters的基本使用:

此时我们是需要从getters里面去获取一些变异后的状态,
1)和mutations中的方法一样,getters里的方法也是会自动的有一个state参数,
之后在使用的时候是用 $store.getters.属性名

getters: {
    powerCounter (state) {
      return state.counter * state.counter
    },
    ageMore20 (state) {
      return state.students.filter(item => item.age > 20)
    }
  },
  {{$store.getters.ageMore20}}
  {{$store.getters.powerCounter}}

这里和组件中的computed方法很像

2)getters作为参数和传递参数
+++++++++作为参数:(当能用到前面定义的getters属性时使用)

ageMore20Length (state, getters) {
      return getters.ageMore20.length
    }

+++++++++传递参数:如果希望传递参数,只能让getters方法本身返回一个函数

 moreAgeStu (state) {
      return function (age) {
        return state.students.filter(item => {
          return item.age > age
        })
      }
  }
  {{$store.getters.moreAgeStu(25)}}

因为这里$store.getters.moreAgeStu返回的是一个函数,所以他本身后面就就可以传递参数

8.Mutation传递参数:

+++当只有一个参数的时候

 this.$store.commit('increaseCount', count)
 increaseCount (state, count) {
      state.counter += count
    }

+++当需要传递的参数有很多时,直接传递一个对象

 btnClick4 () {
      const stu = {
        id: 4,
        name: 'alan',
        age: 78
      }
      this.$store.commit('increaseStudent', stu)
    }
 increaseStudent (state, stu) {
      state.students.push(stu)
    }

9.mutation的提交风格:

btnClick3 (count) {
      // this.$store.commit('increaseCount', count)
      this.$store.commit({
        type: 'increaseCount',
        count
      })
    },
第一种风格
 increaseCount (state, count) {
      state.counter += count
    },
第二种风格
 increaseCount (state, payload) {
      state.counter += payload.count
    },

其中第二种风格第二个参数传递的是一个对象,payload是负载的意思,

10.mutation的响应规则:

Vuex中的store中的state是响应式的,当state中的数据发生变化时,Vue组件会自动的更新。

这就要求我们要遵守一些规则:
1)提前在store中初始化属性,
2)当给state中的对象添加新属性时,使用下面的方式:
使用Vue.set(obj,‘objProp’,‘newValue’)
这里的set方法既可以用来处理数组也可以用来处理对象,唯一的区别是set数组的话,第二个参数是整形的索引值,set对象的话,第二个参数是对象属性的字符串形式。
3)删除一个属性的时候:
Vue.delect(obj,‘objProp’)

 updataStu (state) {
      Vue.set(state.students[0], 'email', '2291230083@qq.com')
    },
 delStu (state) {
      Vue.delete(state.students[0], 'name')
    }

11.vuex-mutation的类型常量

目的是为了更加的规范,也不容易出错

1)首先是创建一个mutation-styles.js文件

export const INCREMENT = 'increment'

2)之后在组件内导入

 this.$store.commit(INCREMENT)

此时commit里面传入的就是一个常量了
3)相应的在vuex的index.js中导入,

 [INCREMENT] (state) {
      state.counter++
    },

11.action方法的使用

原因:在mutation中,当我们使用devtools时,devtools可以帮助我们捕捉mutation的快照,但当我们执行异步操作时,devtools就不能很好的追踪到这个操作是什么时候完成的。

当需要用异步操作时,我们需要放到action里面
1)this.$store.dispatch('aupdataStu')
----先是要dispatch到action方法中,
2)

actions: {
    aupdataStu (context) {
      setTimeout(() => {
        context.commit('updataStu')
      }, 1000)
    }
  },

注意:这里区别于getters和mutations中的方法是,actions里方法的参数是context,而不是state,context拿到的是store对象

因为在actions里面并不是直接的操作state值,对state进行修改的操作还是要放在mutations里面,只不过这里是多一步

3)

updataStu (state) {
      Vue.set(state.students[0], 'email', '2291230083@qq.com')
    },

----------------如果此时我有个需求是需要在修改信息成功之后,然后提示修改信息成功,此时我可以让dipatch方法携带一个对象,对象中包含着需要传递的参数,还有一个回调函数

btnClick5 () {
      this.$store.dispatch('aupdataStu', {
        message: '我是携带的信息',
        success () {
          console.log('修改成功')
        }
      })
    }

之后在commit之后,再调用success回调

aupdataStu (context, payload) {
      setTimeout(() => {
        context.commit('updataStu')
        console.log(payload.message)
        payload.success()
      }, 1000)
    }

**这里有一个启发:现在对象就可以视为是一个存储数据的结构,它里面可以存放各种数据,当我们需要各种参数的时候,就可以把这些都放在一个对象里进行传递 **

但是上面这种方式不够优雅

我们可以使用promise来封装异步操作,之后再调用then来回调

actions: {
    aupdataStu (context) {
      new Promise((resolve, reject) => {
        setTimeout(() => {
          context.commit('updataStu')
          resolve('信息修改成功')
        }, 1000)
      }).then((data) => {
        console.log(data)
      })
    }
  }

更优雅的方式
这里是让dispatch返回的是一个promise对象,之后再调用promise对象的回调函数。

actions: {
    aupdataStu (context, payload) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          context.commit('updataStu')
          console.log(payload)
          resolve('111')
        }, 1000)
      })
    }
  }
 btnClick5 () {
      this.$store.dispatch('aupdataStu', '携带的信息').then(res => {
        console.log('信息修改成功')
        console.log(res)
      })
    }

12.modules的使用

1.使用modules里面的state

modules: {
    a: moudleA
  }
const moudleA = {
  state: {
    name: 'zhangsan'
  },
  mutations: {},
  getters: {},
  actions: {}
}

这里在去取module中name的时候,它会把modules中的a放在state中,此时a中没有state、mutations等这些属性了,会把state中的属性取出来当作自己的属性。所以我们在取得时候,是去state中去拿,而且此时也不需要再写a.state.name了,直接就是a.name.

<h2>{{$store.state.a.name}}</h2>

2.使用modules中的mutations,它在编译得时候是会把moudules的mutation中的方法和外面的方法都放在外面的mutations中
使用起来和之前一样。

3.使用modules中的getters,三种方式

 getters: {
    fullName (state) {
      return state.name + '111'
    },
    fullName1 (state, getters) {
      return getters.fullName + '222'
    },
    fullName2 (state, getters, rootState) {
      return getters.fullName1 + rootState.counter
    }

  },

其中rootState是外面state的引用,目的是可以拿到外面state的属性

 <h2>{{$store.getters.fullName}}</h2>
 <h2>{{$store.getters.fullName1}}</h2>
 <h2>{{$store.getters.fullName2}}</h2>

4.使用modules中的actions

 actions: {
    achangeName (context) {
      setTimeout(() => {
        context.commit('changeName')
      }, 1000)
    }
  }

注意:这里的context就不再是$store,也就是说modules中的actions方法只能调用modules中的mutations方法。

其中这里的context包含很多的属性

在这里插入图片描述

action {
	incrementSum({state, rootstate, commit}) {
		if((state.count + rootstate.count)%2 == 0) {
			commit('increment')
		}
	}
}

这里的incrementSum参数里面是对象的解构赋值,相当于是:

const context = {
	state:{},
	rootstate:{},
	commit:{}
}

const state = context.state
const rootstate = context.rootstate
const commit = context.commit

const {state, rootstate, commit} = context

13.store包内文件的结构:

如果把mutations、getters、actions都放在一个store中会非常的不方便维护:
所以就抽离出来,再导入导出,唯一state不用再放到外面

在这里插入图片描述

import Vuex from 'vuex'
import Vue from 'vue'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'
import moduleA from './modules/moduleA'

/**
 * 1.安装插件
 */
Vue.use(Vuex)

const state = {
  counter: 100,
  students: [
    {
      id: 1,
      name: 'guodong',
      age: 22
    },
    {
      id: 2,
      name: 'xiaozhang',
      age: 19
    },
    {
      id: 3,
      name: 'xiaohong',
      age: 30
    }
  ]
}
// 创建对象
const store = new Vuex.Store({
  state,
  mutations,
  actions,
  getters,
  modules: {
    a: moduleA
  }

})

export default store

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值