当前位置:首页 > 前端技术 > vue 项目实战 (vue全家桶之--- vuex)

vue 项目实战 (vue全家桶之--- vuex)

2022年08月05日 09:25:29前端技术6

老规矩先安装

npm install vuex --save

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

首先

vuex 是什么?

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

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

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

新建一个最简单的store

store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0,
    me: {
      name: 'huangenai',
      age: 22,
      sex: '女'
    },
      list: [{name: 'hea', age: 22}, {name: 'cpq', age: 23}]
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

main.js

import store from './store.js'

new Vue({
  el: '#app',
  router,
  store,//加这个
  components: { App },
  template: '<App/>'
})

State

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

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

在组件中获得state 中的count

this.$store.state.count

newvue.vue

<template>
    <div>
        new vue page
        <p>{{count}}</p>
    </div>
</template>

<script>
export default {
  name: 'newvue',
  data () {
    return {
    }
  },
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}
</script>

<style scoped>
</style>

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

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

在组件中引用

import { mapState } from 'vuex'
<template>
    <div>
        <p>{{count}}</p>
        <p>{{countPlusLocalState}}</p>
        <p>sex: {{sex}}</p>
        <p>age: {{myAge}}</p>
        <p>name: {{name}}</p>
    </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
  name: 'newvue',
  data () {
    return {
      localCount: 1
    }
  },
  computed: {
    ...mapState({
      // 箭头函数可使代码更简练
      sex: state => state.me.sex,
      myAge: state => state.me.age,
      name: state => state.me.name,
      // 传字符串参数 'age' 等同于 `state => state.age`
      count: 'count',
      // 为了能够使用 `this` 获取局部状态,必须使用常规函数
      countPlusLocalState (state) {
        return state.count + this.localCount
      }
    })
  }
}
</script>

<style scoped>
</style>

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

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

Mutation

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

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

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

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

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count ++
    }
  }
})

那么如何调用increment呢??

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

this.$store.commit('increment')

我们还可以传入参数

// ...
mutations: {
  increment (state, n) { this.$state.count = n } }

store.commit('increment', 10)

传入一个对象

mutations: {
  increment (state, data) { state.count += data.count } }
store.commit('increment', { count: 10 })

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

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

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

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

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

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

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

store.js

...
mutations: {
    increment (state) {
      state.count++
    },
    setWeight (state) {
      Vue.set(state.me, 'weight', '45kg')
    },
    setHeight (state) {
      state.me = { ...state.me, height: '156cm' }
    }
 }

newvue.vue 中调用

...  
methods: { setWeight () { this.$store.commit('setWeight') alert(JSON.stringify(this.$store.state.me)) }, setHeight () { this.$store.commit('setHeight') alert(JSON.stringify(this.$store.state.me)) } }

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

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

mutation-types.js

export const SET_WEIGHT = 'SET_WEIGHT'
export const SET_HEIGHT = 'SET_HEIGHT'

store.js

import * as types from './metations-types'
  ...
  mutations: {
    increment (state) {
      state.count++
    },
    [types.SET_WEIGHT] (state) {
      Vue.set(state.me, 'weight', '45kg')
    },
    [types.SET_HEIGHT] (state) {
      state.me = { ...state.me, height: '156cm' }
    }
  }

newvue.vue

....
  methods: {
    setWeight () {
      this.$store.commit(types.SET_WEIGHT)
      alert(JSON.stringify(this.$store.state.me))
    },
    setHeight () {
      this.$store.commit(types.SET_HEIGHT)
      alert(JSON.stringify(this.$store.state.me))
    }
  }

 

state中有mapState, Mutations中也有mapMutations

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

newvue.vue

先引用

import { mapMutations } from 'vuex'
...
    setWeight () {
      this.$store.commit(types.SET_WEIGHT)
      alert(JSON.stringify(this.$store.state.me))
    },
    setHeight () {
      this.$store.commit(types.SET_HEIGHT)
      alert(JSON.stringify(this.$store.state.me))
    },
    ...mapMutations([
      'increment'
      // 将 `this.increment()` 映射为 this.$store.commit('increment')`
    ])
  }

 getter

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

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

比如store 中的state 中的list 

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

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

store.js

export default new Vuex.Store({
  state: {
    ...
    list: [{name: 'hea', age: 22}, {name: 'cpq', age: 23}]
  },
  mutations: {
   ...
  },
  getters: {
    ageFilter: state => {
      return state.list.filter(item => item.age>=23)
    }
  }
})

newvue.vue

....
computed: {
    list () {
      return this.$store.getters.ageFilter
    }
  }

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

例子

... 
getters: {
    ageFilter: state => {
      return state.list.filter(item => item.age >= 23)
    },
    listCount (state,getters){
        return getters.ageFilter.length
    }
}

newvue.vue中调用

...
computed: {
    ...
    listCount () {
      return this.$store.getters.listCount
    }
  }

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

store.js

...
getters: {
    ....
    getName: (state) => (name) => {
      return state.list.find(item => item.name === name)
    }
  }

newvue.vue

....
computed: {
.... listbyName () { return this.$store.getters.getName('cpq') } }

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

newvue.vue

