Vuex基础

Vuex基础

一、初始化项目

1、项目创建

vue create 项目名       //示例: vue craete hm-hr

2、添加 vuex 功能

npm i vuex  或
yarn add vuex

3、引入、使用、创建仓库实例和挂载仓库实例到根实例当中 vuex

import Vuex from "vuex" //引入
Vue.use(Vuex)  //使用
const store = new Vuex.Store() //创建仓库实例
new Vue({
//挂载到根实例中
  store,
  render: h => h(App),
}).$mount('#app')
​

4、检验是否安装引入成功

在app.vue中
created(){
     //安装完vuex  会在组件中注入 一个 $store变量
  console.log(this.$store);
}
​

二、Vuex基础

0、vuex的基本概念

vuex是采用集中式管理组件依赖的共享数据的一个工具,可以解决不同组件数据共享问题。
•   Vuex 是一个专为 Vue.js 应用程序开发的**状态管理模式**。它采用**`集中式`**存储管理应用的所有组件的状态,并以相应的规则保证状态以一种**`可预测`**的方式发生变化。
  • 结论

1. 修改state状态必须通过**`mutations`**
2. **`mutations`**只能执行同步代码,类似ajax,定时器之类的异步代码不能在mutations中执行
3. 执行异步代码,要通过actions,然后将数据提交给mutations才可以完成
4. state的状态即共享数据可以在组件中引用
5. 组件中可以调用action

1、state (共享状态数据)

  • 基本概念

    ​ state是放置所有公共状态的属性,如果你有一个公共状态数据 , 你只需要定义在 state对象

  • 基本创建

      //创建仓库实例
      const store = new Vuex.Store(
     // 数据存储在对象里面
     {
       state: {
         count: 0,
         name: "tom"      //这两个都是保存的数据
       }
     }
      )
  • 基本使用

  <template>
    <div>
      测试
  <!-- 基本使用,插值表达式 -->
  //1、 可以直接插值表达式
  <div>{{$store.state.count}}</div>   // 0        
  <div>{{$store.state.name}}</div>   // tom
  //2、也可以在data中声明变量
  {{name}}  // tom
    </div>
  </template>
  export default {    
  data(){
  return{
    name:this.$store.state.name
  }
  },   
  created(){
    //安装完vuex  会在组件中注入 一个 $store变量
    console.log(this.$store);
    console.log(this.$store.state.name); //tom
  }
  }      
  • 优化(计算属性)

<div>
<div>{{name}}</div>
<div>{{count}}</div>
  </div>
//在计算属性中使用   
// 能跟踪后续的更改
// 都是函数    记得加 return   
computed:{
     name(){
       return this.$store.state.name
     } ,
     count(){
       return this.$store.state.count
     }
}
  • 辅助函数(mapState)

import {mapState} from "vuex"  // 辅助函数1、引入mapState
computed:{
//辅助函数2、采用数组形式引入state属性
  ...mapState(["name","count"])
}

2、mutations(同步修改state)(方法)

  • 基本概念

​ mutations是一个对象,对象中存放修改state的方法 ,只能执行同步代码,目的是形成数据快照

数据快照 :一次mutation的执行,立刻得到一种视图状态,因为是立刻,所以必须是同步

  • 准备严格模式

//创建仓库实例
const store = new Vuex.Store(
  // 数据存储在对象里
  {  
    strict:true,  //限制state 只能被mutaitions 修改的严格模式
    state: {
      count: 0,
      name: "tom"
    }
  }
)
  • 基本创建

/创建仓库实例
const store = new Vuex.Store(
  // 数据存储在对象里
  {
    //限制state 只能被mutations 修改的严格模式
    strict: true,
    state: {
      count: 0,
      name: "tom"
    },
    mutations: {
      //对象里面是方法
      // 方法里面的参数:
      //第一个参数是当前store的state属性
      //payload 载荷  是运输参数 调用 mutations的时候可以传递参数 传递载荷
      setCount(state, data) {
        state.count += data
      }
    }
  }
)
  • 基本使用($store.commit)

<button @click="$store.commit('setCount',666)">点我+666</button>
​
//效果 :  点击按钮 count + 传过来的参数 666
  • 优化

在main.js中的仓库对象里面
mutations: {
      //对象里面是方法
      // 方法里面的参数:
      //第一个参数是当前store的state属性
      //payload 载荷  是运输参数 调用 mutations的时候可以传递参数 传递载荷
      setCount(state, data) {
        state.count += data
      }
    }
​
App.js中 的methods 里
<button @click="setCount(999)">点我+999</button>
//与data同级
methods:{
   setCount(data) {
         this.$store.commit("setCount",data)
      }
}
  • 辅助函数(mapMutations)

