Vue-cli4——vuex

Vue-cli4——vuex

Day1



前言

此文章根据官方文档及些网络资料编写,仅供个人使用。

提示:以下是本篇文章正文内容,下面案例可供参考

一、介绍

它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

如果有多个组件的状态需要共享,都用同一个状态的时候,就需要vuex。例如:

  • 用户的登录状态、名称、头像、地理信息
  • 商品的收藏、购物车中的物品

二、各种状态

2.1 单界面的状态管理

  • State:不用多说,就是我们的状态。(你姑且可以当做就是data中的属性)

  • View:视图层,可以针对State的变化,显示不同的信息。(这个好理解吧?)

  • Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的改变。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ryIIrrOd-1605854623467)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201119162745025.png)]

计数器就是很简单的单界面管理,代码我就不放了,之前写过

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HUU7fzfQ-1605854623469)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201119162812959.png)]

2.2多界面的状态管理

多个页面用同一个状态,下面就是官方给出的图片。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JKP5dK7v-1605854623470)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201119161603117.png)]

new Promise((resolve, reject) => {
    setTimeout(() => {
      // 成功的时候调用resolve
      // resolve('Hello World')

      // 失败的时候调用reject
      reject('error message')
    }, 1000)
  }).then......

他希望你数据在这里面处理

.then((data) => {
    // 1.100行的处理代码
    console.log(data);
    console.log(data);
    console.log(data);
    console.log(data);
    console.log(data);
  }).catch((err) => {
    console.log(err);
  })

然后你要注意,网络请求成功的话会执行 resolve(‘Hello World’) 他会跳到then去执行,将里面的数据给到then

然后你要注意,网络请求失败的话会调用reject(‘error message’),他会跳到catch去执行,将里面的数据给到catch

2.3 三种状态

pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。

fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()

reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SWq2EIM2-1605854623474)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201119141406232.png)]

2.4 另外一种状态的处理形式

err写在then的里面

  new Promise((resolve, reject) => {
    setTimeout(() => {
      // resolve('Hello Vuejs')
      reject('error message')
    }, 1000)
  }).then(data => {
    console.log(data);
  }, err => {
    console.log(err);
  })

三、链式调用

第一种办法

    // wrapped into
    // 网络请求: aaa -> 自己处理(10行)
    // 处理: aaa111 -> 自己处理(10行)
    // 处理: aaa111222 -> 自己处理
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('aaa')
      }, 1000)
    }).then(res => {
      // 1.自己处理10行代码
      console.log(res, '第一层的10行处理代码');

      // 2.对结果进行第一次处理
      return new Promise((resolve, reject) => {
        // resolve(res + '111')
        reject('err')
      })
    }).then(res => {
      console.log(res, '第二层的10行处理代码');

      return new Promise(resolve => {
        resolve(res + '222')
      })
    }).then(res => {
      console.log(res, '第三层的10行处理代码');
    }).catch(err => {
      console.log(err);
    })

第二种办法


    // new Promise(resolve => resolve(结果))简写
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('aaa')
      }, 1000)
    }).then(res => {
      // 1.自己处理10行代码
      console.log(res, '第一层的10行处理代码');

      // 2.对结果进行第一次处理
      return Promise.resolve(res + '111')
    }).then(res => {
      console.log(res, '第二层的10行处理代码');

      return Promise.resolve(res + '222')
    }).then(res => {
      console.log(res, '第三层的10行处理代码');
    })

第三种办法,省略掉Promise.resolve

    // 省略掉Promise.resolve
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('aaa')
      }, 1000)
    }).then(res => {
      // 1.自己处理10行代码
      console.log(res, '第一层的10行处理代码');

      // 2.对结果进行第一次处理
      return res + '111'
    }).then(res => {
      console.log(res, '第二层的10行处理代码');

      return res + '222'
    }).then(res => {
      console.log(res, '第三层的10行处理代码');
    })

