vuex ——介绍、安装、基本使用

一、介绍

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。

如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

二、在项目中安装 vuex

1、安装

在需要安装 vuex 的项目终端中,输入下面指令,回车等待安装:

npm install vuex@next --save

安装完成: 

可以看到 package.json 里面,已经有了 vuex :

 

 2、创建一个最简单的 store

新建一个文件夹 store ,新建文件 index.js :

每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:

(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

(2)不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

三、基本使用——state(获取仓库store中的数据)

仓库 store 的 index.js 中:

main.js 中安装引入:

 

 修改 HomeView.vue :

 可以看到成功获取到数据:

 

四、基本使用——mutation(清楚地跟踪到数据的改变)

接上面的例子,在 HomeView.vue 中添加一个按钮来改变仓库 store 中的数据:

上面这个方法可以更改,但是 vuex 跟踪不到数据的变化(因为store中的数据是很多个组件共享的,不能判断出是哪个组件里面改变了数据)。这时就需要用到 mutation 。

添加 mutation 的方法:

在 HomeView.vue 中去实现这个方法: 

这样就可以改变数据了:

 

如果想在 mutation 中传参,修改上面代码: 

 这样就可以实现传参,每点一次按钮就加5:

 

五、基本使用——getters(认为是store中的计算属性)

1、通过方法访问

接上面的例子,如果我们想翻转state中的msg :

index.js :Getter 接受 state 作为其第一个参数:

// 引入
import { createStore } from "vuex";
// 创建store实例
const store=createStore({
    state(){ //是存储的单一状态,是存储的基本数据
        return{
            msg:'helloworld'
        }
    },
    getters:{ //认为是store中的计算属性
        reverMsg:function(state){
            // 翻转state中的msg
            return state.msg.split('').reverse().join('')
        }
    },
})
// 导出仓库
export default store

 在 HomeView.vue 中去使用这个方法:

<template>
  <div class="home">
    <p>{{$store.getters.reverMsg}}</p>
  </div>
</template>

 可以看到已经翻转:

 

2、通过属性访问

 接上面例子,如果我们要获取data里面的msg的长度:

index.js :

// 引入
import { createStore } from "vuex";
// 创建store实例
const store=createStore({
    state(){ //是存储的单一状态,是存储的基本数据
        return{
            msg:'helloworld'
        }
    },
    // 如果state的状态需要过滤或者其他的操作
    getters:{ //认为是store中的计算属性
        reverMsg:function(state){
            // 翻转state中的msg
            return state.msg.split('').reverse().join('')
        },
        // 如果我们要获取data里面的msg的长度
        reverMsgLength:function(state,getters){  //getters表示当前store中的getters对象
            return getters.reverMsg.length
        }
    },
})
// 导出仓库
export default store

 HomeView.vue :

<template>
  <div class="home">
    <p>{{$store.getters.reverMsg}}</p>
    <p>{{$store.getters.reverMsgLength}}</p>
  </div>
</template>

  

六、基本使用——actions(可以发送异步请求)

1、介绍

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

2、例子 

接上面的例子,我们使用猫眼电影的数据:

 

复制上面的链接 ,在 index.js 里面 :

// 引入
import { createStore } from "vuex";
// 创建store实例
const store=createStore({
    // 获取猫眼电影的数据
    actions:{
        getHot:function(){
            fetch('https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=成都&ci=59&channelId=4').then((res)=>{
                console.log(res);
            })
        }
    }
})
// 导出仓库
export default store

在 HomeView.vue 里面,Action 通过 store.dispatch 方法触发:

<script>
// @ is an alias to /src

export default {
  name: 'HomeView',
  mounted(){
    // Action 通过 store.dispatch 方法触发:
    this.$store.dispatch('getHot')
  }
}
</script>

在 vue.config.js 中配置中转服务器来实现代理:

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer:{
    proxy:{  //通过代理实现跨域
      'path':{
        target:'https://i.maoyan.com',  //替换的服务端地址
        changeOrigin:true,  //开启代理,允许跨域
        //设置重写的路径
        pathRewrite:{
          '^/path':''
        }
      }
    }
  }
})

然后修改 index.js 里面的路径:

获取数据可以使用 axios ,安装 axios ,然后在 mutation 里面添加方法:

完整代码如下:

HomeView.vue :

<script>
// @ is an alias to /src

export default {
  name: 'HomeView',
  mounted(){
    // Action 通过 store.dispatch 方法触发:
    this.$store.dispatch('getHot','hhh')  //后面传一个参数
  }
}
</script>

 index.js :

// 引入
import axios from "axios";
import { createStore } from "vuex";
// 创建store实例
const store=createStore({
    state(){ //是存储的单一状态,是存储的基本数据
        return{
            hotList:[]
        }
    },
    mutations:{
        updateHotList:function(state,value){
            state.hotList=value
        }
    },

    // 获取猫眼电影的数据
    actions:{
        getHot:function(context,payload){ //context:与store实例具有相同的属性和方法的对象
            // fetch('/path/api/mmdb/movie/v3/list/hot.json?ct=成都&ci=59&channelId=4').then((res)=>{
            //     console.log(res.json());
            //     console.log(context.state.hotList);
            // })
            axios.get('/path/api/mmdb/movie/v3/list/hot.json?ct=成都&ci=59&channelId=4').then(res=>{
                console.log(res);
                console.log(context);
                // context.state.hotList=res.data.data.hot
                context.commit('updateHotList',res.data.data.hot)
                console.log(context.state.hotList);
                console.log(payload); //payload 接收传参‘hhh’
            })
        }
    }
})
// 导出仓库
export default store

vue.config.js :

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer:{
    proxy:{  //通过代理实现跨域
      'path':{
        target:'https://i.maoyan.com',  //替换的服务端地址
        changeOrigin:true,  //开启代理,允许跨域
        //设置重写的路径
        pathRewrite:{
          '^/path':''
        }
      }
    }
  }
})

获取到数据:

  

七、基本使用——module(模块分割)

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

八、基本使用——辅助函数

1、mapState 辅助函数

当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:

// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

2、对象展开运算符

mapState 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。但是自从有了对象展开运算符,我们可以极大地简化写法:

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值