Vuex (二)

Vuex(一)

这篇文章将更加详细讲解Vuex的使用,简单讲解见 Vuex(一)

当多个组件想使用同一个数据的时候,就可以使用Vuex

1、安装Vuex

npm i vuex -S

2、导入Vuex并让vue管理

首先新建一个文件夹:store (一般都这么建)
在这里插入图片描述
然后在文件夹里创建 index.js
1、安装插件
2、创建对象
3、导出store对象
4、去main.js挂载一下

//这个 from 'vue'  from后面那个是使用npm导入的时候所使用的名字,可以在配置文件中更改
import Vue from 'vue'
import Vuex from 'vuex'
//1、安装插件
Vue.use(Vuex)
//2、创建对象,对象中的属性是固定的这几项
const store = new Vuex.Store({
    state: {
    //放数据
        counter: 1000
    },
    mutations:{
	//放方法,同步方法
    },
    actions:{
	//放异步方法
    },
    getters:{
	//类似于vue里的计算属性
    },
    modules:{

    }
})
//3、导出store对象
export default store
//4、去main.js挂载一下

main.js

在这里挂载之后就意味着所有的vue组件都有一个$store对象

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

Vue.config.productionTip = false

new Vue({
  el: '#app',
  components: { App },
  template: '<App/>',
  // 在这里挂载之后就意味着所有的vue组件都有一个$store对象
  store
})

3、使用Vuex数据(state)方式

因为挂载之后就意味着所有的vue组件都有一个$store对象,所以可以按照如下方式使用

HelloVuex.vue
在这里插入图片描述
App.vue
在这里插入图片描述

<template>
  <div id="app">
    <h2> {{message}} </h2>
    <h2> {{$store.state.counter}} </h2>
    <button @click="counter++">+</button>
    <button @click="counter--">-</button>
    <hello-vuex></hello-vuex>
  </div>
</template>
<script>
import HelloVuex from './components/HelloVuex'
export default {
  name: 'App',
  components: {
    HelloVuex
  },
  data() {
    return {
      message: '我是APP组件',
      counter: 0
    }
  },
}
</script>
<style>
</style>

结果:此时两个组件都使用的Vuex里面的数据
在这里插入图片描述

4、更新、修改Vuex数据(state)方式–mutations–放同步方法

在这里插入图片描述

例子一:基本使用

不允许组件直接修改state的值,建议组件通过使用 mutations 中的方法来改

修改mutations:添加两个方法

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

修改App.vue

在这里添加两个方法,然后在方法中使用mutations中的方法操作state中数据
在这里插入图片描述
在这里插入图片描述

 methods: {
    add() {
      this.$store.commit('increment')
    },
    sub() {
      this.$store.commit('decrement')
    }
  },
细节讲解:参数传递

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

提交单个参数

在commit的时候方法后跟参数,并且在Vuex中mutations对应的方法中使用第二个参数接收。
在这里插入图片描述
在这里插入图片描述
在App.vue添加

<button @click="addCount(5)">-</button>

方法中添加:

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

在index.js中添加:

        incrementCount(state ,count) {
            state.counter += count
        },
提交多个参数

在commit的时候方法后跟参数,并且在Vuex中mutations对应的方法中使用第二个参数接收。此时这个参数是一个对象。

App.vue中添加

<button @click="addStu()">添加学生</button>
    addStu(){
      const stu = {id:5 ,name:'zyh', age:24 }
      this.$store.commit('addStu',stu)
    }

index.js中添加

        addStu(state,stu){
            state.students.push(stu)
        }
提交风格

除了上述提交以外,提交还可以写为如下风格:

App.vue中添加

<button @click="addStu2(10)">添加学生2</button>
 addStu2(){
      this.$store.commit({
        type: 'addStu2',
        id:6,
        name:'panda',
        age:25
      })
    }

index.js中添加

 addStu2(state,payload){
            console.log(payload.name)
            console.log(payload.id)
            console.log(payload.age)
            state.students.push(payload)
        }