第四种办法

    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('aaa')
      }, 1000)
    }).then(res => {
      // 1.自己处理10行代码
      console.log(res, '第一层的10行处理代码');

      // 2.对结果进行第一次处理
      // return Promise.reject('error message')
      throw 'error message'
    }).then(res => {
      console.log(res, '第二层的10行处理代码');

      return Promise.resolve(res + '222')
    }).then(res => {
      console.log(res, '第三层的10行处理代码');
    }).catch(err => {
      console.log(err);
    })
  </script>
  • State:状态,保存共享状态的地址

  • Vue Components:组件

  • Actions:是做异步操作的,发送网络请求

  • Backend:后端

  • Mutations:方法

  • Devtools:会记录你每次修改State状态

修改State必须通过 Mutations 修改,这样就可以利用 Devtools 记录每一步修改状态。

四、Vuex简单的实例

简单的计数器

App.vue

<template>
  <div>
    <h2>hello world</h2>
    <h2>{{ message }}</h2>
    <button @click="addition">+</button>
    <button @click="subtraction">-</button>
    {{ $store.state.counter }}
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      message: "HELLO"
    }
  },
  methods: {
    addition() {
      this.$store.commit('increment')
    },
    subtraction() {
      this.$store.commit('decrement')
    },
  },
}
</script>

store/index.js

import {createStore} from 'vuex'

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


const store = new Vuex.Store({
  state: {
    counter: 0,
  }
  mutations: {
    increment(state) {
      state.counter++
    },
    decrement(state) {
      state.counter--
    },
  },
  actions: {},
  modules: {},
})

export default store

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y5PsBT1A-1605854623476)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120103439629.png)]

五、Getters

有些时候我们需要对state中的一些状态进行操作,这个时候就需要用到Getters了

5.1 将couter的数量乘以2

我们在实例的基础上添加一些代码,

store/index.js

  getters: {
    powerCounter: state => {
      return state.counter * 2
    },
  },

App.vue

		powerCounter
    <h2>{{ $store.getters.powerCounter }}</h2>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nhqGoLwC-1605854623476)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120104255259.png)]

5.2 参数和传递参数

store/index.js

  state: {
    counter: 0,
    students: [
      {id: 110, name: 'why', age: 18},
      {id: 111, name: 'kobe', age: 24},
      {id: 112, name: 'james', age: 30},
      {id: 113, name: 'curry', age: 10}
    ]
  },
  getters: {
    moreAgeStu(state) {
      return age => {
        return state.students.filter(s => s.age > age)
      }
    },
    moreAgeStuLength: (state, getters) => {
      return getters.moreAgeStu.length
    }
  },

App.vue

    more20stuLength
    <h2> {{ $store.getters.moreAgeStuLength }} </h2>
    moreAgeStu
    <h2> {{ $store.getters.moreAgeStu(19) }} </h2>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WrGNww75-1605854623477)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120104740851.png)]

六、Mutations

更新Vuex的store状态的更新唯一方式:提交Mutations

一般Mutation是带参数的state

而从Vue里面提交的时候是用commit

6.1 携带参数

store/index.js

  mutations: {
    increment(state) {
      state.counter++
    },
    decrement(state) {
      state.counter--
    }
  },

App.vue

    <button @click="addCount(5)">+5</button>
    <button @click="addStudent">添加学生</button>
<script>

    addCount(count) {
      this.$store.commit('incrementCount', 5)
    },
    addStudent() {
      const stu = {id:114, name:'alan', age: 30}
      this.$store.commit('addStudent', stu)
    }
  },
}
</script>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R0PGkZMx-1605854623477)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120113059191.png)]

6.2 另一种提交方式

这种提交方式,提交上去的一种对象,如果要提取数据需要payload.count

App.vue

    addCount(count) {
      // this.$store.commit('incrementCount', 5)

      this.$store.commit({
        type: 'incrementCount',
        count
      })
    },

store/index.js

    incrementCount: (state, payload) => {
      console.log(payload);
    },

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D3WcSAJm-1605854623478)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120114134613.png)]

state.info['address'] = '嘻嘻嘻'
delete state.info.age

响应式的前提是,已经在state里面定义好了

6.3 定义常量

我们在mutations-types.js里面定义一个常量,在其他文件里面用就可以

store/index.js

import {
  INCREMENT
} from "@/store/mutations-types

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

App.vue

import {
  INCREMENT
} from "@/store/mutations-types";

  methods: {
    addition() {
      this.$store.commit(INCREMENT)
    },
  }

在mutation里面的所有代码,都不可以是异步的(setTimeout),必须是同步

