博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
④Vuex基本用法
阅读量:3966 次
发布时间:2019-05-24

本文共 7961 字,大约阅读时间需要 26 分钟。

Vuex


本人是个新手,写下博客用于自我复习、自我总结。

如有错误之处,请各位大佬指出。
学习资料来源于:尚硅谷


vuex 是什么

  1. github 站点:
  2. 在线文档:
  3. 简单来说: 对 vue 应用中多个组件的共享状态进行集中式的管理(读/写)

现在先写个vue版的代码,之后来看看vuex会是什么样。

main.js

/* 入口JS */import Vue from 'vue'import App from './App.vue'/* eslint-disable no-new */new Vue({
el: '#app', components: {
App}, // 映射组件标签 template: '
' // 指定需要渲染到页面的模板})

App.vue

状态自管理应用

  1. state: 驱动应用的数据源(就相当于上面代码中的data,count)
  2. view: 以声明方式将 state 映射到视图(就相当于上面代码中的template部分)
  3. actions: 响应在 view 上的用户输入导致的状态变化(包含 n 个更新状态的函数)
    在这里插入图片描述
    即:在模板界面上(View),通过事件触发某个Actions函数,再去修改状态数据(State),然后状态数据再去让界面(View)更新显示。

多组件共享状态的问题

  1. 多个视图依赖于同一状态
  2. 来自不同视图的行为需要变更同一状态
  3. 以前的解决办法
    a. 将数据以及操作数据的行为都定义在父组件
    b. 将数据以及操作数据的行为传递给需要的各个子组件(有可能需要多级传递)
    c. 但是这样做只能处理简单的情况,更复杂的情况比较棘手,比如更多路由。
  4. vuex 就是用来解决这个问题的

vuex 核心概念和 API

在这里插入图片描述

state

  1. vuex 管理的状态对象
  2. 它应该是唯一的
const state = {
xxx: initValue}

mutations

  1. 包含多个直接更新 state 的方法(回调函数)的对象
  2. 谁来触发: action 中的 commit(‘mutation 名称’)
  3. 只能包含同步的代码, 不能写异步代码
const mutations = {
yyy (state, {
data1}) {
// 更新 state 的某个属性 }}

actions

  1. 包含多个事件回调函数的对象
  2. 通过执行: commit()来触发 mutation 的调用, 间接更新 state
  3. 谁来触发: 组件中: $store.dispatch(‘action 名称’, data1)
  4. 可以包含异步代码(定时器, ajax)
const actions = {
zzz ({
commit, state}, data1) {
commit('yyy', {
data1}) }}

getters

  1. 包含多个计算属性(get)的对象
  2. 谁来读取: 组件中: $store.getters.xxx
const getters = {
mmm (state) {
return ... }}

modules

  1. 包含多个 module
  2. 一个 module 是一个 store 的配置对象
  3. 与一个组件(包含有共享数据)对应

向外暴露 store 对象

export default new Vuex.Store({
state, mutations, actions, getters})

组件中

import {
mapState, mapGetters, mapActions} from 'vuex' export default {
computed: {
...mapState(['xxx']), ...mapGetters(['mmm']), } methods: mapActions(['zzz'])}{
{
xxx}} {
{
mmm}} @click="zzz(data)"

映射 store

import store from './store' new Vue({
store})

store 对象

  1. 所有用 vuex 管理的组件中都多了一个属性$store, 它就是一个 store 对象
  2. 属性:
    state: 注册的 state 对象
    getters: 注册的 getters 对象
  3. 方法:
    dispatch(actionName, data): 分发调用 action

vuex简例

项目结构:(对最开始的代码进行修改)

在这里插入图片描述

首先安装 npm i --save vuex

store.js

/*vuex最核心的管理对象store */import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)/*相当于data对象的状态对象 */const state = {
count: 0 // 指定初始化数据}/*包含了n个直接更新状态的方法的对象 */const mutations = {
INCREMENT (state) {
state.count++ }, DECREMENT (state) {
state.count-- }}/*包含了n个间接更新状态的方法的对象 */const actions = {
//增加的action increment ({
commit}) {
// 提交一个mutation请求 commit('INCREMENT') }, //减少的action decrement ({
commit}) {
// 提交一个mutation请求 commit('DECREMENT') }, //带条件的action incrementIfOdd ({
commit, state}) {
if(state.count%2===1) {
// 提交一个mutation请求 commit('INCREMENT') } }, //异步的action incrementAsync ({
commit}) {
//在action中直接就可以执行异步代码 setTimeout(() => {
// 提交一个mutation请求 commit('INCREMENT') }, 1000) },}/*包含多个getter计算属性的对象 */const getters = {
evenOrOdd (state) {
// 当读取属性值时自动调用并返回属性值 return state.count%2===0 ? '偶数' : '奇数' }}/*向外暴露 store 对象 */export default new Vuex.Store({
state, //状态对象 mutations, //包含多个更新state函数的对象 actions, //包含多个对应事件回调函数的对象 getters //包含多个getter计算属性函数的对象})

main.js

/*入口js */import Vue from 'vue'import Counter from './Counter.vue'import store from './store'new Vue({
el: '#app', components: {
Counter }, template: '
', store // 注册vuex的store: 所有组件对象都多一个属性$store})

Counter1.vue(原始版本,Counter为对Counter1的改进版,在之后)

它的整体思路就是:

首先建一个store.js,用来存放Vuex相关内容,在其中:
①引入Vuex

import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)

②向外暴露store对象(基本上每次都会暴露这几个对象)

export default new Vuex.Store({
state, //状态对象 mutations, //包含多个更新state函数的对象 actions, //包含多个对应事件回调函数的对象 getters //包含多个getter计算属性函数的对象})

③格式比较固定,暴露之后,肯定要对以上所有对象进行实现:

/*相当于data对象的状态对象 */const state = {
//初始化数据 count: 0 }/*包含了n个直接更新状态的方法的对象 */const mutations = {
INCREMENT (state) {
state.count++ }}/*包含了n个间接更新状态的方法的对象 */const actions = {
increment ({
commit}) {
// 提交一个mutation请求 commit('INCREMENT') }, incrementIfOdd ({
commit, state}) {
if(state.count%2===1) {
// 提交一个mutation请求 commit('INCREMENT') } }}/*包含多个getter计算属性的对象 */const getters = {
evenOrOdd (state) {
// 当读取属性值时自动调用并返回属性值 return state.count%2===0 ? '偶数' : '奇数' }}

那么这里面最基本的用法就是,先在组件中调用actions中的方法,然后在actions中去调用mutations中的方法,用来直接对state数据进行改变(更新状态)。

全部都弄好后,即然要在组件中使用,就要想办法创建个store对象,即在main.js中:

①导入组件和store

import Vue from 'vue'import Counter from './Counter.vue'import store from './store'

②注册vuex的store,这样一来所有组件对象都会多一个属性$store,这样之后就能使用store中的方法了。

new Vue({
el: '#app', components: {
Counter }, template: '
', store // 注册vuex的store: 所有组件对象都多一个属性$store})

注册好之后,就要考虑如何去使用了,进入组件中。因为上面说到,我们在组件中调用actions中的方法,在actions中设置时会去帮我们调用mutations中的方法,所以在组件中,使用store对象目前只涉及到三种用法:

this.$store.state.count
this.$store.getters.evenOrOdd
this.$store.dispatch('increment')
分别可以调用store对象中的state、getters和actions。注意调用actions用的是dispatch,这个看上面的图就发现了,规定用的就是dispatch。

这样一来就可以连接起每个部分了。

在上面还说到有个简化版,Counter.vue:

因为store里的每个对象可能会有多个方法,我们一个一个去调用还是很麻烦的,现在就可以一次性全部导入。

首先要引入import {mapState, mapGetters, mapActions} from 'vuex',然后使用。分别为:
...mapState([])
...mapGetters([])
...mapActions([])
注意这时候调用actions,可不是dispatch了。

最后再通过结构图理解一下:

在这里插入图片描述
vuex里有四个结构,state、mutations、actions、getters。
更新state的是mutations、用state进行计算的是getters。
操作mutations的是actions。
这四个都是对象。
state里面包含的数据原本是从vue组件中转移过来的。
而组件要想获取到state里的数据,有四种方式:
$store.statemapState()
$store.gettersmapGetters()

在vue中对标签 / 按钮进行操作,分发事件,触发action调用,用到的就是dispatch()mapActions()。action不能直接对数据进行操作,所以去请求mutation,用到的就是commit()。这时候可能需要获取数据后再commit,所以就涉及到后台backend,用到的就是ajax请求,也就是说在vuex里可以直接进行异步操作。而到了mutation就可以直接更新状态。mutation里还有个开发工具devtool,专门用来监视mutation。


在最后再说几个问题:在正常项目中,vuex的四个结构,即store.js中的四个对象包含的数据 / 方法可能会比较多,都放在store.js中,不太好处理(当然都放在一起也行,还是需要看习惯)。所以,我们可以把它们分开来存放。

在这里插入图片描述
index.js:

/*vuex核心管理模块store对象 */import Vue from 'vue'import Vuex from 'vuex'import state from './state'import mutations from './mutations'import actions from './actions'import getters from './getters'Vue.use(Vuex)export default new Vuex.Store({
state, mutations, actions, getters})

state.js

/*状态对象模块 */export default {
todos: []}

getters.js

/*包含n个基于state的getter计算属性方法的对象模块 */export default {
// 总数量 totalSize (state) {
return state.todos.length }}

actions.js

/*包含n个用于间接更新状态的方法的对象模块 */import {
ADD_TODO, DELETE_TODO} from './mutation-types'export default {
addTodo ({
commit}, todo) {
// 提交一个comutation请求 commit(ADD_TODO, {
todo}) // 传递给mutation的是一个包含数据的对象 }, deleteTodo ({
commit}, index) {
commit(DELETE_TODO, {
index}) }}

mutation-types.js

/*包含n个mutation名称常量 */export const ADD_TODO = 'add_todo' // 添加todoexport const DELETE_TODO = 'delete_todo' // 删除todo

mutations.js

/*包含n个用于直接更新状态的方法的对象模块 */import {
ADD_TODO, DELETE_TODO} from './mutation-types'export default {
[ADD_TODO] (state, {
todo}) {
// 方法名不是ADD_TODO, 而是add_todo state.todos.unshift(todo) }, [DELETE_TODO] (state, {
index}) {
state.todos.splice(index, 1) }}

还有就是,我们在main.js里,之前我们做的操作,需要映射组件标签+指定渲染到页面的模板:

/*入口JS */import Vue from 'vue'import App from './App.vue'import store from './store'/* eslint-disable no-new */new Vue({
el: '#app', components: {
App}, // 映射组件标签 template: '
', // 指定需要渲染到页面的模板 store})

有一个简便写法:

/*入口JS */import Vue from 'vue'import App from './App.vue'import store from './store'/* eslint-disable no-new */new Vue({
el: '#app', render: h => h(App), //简化 store })

这个render是一个渲染函数,它完整写是这样的:

render: function(createElement){
return createElement(App) //返回的是
},

就相当于它会返回一个App标签,然后插入到el里就可以了。

转载地址:http://dlyki.baihongyu.com/

你可能感兴趣的文章
NET - NET Core中使用Log4net输出日志到数据库中去
查看>>
NET - NET Core 迁移nuget包缓存到指定位置
查看>>
Spring - SpringBoot 集成 swagger2
查看>>
SQL - 深入理解MySQL索引之B+Tree
查看>>
SQL - 数据库索引原理,及MySQL索引类型
查看>>
Spring - Dubbo的实现原理
查看>>
Spring - Dubbo 扩展点详解
查看>>
Spring - Hystrix原理与实战
查看>>
Spring - Sentinel 原理 全解析
查看>>
Spring - 比较Sentinel和Hystrix
查看>>
Spring - Nacos 服务注册与发现原理分析
查看>>
Spring - Nacos 配置中心原理分析
查看>>
Spring - Nacos 配置实时更新原理分析
查看>>
Android开发MVP模式(解决了View和Model的耦合)
查看>>
Android网络框架Volley(实战篇)
查看>>
Android 常见分辨率(mdpi、hdpi 、xhdpi、xxhdpi )及屏幕适配注意事项
查看>>
Android 5.0学习之感想篇(含Demo)
查看>>
ViewPagerindicator 源码解析
查看>>
HoloGraphLibrary 源码解析
查看>>
CircularFloatingActionMenu 源码解析
查看>>