此时结果:会增加type类型还可以通过点的形式访问其中属性
在这里插入图片描述
综上:这种提交风格相当于提交的是一个对象,包含了type和要传递的参数(可单个也可以多个)

响应式规则

可以使用set添加属性,此时是响应式的
在这里插入图片描述
App.vue添加代码

   <h2> {{$store.state.info}} </h2>
    <button @click="updateinfo()">添加信息</button>
    updateinfo(){
       this.$store.commit('updateinfo')
    }

在index中添加

        info:{
            name:'dululu'
        }
        updateinfo(state) {
            // 这样添加属性的话不是响应式的 --- 无法同步到页面上
            // state.info['address'] = '洛杉矶'

    //这样是响应式的 set => 参数一:要修改的值 参数二:key或者数组下标 参数三:value(可以是字符串或者number)
            Vue.set(state.info,'address','洛杉矶')
            //响应式删除属性
            //Vue.delete(state.info,'address')    
        },

结果:
在这里插入图片描述

5、getters基本使用

当一个数据需要经过一系列变化在使用的时候可以使用getters来实现,类似于vue中的计算属性

例子一:将counter平方

在getters添加代码:

 getters: {
        //类似于vue中的计算属性
        powerCounter(state){
            return state.counter * state.counter
        }
    },

使用方式:
在APP.vue中添加如下代码,注意方法不用加括号,当做属性来用就可以
在这里插入图片描述
结果:
在这里插入图片描述

例子二:获取大于20岁学生数据

state中添加:

        students:[
            {id:1 ,name:'zs',age:18},
            {id:1 ,name:'ls',age:24},
            {id:1 ,name:'ww',age:30},
            {id:1 ,name:'zl',age:10}
        ]

getters添加:
more20stu:获取大于20岁学生
more20stuLength:获取大于20岁学生人数
moreAgeStu:获取大于指定年龄学生
在这里插入图片描述
因为getters中只有两个参数,第一个是state,第二个是getters,所以想要获取指定年龄不能传入第三个参数,但是可以返回一个带参数的函数,然后在函数中通过调用地方传递过来的参数进行判断

 more20stu(state){
            return state.students.filter(s => s.age >20)
        },
        more20stuLength(state,getters){
            return getters.more20stu.length
        },
        moreAgeStu(state){
            return function (age) {
                return state.students.filter(s => s.age >age)
            }
        }

在App.vue添加:
在这里插入图片描述

    <h2> {{$store.getters.more20stu}} </h2>
    <h2> {{$store.getters.more20stuLength}} </h2>
    <h2> {{$store.getters.moreAgeStu(12)}} </h2>

结果:
在这里插入图片描述

6、action的使用–放异步方法

如果是一个异步的方法我们要放入action,因为放入mutations中vuex是监听不到变化的。

对于一个异步方法我们需要如下调用:
在App.vue的方法中先通过dispatch引用action中的方法,然后在action的方法中引用mutation中的方法。

在App.vue中添加

<button @click="updateinfo2()">异步添加信息</button>
    updateinfo2(){
       this.$store.dispatch('aUpdataInfo','我是payload')
    }

在index.js中的action中加

actions: {
        //context:上下文
        aUpdataInfo(context,payload) {
            console.log(payload)
            setTimeout(() => {
                context.commit('updateinfo')
            }, 1000);
        }
    },

如果要对数据进行操作后返回些东西:可以使用Promise

index.js中代码改为

      aUpdataInfo(context, payload) {
            return new Promise((resolve, rekect) => {
                setTimeout(() => {
                    context.commit('updateinfo')
                    console.log(payload)

                    resolve('111111')
                }, 1000);

            })
        }

App.vue中改为

    updateinfo2(){
       this.$store.dispatch('aUpdataInfo','我是payload').then(res =>{
          console.log('里面完成了提交');
          console.log(res);
       })
       
    }