import { mapGetters } from 'vuex'
  computed: {
   ....
    // listCount () {
    //   return this.$store.getters.listCount
    // },
    ...mapGetters([
      'listCount'
    ])
  }

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

Action

其实跟上述的mutation很相似。

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

store.js

export default new Vuex.Store({
  state: {
    ...
  },
  mutations: {
    ...
  },
  getters: {
    ...
  },
  actions: {
    setWeight ({commit}) {
      commit(types.SET_WEIGHT)
    }
  }

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

newvue.vue

...  
methods: {
    ...
    setWeight () {
      this.$store.dispatch('setWeight')
    }
}

同样action 也支持传参数

action.js

export default new Vuex.Store({
  state: {
    count: 0,
    ...
  },
  mutations: {
    increment (state,count) {
      state.count = count
    },
    ...
  },
  getters: {
    ...
  },
  actions: {
    ...
    setCount ({commit},data) {
      commit('increment',data.count)
    }
  }
})

newvue.vue

methods: {
    ...
    setCount () {
      this.$store.dispatch('setCount', {count: 123})
} }

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

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

action可以包含异步函数。

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

import api from '../api'

... 
actions: {
  login ({commit}, payload) => {
  return new Promise((resolve, reject) => {
    api.login(payload, userToken => {
      if (userToken && userToken.accessToken) {
        commit(types.LOGIN, userToken)
        resolve(userToken)
      } else {
        reject()
      }
    })
  })
}

调用

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

同样action也有辅助函数 mapActions

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
  }
}

你还可以action中相互调用

actions: {
    ...
    setCountA ({commit},count) {
      commit('increment', count)
    },
    setCountB ({commit},data) {
      dispatch('setCountA',data.count)
    }
}

  

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

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

作者:huangenai
来源链接:https://www.cnblogs.com/huangenai/p/9736748.html

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/front/17548.html

标签: vue
分享给朋友:

“vue 项目实战 (vue全家桶之--- vuex)” 的相关文章

【Vue】详解Vue组件系统

【Vue】详解Vue组件系统

本文提纲:1.Vue渲染的两大基础方式 2.组件的局部注册和全局注册 3. Vue中的props数据流 4.Vue的自定义事件 5. Slot的使用   Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根...

【vue】Vue中添加$alert的messageBox消息弹出框,进行换行、空格等html渲染

出现情况: 在Vue中 $alert的messageBox 无法直接通过正则表达式进行来进行换行和缩进解决方式: dangerouslyUseHTMLString 是否将 message 属性作为 HTML 片段处理 boolean — false this.$alert(...

Vue的生命周期的详解

Vue的生命周期的详解

Vue的生命周期 Vue的生命周期是每个使用Vue框架的前端人员都需要掌握的知识,以此作为记录。 Vue的生命周期就是vue实例从创建到销毁的全过程,也就是new Vue() 开始就是vue生命周期的开始。Vue 实例有⼀个完整的⽣命周期,也就是从...

用HBuilderX 打包 vue 项目 为 App 的步骤

用HBuilderX 打包 vue 项目 为 App 的步骤

用HBuilderX 打包 vue 项目 为 App 的步骤 首先打包你的 vue 项目 生成 dist 文件夹,教程请移步  https://www.cnblogs.com/taohuaya/p/...

dotnetcore+vue+elementUI 前后端分离---支持前端、后台业务代码扩展的快速开发框架

dotnetcore+vue+elementUI 前后端分离---支持前端、后台业务代码扩展的快速开发框架

Document 框架采用dotnetcore+vue+elementUI 前后端分离,并且支持前端、后台代码业务动态扩展,框架内置了一套有着20多种属性配置的代码生成器,可灵活配置生成的代码,代码生成器界面配置完成即可生成单表/主从表的增、删、改、查、导入、导出、上传、审核基础...

脚手架vue-cli和@vue/cli的搭建及区别

脚手架vue-cli和@vue/cli的搭建及区别

vue-cli与@vue/cli vue脚手架版本目前有2,3,4.不管搭建哪个版本的脚手架,首先都需要安装node. node的安装 node的安装我们可以直接去node官网(http://nodejs.cn/)下载安装,node安装...

Vue中自定义标签及其使用

Vue中自定义标签及其使用

Vue中自定义标签及其使用 问题 需求 自定义 创建组件的vue文件 编辑组件 使用 导入...

vue.js快速搭建图书管理平台

vue.js快速搭建图书管理平台

上一期简单讲解了vue的基本语法,这一次我们做一个小项目,搭建一个简单的图书管理平台,能够让我们更深刻的理解这门语言的妙用。   前  言 上一期简单讲解了vue的基本语法,这一次我们做一个小项目,搭建一个简单的图书管理平台,能够...

vue中axios的封装

vue中axios的封装

https://juejin.im/post/5b55c118f265da0f6f1aa354 掘金的网址(很好) 一、axios的封装 在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promi...

如何搭建一个vue项目

如何搭建一个vue项目

一、安装node环境   1、下载地址为:https://nodejs.org/en/   2、检查是否安装成功:如果输出版本号,说明我们安装node环境成功      3、为了提高我们的效率,可以使用淘宝的镜像:http://npm.taobao.org/...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。