Vuex的五个核心成员

303 阅读2分钟

一 Vuex是什么

1.1 首先学习Vuex是什么的概念

概念: Vuex是vue项目中实现大范围数据共享的技术方案

作用:是能够方便高效地实现组件之间的数据共享

好处:1 数据存取一步到位,不需要层层传递,2 数据流动清晰,3 存储的在Vuex中的数据都是响应式的

1.2 什么样的数据适合存储到Vue中

那种需要频繁,大范围的数据共享,就可以存储到Vuex当中

二 安装Vuex

1 安装依赖包 :npm i vuex@3.6.2(V2的版本)

2 导入包 impoft Vuex from 'Vuex'

3 安装插件 Vue.use(Vuex)

4 创建store =new Vuex.Store({ })

5 挂载Vue实例

new Vue({
  
  store // 2. 注入Vue实例
})

开发中我们一般都抽离main.js中的Vuex

新建src/store/index.js

import Vue from 'vue'
// 1 导入
import Vuex from 'vuex'
//2 安装插件
Vue.use(Vuex)
// 3 创建Store对象
const store = new Vuex.Store({
  state: {
    count: 0
  }
})
export default store

在mian.js中导入store文件

import Vue from 'vue'
import App from './App.vue'
import '@/assets/css/bootstrap.css'
// 导入store
import store from './store' 
Vue.config.productionTip = false

new Vue({
// 挂载到vue实例
  store,
  render: h => h(App),
}).$mount('#app')

三 认识核心成员1 State

3.1 概念:什么是State

  • 概念: State本质上就是Object对象
  • 作用:用来存储全局共享的数据

3.2 State定义公共数据的格式

new Vuex.store({
  state: {
   属性名: 属性值 
  }
})

3.3 组件访问State数据的第一种方式

  • 在组件中,通过this.$store.state.属性名来访问。
export default {
  name: 'Left',
 methods:{
  add(){
     this.$store.state.count++
  }
 }
}
  • 在模板中,则可以省略this而直接写成: {{$store.state.属性名}}

    <p>count 值:{{$store.state.count}}</p>

3.4 组件访问State数据的第二种方式,mapState 辅助函数来映射数据

//直接就可以使用了
  <p>利用辅助函数来渲染值:{{str}},{{count}}</p>

<script>
import {mapState} from 'vuex'
export default {
  name: 'kk',
  computed:{
    // 把需要的全局数据,映射为当前组件的计算属性
    // 返回值就是一个对象,展开这个对象的中的值
    ...mapState(['count','str'])
  }
}
</script>

三 认识核心成员2 Mutation

概念:变异。 它是Vuex中用来修改公共数据的唯一入口。因为在Vuex中是不能直接修改数据的的值,因为直接修改Vuex是监测不到的,如果这个共享数据多个组件使用,一旦出了问题,我们排查起来就很困难。所以我们要知道是哪个地方修改了这个值,就必须同Mutation来修改。

  • 两个参数
  • 参数一:所有的mutations的函数,第一个参数一定是state
  • 参数二:接收传过来的值

222.png

方法1 commit方法:

1:在vuex中定义Mutation方法

 mutations:{
    // 重点:所有的mutations的函数,第一个参数一定是state
    // 重点:第二个参数payload(载荷),是传过来的值
      addCount(state,payload){
       state.count+=payload.num
      }
  }

2:在组件中调用Mutation方法

   <button class="btn btn-primary" @click="$store.commit('addCount',5)">+5</button><br>
   <button class="btn btn-primary" @click="$store.commit('addCount',{num:10})">+10</button><br>

方法2:辅助函数mapMutations

组件中methods中映射,然后调用

  <button class="btn btn-primary" @click="addCount({num:20})">20</button><br>
  <script>
import {mapMutations} from 'vuex'
export default {
  name: 'Left',
  methods:{
    ...mapMutations(['addCount'])
  }
}
</script>

vuex中定义

import Vue from 'vue'
// 1 导入
import Vuex from 'vuex'

Vue.use(Vuex)
// 2 创建Store对象
const store = new Vuex.Store({
  state: {
    count: 1,
    str:'假如生活欺骗了你'
  },
  mutations:{
    // 重点:所有的mutations的函数,第一个参数一定是state
      addCount(state,payload){
       state.count+=payload.num
      }
  }
})
export default store

三 认识核心成员3 Action

概念:对于异步变更数据Mutation是无法监测到的(请求,定时器等)这时需要Action来处理,所以Action本质上是JavaScript函数,专门用来处理Vuex中的异步操作。

用法

  • 两个参数:
  • 参数1:上下文对象context(形参),用于调用其他成员的方法。
  • 参数2:载荷payload(形参),用于传参

vuex中定义

import Vue from 'vue'
// 1 导入
import Vuex from 'vuex'

Vue.use(Vuex)
// 2 创建Store对象
const store = new Vuex.Store({
  state: {
    count: 1,
    str:'假如生活欺骗了你'
  },
  mutations:{
    // 重点:所有的mutations的函数,第一个参数一定是state
    addCount(state,payload){
       
            state.count+=payload.num
     
       }
  },
  actions:{
// 在actions做异步的操作,然后交给mutations修改
// 怎么交个mutations呢,commit
// 怎么调用commit 
// 接收形参:上下文对象($store)
// 通过dispatch方法,调用指定名称Action方法

addCountAsync(context,payload){
    console.log(payload,"这是payload数据");
    console.log(context,"这是contex数据");
    setTimeout(()=>{
      context.commit('addCount',payload)
      },1000)  
}
  }
})
export default store