//引入辅助函数 mapMutations 
import {mapState,mapMutations} from "vuex" 
//2在methods 里面写
methods:{
  //  setCount(data) {
  //        this.$store.commit("setCount",data)
  //     }
  ...mapMutations(["setCount"]) //采用数组形式引入state属性 
}

但是请注意: Vuex中mutations中要求不能写异步代码,如果有异步的ajax请求,应该放置在actions中

3、actions(异步修改state)(方法)

  • 基本概念

actions 是一个对象对象中存放着方法,state是存放数据的,mutations是同步更新数据,actions则负责进行异步操作

  • 基本创建

   //异步都要放在actions中     在store对象里面与mutatoins对象同级哦
        actions: {
          asynSetCount(store,data) {
             //默认得到当前的仓库是例 store
            //用延时器做异步演示
            setTimeout(() => {
              //actions 不能直接修改 state 需要通过 mutations
         store.commit("setCount",data)
            },1000)
       } 
  }
  • 基本使用

 <button @click="$store.dispatch('asynSetCount',666)">点我增加延迟666</button>
  • 优化

<button @click="asynSetCount(666)">点我延迟666</button>
methods:{
asynSetCount(data){
​
  this.$store.dispatch("asynSetCount",data)
          }
}
  • 辅助函数(mapActions)

import {mapState,mapMutations,mapActions} from "vuex"  // 辅助函数1、引入mapActions
​
methods:{
  //  setCount(data) {
  //        this.$store.commit("setCount",data)
  //     }
  ...mapMutations(["setCount"]),
​
// asynSetCount(data){
​
//   this.$store.dispatch("asynSetCount",data)
// }
    //等价于上面
    ...mapActions(["asynSetCount"])    //采用数组形式引入state属性 
​
}

4、getters(每个属性都是函数)

  • 基本创建

    const store = new Vuex.Store(
      // 数据存储在对象里
      {
        //限制state 只能被mutations 修改的严格模式
        strict: true,
        state: {
          count: 0,
          name: "tom",
          list: [1, 2, 3, 4, 5, 6, 7, 888, 77, 666]
        },
    ......
    getters: {
          //这里是依赖于state 的派生数据
          // 每个属性都是函数(所以记得加return),默认可以得到state对象
          // 返回值就是最终显示的数据  必须要有返回值
          //如果需要的是显示 list ,当比5大的数据 演示
          filterList(state) {
            return state.list.filter(val => val > 5)  //返回处理过后的数据 
          }
        }
        }
    • 基本使用

 <div>{{$store.state.list}}</div>   /[ 1, 2, 3, 4, 5, 6, 7, 888, 77, 666 ]
<div>{{$store.getters.filterList}}</div> // [ 6, 7, 888, 77, 666 ]
​
  • 优化

<div>{{filterList}}</div> 
// 总结 :因为getters里面的每个属性都是函数,所以需要写在计算属性里面,而mutations 和actions 里面存放的是修改state 数据的方法所以写在methods 里面
computed:{
    filterList(){
        //计算属性里面的函数记得加上return
    return  this.$store.getters.filterList
    }
  }
​
  • 辅助函数(mapGetters)

 computed:{
//等价于下面
 ...mapGetters(["filterList"]) //采用数组形式引入state属性 
    // filterList(){
    // return  this.$store.getters.filterList
    // },
 }  
  }
  • 在项目中的常见用法

很少会有复杂的逻辑,通常都是用来进行state嵌套数据的简化获取 main.js中

