经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » HTMLCSS » CSS » 查看文章
vue 项目实战 (vue全家桶之--- vuex)
来源:cnblogs  作者:huangenai  时间:2018/10/8 8:47:07  对本文有异议

老规矩先安装

  1. npm install vuex --save

在看下面内容之前 你应该大概的看了一边vuex官方的文档对vuex有个大概对了解

首先

vuex 是什么?

vuex 是属于vue中的什么,它在项目中扮演着一个什么样的角色,起到什么作用,在项目中我是否要用到vuex。

官方文档对vuex的解读是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。

如果你是在开发一个大型的应用程序,组件与组件之间,兄弟组件之间,或者说多层嵌套组件之间,你是无法传递数据的。子父组件之间,也只是说通过事件保持数据的一致性,也是很繁琐的,会变得很不好管理。而vuex就是为了解决这样的问题,把组件的共享状态抽取出来,以一个全局单例模式管理。组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为,而且代码将会变得更结构化且易维护。

新建一个最简单的store

store.js

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. Vue.use(Vuex)
  4. export default new Vuex.Store({
  5. state: {
  6. count: 0,
  7. me: {
  8. name: 'huangenai',
  9. age: 22,
  10. sex: '女'
  11. },
      list: [{name: 'hea', age: 22}, {name: 'cpq', age: 23}]
  1. },
  2. mutations: {
  3. increment (state) {
  4. state.count++
  5. }
  6. }
  7. })

main.js

  1. import store from './store.js'
  2. new Vue({
  3. el: '#app',
  4. router,
  5. store,//加这个
  6. components: { App },
  7. template: '<App/>'
  8. })

State

驱动应用的数据源,组件之间共享的状态。

上面代码中的 count 就是一个共享的数据,me 也是一个共享的数据对象。

在组件中获得state 中的count

  1. this.$store.state.count

newvue.vue

  1. <template>
  2. <div>
  3. new vue page
  4. <p>{{count}}</p>
  5. </div>
  6. </template>
  7.  
  8. <script>
  9. export default {
  10. name: 'newvue',
  11. data () {
  12. return {
  13. }
  14. },
  15. computed: {
  16. count () {
  17. return this.$store.state.count
  18. }
  19. }
  20. }
  21. </script>
  22.  
  23. <style scoped>
  24. </style>

为什么要写在computed 里面呢,而不是写在data里面,因为当state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM,如果你不理解可以先去看看computed

当一个组件要引用到多个状态的时候 ,一个个写是不是很累。不用担心,我们有mapState 辅助函数帮助我们生成计算属性。

在组件中引用

  1. import { mapState } from 'vuex'
  1. <template>
  2. <div>
  3. <p>{{count}}</p>
  4. <p>{{countPlusLocalState}}</p>
  5. <p>sex: {{sex}}</p>
  6. <p>age: {{myAge}}</p>
  7. <p>name: {{name}}</p>
  8. </div>
  9. </template>
  10.  
  11. <script>
  12. import { mapState } from 'vuex'
  13. export default {
  14. name: 'newvue',
  15. data () {
  16. return {
  17. localCount: 1
  18. }
  19. },
  20. computed: {
  21. ...mapState({
  22. // 箭头函数可使代码更简练
  23. sex: state => state.me.sex,
  24. myAge: state => state.me.age,
  25. name: state => state.me.name,
  26. // 传字符串参数 'age' 等同于 `state => state.age`
  27. count: 'count',
  28. // 为了能够使用 `this` 获取局部状态,必须使用常规函数
  29. countPlusLocalState (state) {
  30. return state.count + this.localCount
  31. }
  32. })
  33. }
  34. }
  35. </script>
  36.  
  37. <style scoped>
  38. </style>

假设computed 里面还有别的数据,因为mapstate返回来的是一个对象所以我们这样写可以将数据混入

  1. computed: {
  2. localComputed () { /* ... */ },
  3. // 使用对象展开运算符将此对象混入到外部对象中
  4. ...mapState({
  5. // ...
  6. })
  7. }

Mutation

你说你想修改state的值,this.$store.state.count = 1 这样可不可以 no no no....  所以就有了Mutation。

切记Mutation 必须是同步函数!!!

想要修改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

在上面代码我们新建一个store里面下的 有一个increment,就可以实现修改state里面的count

  1. export default new Vuex.Store({
  2. state: {
  3. count: 0
  4. },
  5. mutations: {
  6. increment (state) {
  7. state.count ++
  8. }
  9. }
  10. })

