vuex与映射

本文深入探讨Vuex,它是Vue.js应用的状态管理库。内容包括Vuex的基本概念,如state、getter、mutation和action,强调何时使用Vuex以及它们在大型项目中的重要性。同时,介绍了映射的使用,包括基本和高级用法,以简化代码并提高代码可读性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、vuex定义

vuex是vue的全局状态的管理工具
vuex数据更新,其引用组件都会响应式的更新

2、Vue中的单项数据流

与单向数据流对应的就是双向数据流:双向数据流在Vue中也叫做‘双向绑定’,其实现主要是依靠MVVM框架,在Vue中主要由三个部分组成:ViewViewModelModel。其中View可以简单的理解为视图层,Model可以简单的理解为数据层,其中View与Model之间是不能直接通信的,必须得依靠ViewModel中间件来完成。通过ViewModel就可以实现数据双向绑定,也就是ViewModel之间的同步是自动的,Model数据改变了View视图上的数据也会跟着改变,而不必手动去更新。

3.什么情况下该使用Vuex?

Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。 如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择

  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {}

1.state

就是在这个里面定义的数据,vue的所有组件都可以使用,具体语法如下

  state: {
      user : {
          name:'张三',
          age:18
      }
  },

组件使用

this.$store.state.user.name   // 张三
$store.state.user.age     // 18 

辅助函数

<script>
import { mapState } from "vuex";

export default {
  name: "Home",
  
  computed: {
    ...mapState(["user"])
  }
}
</script>

导入了辅助函数之后就可以直接用

user.name   // 张三
user.age    // 18 

2.getter

getters其实并没有过多的介绍,就相当于是vue中的计算属性computed

vuex

info(state) {
    console.log('getters')
    return `我的名字叫做${state.user.name} 我的年纪${state.user.age}`
 }

组件

 <h3>简介: {{ $store.getters.info }}</h3>

 辅助函数

<script>
import { mapGetters } from "vuex";

export default {
  name: "Home",
  
  computed: {
   ...mapGetters(["info"])
  }
}
</script>

导入了辅助函数之后就可以直接用

<h3>简介(mapGetters): {{ info }}</h3>

3.mutations

语法: this.$store.commit('mutation名', 载荷实参 )

这个就厉害了,所有的state里面的数据,只能通过mutations来修改

组件

 <p><button @click="doClick">改变数据</button></p>
 
   doClick() {
      this.$store.commit("updated", {
        name: "大帅哥",
        age: 100,
      });
    },

vuex

mutations: {
  // state 就是 state里面的数据 , payload就是载荷 通常就是一个对象
    updated(state, payload) {
      state.user = payload
    },
}

4.actions

语法: this.$store.dispatch('actions的名字', 参数)

步骤:

  1. 组件提交actions异步更新 this.$store.dispatch('actions的名字', 参数)
  2. actions 发送异步请求,但是里面只能看不能改
  3. 提交给 mutations , context.commit('mutations函数名',要修改的数据)
  4. mutations 里面就可以直接修改数据了

 

工作流程 :

 

  • 1.actions与mutations相同点 :都是修改state数据

  • 2.actions与mutations不同点

    • mutations:同步更新
    • actions: 异步更新(例如你的数据来源于ajax)
    1. 注意点
    • actions里面不能直接修改数据 ,
    • 主要就是发送axios请求,以防代码冗余
    • vuex中没有vue的实例,调用不了axios 的方法,我们要手动导入

组件

<button @click="doClick111">点我发送axios请求</button>


doClick111() {
      this.$store.dispatch("getList");
  }

vuex

//导入axios
import axios from "axios";

// 先定义一个空数组准备接收
state : {
    list : []
}

// 这里我们注意 , vuex里面没有this 所以我们要导入axios

 actions: {
    async getList(context) {
      const { data: res } = await axios.get('/getBooks')
      console.log(res);
      context.commit('getBooks', res.data)
    }
}

5.modules

modules主要就是,模块化的,这个大型项目用的很多,但是vue2也不支持很大型的项目,所以这个用的还是比较少,但是我这边还是给大家提一下

// 导入子模块
import user from './user'

 modules: {
    user
  }

子模块 store/user.js

import Vue from "vue";
import Vuex from "vuex";
//导入axios
import axios from "axios";

Vue.use(Vuex);