//创建仓库实例           记得数据是存到 state里面的哦
const store = new Vuex.Store(
  // 数据存储在对象里
  {
    //限制state 只能被mutations 修改的严格模式
    strict: true,
    state: {
      count: 0,
      name: "tom",
      list: [1, 2, 3, 4, 5, 6, 7, 888, 77, 666],
      students: {
        name: "翠花",
        age: 18,
        school: {
          name: "吉山幼儿园",
          address: "珠吉路58号"
        }
      },
    },
  getters: {
      //这里是依赖于state 的派生数据
      // 每个属性都是函数,默认可以得到state对象
      // 返回值就是最终显示的数据
      //如果需要的是显示 list ,当比5大的数据 演示
      // filterList(state) {
      //   return state.list.filter(val => val > 5)
      // }
      //简写模式
      filterList: state => state.list.filter(val=>val>5),
      schoolAddress: state=>state.students.school.address
    }
//App.vue中
<div>{{$store.getters.schoolAddress}}</div>

5、modules(模块化)

  • 基本概念

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象 state 当中。当应用变得非常复杂时,就有可能变得相当臃肿。Vuex会变得越来越难以维护, 由此,又有了Vuex的模块化

  • 基本创建

//创建仓库实例
const store = new Vuex.Store(
  // 数据存储在对象里
  {
    //限制state 只能被mutations 修改的严格模式
    strict: true,
   //本来这里直接放state、mutations、actions
    //如果分模块就应该放在 modules里面
    modules: {      
      //假设有 user 和 setting 模块
      user: {
        state: {
          name:"狗蛋"
        }
      },
      setting: {
        state: {
          token:"666"
        }
      }
     }    
  }
  • 基本使用

1.模块化中的state

由于经过 vuex 的封装和转换, 真实获取数据时, 跟创建 Modules 的写法有所出

 <!-- 模块化状态下,state的固定获取方法:$store.state   模块名.属性名     -->
 用户名称:
 <div>{{$store.state.user.name}}</div><br>
 用户token:
  <div>{{$store.state.setting.token}}</div>

2.模块化中的mutations和actions

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应

但是,如果我们想保证内部模块的高封闭性,我们可以采用namespaced来进行区分

  • 添加空间命名锁 避免全局通用mutations

 modules: {
      //假设有 user 和 setting 模块
      user: {
        //添加命名空间锁,避免全局通用mutations
        namespaced:true,
        state: {
          name: "狗蛋"
        },
        mutations: {
          getName(state) {
            state.name= "翠花"
        }
        }
      },
      setting: {
        state: {
          token: "666"
        }
      }
    }

在AAp.vue中调用mutations方法会报错

<button @click="$store.commit('getName')">点我变翠花</button>
 //  [vuex] unknown mutation type: getName  报错信息

(1).基于命名空间锁的mutations的调用方法1

直接在调用时加上模块路径即可

<!-- 调用带有命名空间锁的函数 最简单的方法就是添加模块路径 -->
 <button @click="$store.commit('user/getName')">点我变翠花</button>  //效果: 狗蛋变翠花

(2)基于命名空间锁的mutations的调用方法2

在使用全局的辅助函数时, 可以指定命名空间

注意, 给出参数的顺序是 mapMutations(模块名, [函数名])

<button @click="getName">点我变翠花</button>
import {mapMutations}from "vuex"
export default {
  methods:{
    //如果加了命名空间锁,直接用辅助函数生成是行不通的,
    //可以在传数组之前,加上一个字符串作为模块名
...mapMutations("user",['getName'])
  }
}
 // 效果 : 狗蛋变翠花

(3)基于命名空间锁的mutations的调用方法3

<button @click="getName">点我变翠花</button>
​
//如果添加了命名空间锁还可以调用 vuex 提供的方法
//创建专门属于某个模块的辅助函数
import {createNamespacedHelpers} from "vuex"
//调用这个函数时,加上模块名作为参数,就可以创建出基于该模块的辅助函数
const {mapMutations} =createNamespacedHelpers('user')
export default {
  methods:{
...mapMutations(["getName"])
  }
}      //效果也是 点击按钮 狗蛋变翠花

2.1.拓展如果解构时变量名被占用的重命名方法

<button @click="getName">点我变翠花</button>
<script>
import {mapMutations}from "vuex"
//如果添加了命名空间锁还可以调用 vuex 提供的方法
//创建专门属于某个模块的辅助函数
import {createNamespacedHelpers} from "vuex"
//调用这个函数时,加上模块名作为参数,就可以创建出基于该模块的辅助函数
​
//假设解构的变量名已经存在,可以声明解构之后要重命名的名称
//只需要在解构时使用以下语法 const {旧变量名:新变量名}
const {mapMutations:usermapMutations} =createNamespacedHelpers('user')
export default {
  methods:{
//     //如果加了命名空间锁,直接用辅助函数生成是行不通的,
//     //可以在传数组之前,加上一个字符串作为模块名
...mapMutations("user",['getName']),
...usermapMutations(["getName"])
  }
}

3.模块中的getters

一般来说, 在模块状态下, getters 依旧是放在最外层

作用就是简化各个子模块重要数据的获取步骤

请注意,这个getters是根级别下的getters

  • 创建

  {
    //限制state 只能被mutations 修改的严格模式
    strict: true,
    //本来这里直接放state、mutations、actions
    //如果分模块就应该放在 modules里面
    modules: {
      //假设有 user 和 setting 模块
      user: {
        //添加命名空间锁,避免全局通用mutations
        namespaced:true,
        state: {
          name: "狗蛋"
        },
        mutations: {
          getName(state) {
            state.name= "翠花"
        }
        }
      },
      setting: {
        state: {
          token: "666"
        }
      }
    },
//分模块的情况下,getters还是放在最外层
//因为在这里可以直接获取到所有子模块的数据
    //方便数据的简化
    getters: {
      name: state => state.user.name,
      token:state=>state.setting.token
    }
  }
  • 使用

 用户名称:
 <div>
   {{$store.getters.name}}
   </div><br>
 用户token:
  <div>
    {{$store.getters.token}}
    </div>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值