那么如何调用increment呢??

调用 this.$store.commit(type)  类型叫increment 的 mutation。

  1. this.$store.commit('increment')

我们还可以传入参数

  1. // ...
  2. mutations: {
  3. increment (state, n) {
  4. this.$state.count = n
  5. }
  6. }

  1. store.commit('increment', 10)

传入一个对象

  1. mutations: {
  2. increment (state, data) {
  3. state.count += data.count
  4. }
  5. }
  1. store.commit('increment', {
  2. count: 10
  3. })

mutations可以修改store中的状态,但是并不是说随随便便修改的,比如说??状态是对象的时候,你突然重新赋值过去一个新对象,原来的属性没了,真怎么行。

Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。

比如 上面代码的 state 内有个对象me 我可以新增删除里面的属性吗,怎么操作呢。

最好就是一开始就定义好所有的属性。

如果你非要新增属性,也提供了方法。

1.     Vue.set(me, 'height','156cm')

2.    state.me = { ...state.me, height: '156cm' }

store.js

  1. ...
  2. mutations: {
  3. increment (state) {
  4. state.count++
  5. },
  6. setWeight (state) {
  7. Vue.set(state.me, 'weight', '45kg')
  8. },
  9. setHeight (state) {
  10. state.me = { ...state.me, height: '156cm' }
  11. }
  12. }

newvue.vue 中调用

  1. ...
    methods: {
  2. setWeight () {
  3. this.$store.commit('setWeight')
  4. alert(JSON.stringify(this.$store.state.me))
  5. },
  6. setHeight () {
  7. this.$store.commit('setHeight')
  8. alert(JSON.stringify(this.$store.state.me))
  9. }
  10. }

当mutations中的类型多了起来,我们在组件中要commit 某一个类型 还要去找 再复制过来 是不是很不好管理。

所以我们可以使用常量替代 mutation 事件类型,新建一个

mutation-types.js

  1. export const SET_WEIGHT = 'SET_WEIGHT'
  2. export const SET_HEIGHT = 'SET_HEIGHT'

store.js

  1. import * as types from './metations-types'
  2. ...
  3. mutations: {
  4. increment (state) {
  5. state.count++
  6. },
  7. [types.SET_WEIGHT] (state) {
  8. Vue.set(state.me, 'weight', '45kg')
  9. },
  10. [types.SET_HEIGHT] (state) {
  11. state.me = { ...state.me, height: '156cm' }
  12. }
  13. }

newvue.vue

  1. ....
  2. methods: {
  3. setWeight () {
  4. this.$store.commit(types.SET_WEIGHT)
  5. alert(JSON.stringify(this.$store.state.me))
  6. },
  7. setHeight () {
  8. this.$store.commit(types.SET_HEIGHT)
  9. alert(JSON.stringify(this.$store.state.me))
  10. }
  11. }

 

state中有mapState, Mutations中也有mapMutations

使用 mapMutations 辅助函数将组件中的 methods 映射为 this.$store.commit 调用

newvue.vue

先引用

  1. import { mapMutations } from 'vuex'
  1. ...
  2. setWeight () {
  3. this.$store.commit(types.SET_WEIGHT)
  4. alert(JSON.stringify(this.$store.state.me))
  5. },
  6. setHeight () {
  7. this.$store.commit(types.SET_HEIGHT)
  8. alert(JSON.stringify(this.$store.state.me))
  9. },
  10. ...mapMutations([
  11. 'increment'
  12. // 将 `this.increment()` 映射为 this.$store.commit('increment')`
  13. ])
  14. }

 getter

getter 又是什么 ,在store中。什么时候用到他。

上述我们可以用 this.$store.state.count 能拿到 store的state ,而getter 则是拿store中的计算属性。

比如store 中的state 中的list 

在项目中我们有多个组件需要通过过滤拿到list中 age 大于等于22的对象,如果没有getter 我们需要在每个组件中都要定义一个函数过滤好在返回值,或者抽出来一个公共的方法哪个组件需要的时候就导入这个方法,再进行调用,也是很麻烦的一件事。

在这里我们可以用到store 里的getter,并通过属性访问获得过滤后的数据

store.js

  1. export default new Vuex.Store({
  2. state: {
  3. ...
  4. list: [{name: 'hea', age: 22}, {name: 'cpq', age: 23}]
  5. },
  6. mutations: {
  7. ...
  8. },
  9. getters: {
  10. ageFilter: state => {
  11. return state.list.filter(item => item.age>=23)
  12. }
  13. }
  14. })