注意上述代码中因为this.$store.dispatch调用了action中的方法,而在action方法中return了一个Promise,所以可以在App.vue调用action方法的那个后面 .then

7、modules的使用

模块有着自己的 state:{},mutations:{}, actions:{}, getters:{}
在这里插入图片描述

模块定义

在index.js添加

const moduleA = {
    state:{},
    mutations:{},
    actions:{},
    getters:{}
}
    modules: {
        a:moduleA
    }
模块中state

修改 moduleA

    state:{
        name: 'Tim'
    },

在App.vue中添加

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

结果:
在这里插入图片描述
由此可以看出,vuex会自动把一个模块放到本身的state中去,调用的时候当做一个对象去调用

模块中的mutations

修改 moduleA

    mutations:{
        updateName(state,payload) {
            state.name = payload
        },
    },

App.vue中添加

    <h2> {{$store.state.a.name}} </h2>
    <button @click="updateName">修改名字</button>
    updateName(){
      this.$store.commit('updateName','lisi')
    }

结果:
在这里插入图片描述
可以看出,使用方式和以前一样,但是要注意,模块中的方法名字不要和store中的方法名字重复

模块中的getters

修改 moduleA

    getters:{
        fullname(state){
            return state.name + '1111'
        },
        fullname1(state,getters,rootState){
            return getters.fullname + rootState.counter
        }

    }

App.vue添加

    <h2> {{$store.getters.fullname}} </h2>
    <h2> {{$store.getters.fullname1}} </h2>

结果:
在这里插入图片描述
由此可看出,调用时和之前一样,但是在模块中的getters中的方法有三个参数,第三个参数是获取 根 也就是 store中的state

模块中的action

修改 moduleA

  actions: {
        aUpdataName(context) {
            setTimeout(() => {
                context.commit('updateName','wangwu')
            }, 1000);
        }
    },

App.vue

   <h2> {{$store.getters.fullname}} </h2>
    <h2> {{$store.getters.fullname1}} </h2>
    <button @click="aUpdataName">异步修改名字</button>
    aUpdataName(){
      this.$store.dispatch('aUpdataName')
    }

模块中的context有如下属性,这里的context.commit和store中context.commit不同,这里的只能提交模块中的,而store中的context.commit等同于store.commit
在这里插入图片描述
结果:
在这里插入图片描述

8、对象解构

想要获取对象中一些数据可以如下写:
在这里插入图片描述
此时console.log(name)就是why了

9、Vuex结构

我们先将index.js复制一份,然后进行抽取
新建如下文件,将index copy.js代码对应部分抽取进对应js文件,其中state是放在index copy.js中
在这里插入图片描述
形式为:

export default{
抽取内容
}

抽取后的index copy.js为

//这个 from 'vue'  from后面那个是使用npm导入的时候所使用的名字,可以在配置文件中更改
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutation'
import actions from './action'
import getters from './getters'
import moduleA from './modules/moduleA'
//1、安装插件
Vue.use(Vuex)
const state  =  {
    counter: 1000,
    students: [
        { id: 1, name: 'zs', age: 18 },
        { id: 1, name: 'ls', age: 24 },
        { id: 1, name: 'ww', age: 30 },
        { id: 1, name: 'zl', age: 10 }
    ],
    info: {
        name: 'dululu'
    }
}
//2、创建对象
const store = new Vuex.Store({
    state,
    mutations,
    actions,
    getters,
    modules: {
        a: moduleA
    }
})
//3、导出store对象
export default store
//4、去main.js挂载一下

列举抽取样式:
moduleA

export default{
    state: {
        name: 'Tim'
    },
    mutations: {
        updateName(state, payload) {
            state.name = payload
        },
    },
    actions: {
        aUpdataName(context) {
            setTimeout(() => {
                context.commit('updateName','wangwu')
            }, 1000);
        }
    },
    getters: {
        fullname(state) {
            return state.name + '1111'
        },
        fullname1(state, getters, rootState) {
            return getters.fullname + rootState.counter
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值