上下文对象 context(形参),中就可以调用commit的方法

1111.png

组件用dispatch方法调用

<button class="btn btn-primary" @click="$store.dispatch('addCountAsync',{num:30})">异步加30</button><br>

actions的mapActions辅助函数

<button class="btn btn-primary" @click="addCountAsync({num:100})">异步加100</button><br>

组件中methods中映射,然后调用

<script>
import {mapActions, mapMutations,} from 'vuex'
export default {
  name: 'Left',
  methods:{
    ...mapMutations(['addCount']),
    ...mapActions('[addCountAsync]')
  }
}
</script>

四 认识核心成员4 Getters

  • 概念:Getter本质上JavaScript的函数,用来统计全局属性的状态值
  • 作用:他是Vuex的全局计算属性,当Store数据源发生变化时,getter的返回值会自动更新。
import Vue from 'vue'
// 1 导入
import Vuex from 'vuex'

Vue.use(Vuex)
// 2 创建Store对象
const store = new Vuex.Store({
  state: {
    count: 1,
    str:'假如生活欺骗了你',
    books: [
        {
          "name": "javasript技术内幕",
          "price": 100,
          "isAllDone": false
        },
        {
          "name": "数学之美",
          "price": 44,
          "isAllDone": false
        },
        {
          "name": "认知天性",
          "price": 40,
          "isAllDone": false
        }
      ]
  },

  getters:{
    isAllDone(state,payload){
        return state.books.every(item=>item.isAllDone)
    }
 }

})
export default store
<h1>{{$store.getters.isAllDone}}</h1>

总结:现在多个地方用到isAllDone的状态,只要Vuex的isAllDone改变了,组件用到的这个值,也就跟着改变了。

computed 中使用辅助函数mapGetters,将Getters中的变量映射到当前的组件中使用

<h1>{{isAllDone}}</h1>
import {mapGetters} from 'vuex'

 export default {
  name: 'Left',

   computed:{
   ...mapGetters(['isAllDone'])

}
}

五 认识核心成员5 Module

场景:很多个组件的state,mutations,actions。getters,都掺杂在一起,结构混乱,不利于维护。所以衍生出了Module,每个组件的Vuex数据都划分成独立的模块,每个模块拥有自己的state,mutations,actions,getters

11111.png

用法:新建模块,在moude导入模块,注册模块,namespaced开启命名空间

55.png

访问方法

访问数据和修改数据的调整

  • 访问模块中的数据,要加上模块名

    获取数据项:  {{$store.state.模块名.数据项名}}
    获取getters: {{$store.getters['模块名/getters名']}}
    
  • 访问模块中的mutations/actions:

    • 如果namespaced为true,则需要额外去补充模块名
    • 如果namespaced为false,则不需要额外补充模块名
    $store.commit('mutations名')        // namespaced为false
    $store.commit('模块名/mutations名')  // namespaced为true
    
用斜线来分割,斜线前是模块名,斜线后是方法名
    <button class="btn btn-warning" @click="$store.commit('count/updata')">调用</button>

总结:划分module下访问数据和方法总结

不用辅助函数的访问store

//模块名count
//数据名:str1
 <h2>{{$store.state.count.str1}}</h2>

使用辅助函数mapState来调用

<template>
  <div class="right-container">
    <h3>Right 组件</h3>
    <!--1 module模块下调用数据 -->
    <h1>{{str}}</h1>
    <hr>
     <!-- 2 module模块下调用方法 -->
    <button class="btn btn-warning" @click="$store.commit('count/updata')">调用</button>
  </div>
</template>

<script>
import{mapState}from'vuex'
export default {
  name: 'Right',
  computed:{
    // 参数1:访问模块名
    // 参数2:访问的数据名
    ...mapState('count',['str'])
  }
}
</script>

<style>
</style>

六 总结四个核心成员在模块下的用法

模块

// 定义count模块
export default {
    // 开启命名空间
    namespaced:true,
// 简写
    state:()=>({
str:'假如生活欺骗了你',
str1:'不要悲伤,不要心急'
    }),
    mutations: {
       updata(){
           console.log("count模块下mutations被调用了");
       }     
    },
    actions: {
        test(){
            console.log("count下actions方法调用了");
        }
    },
    getters:{
        gettData(state){
         return state.str+'因为他明天还会继续欺骗你'
        }
    },

}

组件

<template>
  <div class="right-container">
    <h3>Right 组件</h3>
    <!--1 module模块下辅助函数调用数据 -->
    <h1>{{str}}</h1>
    <!-- modeule模块下普通调用 -->
    <h2>{{$store.state.count.str1}}</h2>
    <hr>

     <!-- 2 module模块下调用方法 -->
          <!-- Mutations调用 -->
<button class="btn btn-warning" @click="$store.commit('count/updata')">Mutations普通调用</button>
<button class="btn btn-warning" @click="updata">Mutations辅助调用</button>
           <!--Actions调用 -->
 <button class="btn btn-warning" @click="$store.dispatch('count/test')">Actions普通调用</button>
 <button class="btn btn-warning" @click="test">Actions辅助调用</button>
      <!-- getter -->
 <h1>{{gettData}}</h1>
  </div>
</template>

<script>
import{mapState,mapMutations,mapActions,mapGetters}from'vuex'
export default {
  name: 'Right',
  computed:{
    // 参数1:访问模块名
    // 参数2:访问的数据名
    ...mapState('count',['str']),
    ...mapGetters('count',['gettData'])
  },
  methods:{
    ...mapMutations('count',['updata']),
    ...mapActions('count',['test'])
  }
}
</script>

<style>
</style>

6666.png