newvue.vue

  1. ....
  2. computed: {
  3. list () {
  4. return this.$store.getters.ageFilter
  5. }
  6. }

在getter中,Getter 也可以接受其他 getter 作为第二个参数。

例子

  1. ...
  2. getters: {
  3. ageFilter: state => {
  4. return state.list.filter(item => item.age >= 23)
  5. },
  6. listCount (state,getters){
  7. return getters.ageFilter.length
  1. }
  2. }

newvue.vue中调用

  1. ...
  2. computed: {
  3. ...
  4. listCount () {
  5. return this.$store.getters.listCount
  6. }
  7. }

通过方法访问,让getter返回一个函数,我们可以传值过去

store.js

  1. ...
  2. getters: {
  3. ....
  4. getName: (state) => (name) => {
  5. return state.list.find(item => item.name === name)
  6. }
  7. }

newvue.vue

  1. ....
    computed: {
    ....
  2. listbyName () {
  3. return this.$store.getters.getName('cpq')
  4. }
  5. }

getter 有mapGetters 辅助函数,将 store 中的 getter 映射到局部计算属性

newvue.vue

  1. import { mapGetters } from 'vuex'
  1. computed: {
  2. ....
  3. // listCount () {
  4. // return this.$store.getters.listCount
  5. // },
  6. ...mapGetters([
  7. 'listCount'
  8. ])
  9. }

在组件中,什么时候通过getter拿到store 状态,什么时候 直接拿state 想必都清楚了。

Action

其实跟上述的mutation很相似。

但是他不是直接修改state,在上面mutation说过,必须是同步函数。而Action则可以包含任意异步函数,action 是通过提交 mutation,而修改state。

store.js

  1. export default new Vuex.Store({
  2. state: {
  3. ...
  4. },
  5. mutations: {
  6. ...
  7. },
  8. getters: {
  9. ...
  10. },
  11. actions: {
  12. setWeight ({commit}) {
  13. commit(types.SET_WEIGHT)
  14. }
  15. }

Action 通过 this.$store.dispatch 方法触发

newvue.vue

  1. ...
  2. methods: {
  3. ...
  4. setWeight () {
  5. this.$store.dispatch('setWeight')
  6. }
  1. }

同样action 也支持传参数

action.js

  1. export default new Vuex.Store({
  2. state: {
  3. count: 0,
  4. ...
  5. },
  6. mutations: {
  7. increment (state,count) {
  8. state.count = count
  9. },
  10. ...
  11. },
  12. getters: {
  13. ...
  14. },
  15. actions: {
  16. ...
  17. setCount ({commit},data) {
  18. commit('increment',data.count)
  19. }
  20. }
  21. })

newvue.vue

  1. methods: {
  2. ...
  3. setCount () {
  4. this.$store.dispatch('setCount', {count: 123})
    }
  5. }

为什么要action 直接用mutation岂不更方便,为什么要通过action,又多了一步

因为mutation只是同步函数啊,在很多情况下我们要执行异步操作的。

action可以包含异步函数。

我们假设一个登录的功能,在action中支持异步函数,在mutation只能是同步函数,所以要用到action

  1. import api from '../api'
  2. ...
  3. actions: {
  4. login ({commit}, payload) => {
  5. return new Promise((resolve, reject) => {
  6. api.login(payload, userToken => {
  7. if (userToken && userToken.accessToken) {
  8. commit(types.LOGIN, userToken)
  9. resolve(userToken)
  10. } else {
  11. reject()
  12. }
  13. })
  14. })
  15. }

调用

  1. this.$store.dispatch('login', {username, password}).then(
  2. (res) => {
  3. }).catch()

同样action也有辅助函数 mapActions

  1. import { mapActions } from 'vuex'
  2. export default {
  3. // ...
  4. methods: {
  5. ...mapActions([
  6. 'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
  7. }
  8. }

你还可以action中相互调用

  1. actions: {
  2. ...
  3. setCountA ({commit},count) {
  4. commit('increment', count)
  5. },
  6. setCountB ({commit},data) {
  7. dispatch('setCountA',data.count)
  8. }
  9. }

  

此随笔乃本人学习工作记录,如有疑问欢迎在下面评论,转载请标明出处。

如果对您有帮助请动动鼠标右下方给我来个赞,您的支持是我最大的动力。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号