export default {
  namespaced: true,
  state: {
    list: [],
  },
  getters: {},
  mutations: {
    getBooks(state, payload) {
      state.list = payload;
    },
  },
  actions: {
    async getList(context) {
      const { data: res } = await axios.get("/getbooks");
      console.log(res);
      context.commit("getBooks", res.data);
    },
  },
  modules: {},
}

 二.映射

基本用法

假设Vuex的代码如下:

const store = new Vuex({
    state:{
        userInfo:{
            id:110,
            username:'laoxie'
        }
    },
    getters:{
        isLogin(state){
            return !!state.userInfo.id
        }
    },
    mutations:{
        login(state,payload){
            state.userInfo = payload
        },
        logout(state){
            state.userInfo = {}
        }
    },
    actions:{
        login(ctx,payload){
            ajax('/login',payload).then(data=>{
                ctx.commit('login',data)
            })
        }
    }
})

mapStatemapGetter映射的值都属于属性,所以一般用在computed选项中,mapMutationsmapActions映射的值都属于方法,所以一般用在methods中,它们的参数支持数组与对象用法,并返回一个对象

{
    computed:{
        // 把同名属性userInfo映射到computed中,以下两行代码等效
        // userInfo(){return this.$store.state.userInfo}
        ...mapState(['userInfo']), 
        
        // 如需更改名字,则可使用对象形式(字符串或函数形式)
        ...mapState({user:'userInfo',currentUser:state=>state.userInfo})
        
        // mapGetters采用对象参数时不支持函数写法
        ...mapGetters(['isLogin']),
        ...mapGetters({logined:'isLogin'}),
    },
    methods:{
        // 以下两种写法等效于:logout(){this.$store.commit('logout')}
        ...mapMutations(['logout']), 
        ...mapActions({
            logout(commit,payload){
                // commit固定为第一个参数
                // payload为调用logout时传入的参数,不传则为undefined
                commit('logout')
            }
        }),
        
        // 以下两种写法等效于:login(user){this.$store.dispatch('login',user)}
        ...mapActions(['login']),
        ...mapActions({
            login(dispatch,payload){
                // dispatch固定为第一个参数
                // payload为调用login时传入的参数,不传则为undefined
                dispatch('login',payload)
            }
        })
    }
}

高级用法

假设Vuex使用了模块化及命名空间,更能体会4个映射方法的优势,假设vuex代码如下:

const user = {
    // 模块化并设置命名空间 
    namespaced:true,
    state:{
        userInfo:{
            id:110,
            username:'laoxie'
        }
    },
    getters:{
        isLogin(state){
            return !!state.userInfo.id
        }
    },
    mutations:{
        login(state,payload){
            state.userInfo = payload
        },
        logout(state){
            state.userInfo = {}
        }
    },
    actions:{
        login(ctx,payload){
            ajax('/login',payload).then(data=>{
                ctx.commit('login',data)
            })
        }
    }
}
const store = new Vuex({
    modules:{
        user
    }
})

Vuex模块化后,默认只影响state的获取,gettersmutationsactions依然在全局状态下,设置了命名空间(namespaced:true)后getters、mutations、actions的获取与操作需要带上命名空间,操作相对会比较繁琐,使用映射方法可以简化我们的代码,用法如下:

{
    computed:{
        // 以下两个用法效果一至
        // 不用第一个参数用法如下
        ...mapState({userInfo:state=>state.user.userInfo}),
        // 设置第一个参数为模块名称
        ...mapState('user',['userInfo']), 
        
       
        // 以下两个用法效果一至
        ...mapGetters(['user/isLogin']), // 不推荐,给实例写入`user/isLogin`属性
        ...mapGetters('user',['isLogin']), // 给实例写入`isLogin`属性
    },
    methods:{
        // 以下写法等效于:logout(){this.$store.commit('user/logout')}
        ...mapActions('user',['logout']),
        
        // 以下写法等效于:login(user){this.$store.dispatch('user/login',user)}
        ...mapActions('user',{
            login(dispatch,payload){
                // dispatch固定为第一个参数
                // payload为调用login时传入的参数,不传则为undefined
                dispatch('login',payload)
            }
        })
    }
}

以上为mapStatemapGettersmapMutationsmapActions 4个映射方法的使用,结果模块化与命名空间更能发挥它们的优势

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值