七、Action

类似Mutation,但是里面是可以进行异步操作的,类似网络请求。

action本身可以使用Promise,进行异步操作

一般action是带参数的context

而从Vue里面提交的时候是用dispatch

7.1 简单实现

store/index.js

  mutations: {
    updateInfo(state) {
      // state.info['address'] = '嘻嘻嘻'
      // delete state.info.age
      state.info.name = 'TETETE '
    }
  },
	actions: {
    aUpdateInfo(context, payload) {
      setTimeout(()=>{
        // 要注意,这里的updateInfo是指上面mutations里面的mutations
        context.commit('updateInfo')
        console.log(payload.message);
        payload.success()
      },1000)
    }
  },

App.vue

    updataInfo() {
      this.$store.dispatch('aUpdateInfo', {
        message: '我是携带的信息',
        success: () => {
          console.log('已经完成')
        }
      })
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OV2O3XRS-1605854623479)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120125552927.png)]

点击按钮的一秒后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xWHyBggg-1605854623480)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120125607355.png)]

7.2 使用Promise

store/index.js

  mutations: {
    updateInfo(state) {
      // state.info['address'] = '嘻嘻嘻'
      // delete state.info.age
      state.info.name = 'TETETE '
    }
  },
	actions: {
    aUpdateInfo(context, payload) {
      return new Promise((resolve, reject) => {
        setTimeout(()=>{
          // 要注意,这里的updateInfo是指上面mutations里面的mutations
          context.commit('updateInfo')
          console.log(payload);
          resolve('123321')
        },1000)
      })
    }
  },

App.vue

    updataInfo() {
      this.$store.dispatch('aUpdateInfo',
          '我是携带的信息').then(res => {
        console.log('里面完成了提交');
        console.log(res)
      })
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4OKQZbyi-1605854623480)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120131012696.png)]

八、Modules

这是一个模块,每一个模块有自己的state、mutations、actions、getters等。

Vue实例找mutations,会先去store里面找,找不到在去模块找

8.1 实例

rootState,是指父的State

store/index.js

const moduleA = {
  state: {
    name: 'zhangsan'
  },
  mutations: {
    updateName(state, payload) {
      state.name = payload
    }
  },
  getters: {
    fullname(state) {
      return state.name + '11111'
    },
    fullname2(state, getters) {
      return getters.fullname + '2222'
    },
    fullname3(state, getters, rootState) {
      return getters.fullname2 + rootState.counter
    }
  },
  actions: {
    aUpdateName(context) {
      console.log(context);
      setTimeout(() => {
        context.commit('updateName', 'wangwu')
      }, 1000)
    }
  }
}

// 在store里面添加
  modules: {
    a: moduleA
  },

App.vue

    <h2>----------App内容: modules中的内容----------</h2>
    <h2>{{$store.state.a.name}}</h2>
    <button @click="updateName">修改名字</button>
    <h2>{{$store.getters.fullname}}</h2>
    <h2>{{$store.getters.fullname2}}</h2>
    <h2>{{$store.getters.fullname3}}</h2>
    <button @click="asyncUpdateName">异步修改名字</button>
// 在Vue实例里面
    updateName() {
      this.$store.commit('updateName', 'lisi')
    },
    asyncUpdateName() {
      this.$store.dispatch('aUpdateName')
    }

九、分离式目录结构

store
	modules
		moduleA.js
	actions.js
	getters.js
	index.js
	mutations.js
	mutations-types.js

重构代码例如action.js:

export default {
  aUpdateInfo(context, payload) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        context.commit('updateInfo')
        console.log(payload);
        resolve('123321')
      }, 1000)
    })
  }
}

我们利用export default {}将内容导出

在index.js导入

import moduleA from "@/store/modules/moduleA";
import actions from "@/store/actions";
import mutations from "@/store/mutations";
import getters from "@/store/getters";

const state = {
  counter: 0,
  students: [
    {id: 110, name: 'why', age: 18},
    {id: 111, name: 'kobe', age: 24},
    {id: 112, name: 'james', age: 30},
    {id: 113, name: 'curry', age: 10}
  ],
  info: {
    name: 'kobe',
    age: 40,
    height: 188
  }
}

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

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值