Vuex

Vuex 复习笔记

Vuex命名空间及如何获取根模块、兄弟模块状态管理器_vuex获取兄弟类 state-CSDN博客

Vuex详解,一文彻底搞懂Vuex-CSDN博客

什么是 Vuex

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

核心概念

  1. State: 存储应用的状态数据。
  2. Getters: 从 state 中派生出一些状态,这些状态可以视为 state 的计算属性。
  3. Mutations: 更改 Vuex 的 store 中的状态的唯一方法。
  4. Actions: 与 mutation 类似,不同在于:
  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
  1. Modules: 将 store 分割成模块(module),每个模块有自己的 state、mutation、action 和 getter,甚至可以嵌套子模块。

使用步骤

  1. 安装 Vuex
   npm install vuex --save
  1. 创建 store
   import Vue from 'vue';
   import Vuex from 'vuex';

   Vue.use(Vuex);

   export default new Vuex.Store({
       state: {
           // 全局状态
       },
       getters: {
           // 全局 getter
       },
       mutations: {
           // 全局 mutation
       },
       actions: {
           // 全局 action
       },
       modules: {
           // 模块
       }
   });
  1. 在 Vue 实例中使用 store
   import store from './store';

   new Vue({
       store,
       render: h => h(App),
   }).$mount('#app');

结合代码详细讲解

目录结构

├── components
│   ├── login.js
│   └── panel.js
├── css
│   └── style.css
├── index.html
├── lib
│   ├── vue.min.js
│   └── vuex.min.js
└── store
    ├── BaseModule.js
    ├── UserModule.js
    └── index.js

BaseModule.js

export default {
  state: {
    welcome: ''
  },
  mutations: {
    say(state, message) {
      state.welcome = message;
    }
  },
  getters: {
    welcome: state => state.welcome
  }
}

UserModule.js

export default {
  state: {
    username: '',
    token: ''
  },
  mutations: {
    login(state, { username, token }) {
      state.username = username;
      state.token = token;
    }
  },
  getters: {
    username: state => state.username,
    token: state => state.token
  }
}

index.js

import Vue from 'vue';
import Vuex from 'vuex';
import BaseModule from './BaseModule';
import UserModule from './UserModule';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    base: BaseModule,
    user: UserModule
  }
});

index.html

<!DOCTYPE html>
<html lang="zn-CH">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./lib/vue.min.js"></script>
    <script src="./lib/vuex.min.js"></script>
    <script src="./store/BaseModule.js"></script>
    <script src="./store/UserModule.js"></script>
    <script src="./store/index.js"></script>
    <link rel="stylesheet" href="./css/style.css">
</head>

<body>
    <div id="app">
        <div class="wrapper" style="width: 900px;">
            <!-- 2. 登录成功后的欢迎界面 -->
            <Panel v-if="token" :username="username">
                {{ welcome }}
            </Panel>

            <!-- 1. 登录界面 -->
            <Login v-else @confirm="login">
                {{ welcome }}
            </Login>
        </div>
    </div>

    <script src="./components/login.js"></script>
    <script src="./components/panel.js"></script>
    <script>
        import store from './store/index.js';

        var app = new Vue({
            el: '#app',
            store, // 添加 store
            computed: {
                welcome() {
                    return this.$store.getters['base/welcome'];
                },
                username() {
                    return this.$store.getters['user/username'];
                },
                token() {
                    return this.$store.getters['user/token'];
                }
            },
            methods: {
                // 回车/点击确认的回调事件
                login(username) {
                    if (username) {
                        this.$store.commit('user/login', { username, token: 'sxgWKnLADfS8hUxbiMWyb' });
                        this.$store.commit('base/say', '登录成功,欢迎你回来!');
                    }
                }
            }
        });
    </script>
</body>

</html>

解释

  1. 模块化存储:在 BaseModule.jsUserModule.js 中定义了两个模块,分别管理不同的状态和 mutation,使用 namespaced: true 可以避免命名冲突。
  2. 集中化状态管理:在 index.js 中创建了 Vuex store,并将模块注册到 store 中。
  3. 绑定 store:在 Vue 实例中绑定了 store,使得组件可以通过 this.$store 访问 Vuex store。
  4. 响应式数据绑定:在 index.html 中的 Vue 实例使用 computed 计算属性从 Vuex store 中获取状态数据,并在模板中使用。
  5. 方法绑定:在 Vue 实例的方法中调用 Vuex 的 commit 方法提交 mutation,更改状态。

例题:消失的 Token

介绍

小蓝开发了一个登录功能,但是在登录界面中输入用户名后点击“确认”按钮并没有如预期般成功进入欢迎界面。但是从出现欢迎语来看,数据已经发生了改变,到底是怎么回事呢?请帮助小蓝排查代码,让登录功能回归正常吧!

准备

目录结构如下:

├── components
│   ├── login.js
│   └── panel.js
├── css
│   └── style.css
├── index.html
├── lib
│   ├── vue.min.js
│   └── vuex.min.js
└── store
    ├── BaseModule.js
    ├── UserModule.js
    └── index.js 

其中:

  • index.html 是主页面。
  • components 是为示例组件文件夹。
  • lib 是存放项目相关依赖的文件夹。
  • store 是 Vuex 状态管理文件夹。
  • css 是存放项目样式的文件夹。

注意:打开环境后发现缺少项目代码,请复制下述命令至命令行进行下载。

cd /home/project
wget https://labfile.oss.aliyuncs.com/courses/18164/dist_03.zip
unzip dist_03.zip
mv dist/* ./
rm -rf dist*

在浏览器中预览 index.html 页面效果如下:

图片[1]曙光博客-随笔小窝Vuex曙光博客-随笔小窝曙光博客

此时输入用户名后回车/点击确定,数据发生改变,但还是停留在登录页,无法正确显示登录成功界面。

目标

找到 index.html 中的 TODO 部分,仔细阅读 store 文件夹下的相关代码并结合 Vuex 相关知识,排查代码中存在的问题,修改后使得登录界面输入 admin 时,点击确认按钮/回车可以正确显示如下界面:

图片[2]曙光博客-随笔小窝Vuex曙光博客-随笔小窝曙光博客

规定

  • 请按照给出的步骤操作,切勿修改默认提供的文件名称、文件夹路径等。
  • 满足需求后,保持 Web 服务处于可以正常访问状态,点击「提交检测」系统会自动检测。

判分标准

  • 本题完全实现题目目标得满分,否则得 0 分。
  • 在 Vuex 中,访问 state 需要通过正确的路径和语法。你提到的 this.$store.state['user/username'] 不能访问是因为 state 对象是一个普通的 JavaScript 对象,不能用这种形式访问嵌套的属性。
  • 正确的访问方式如下:
  • 访问模块的 state console.log(this.$store.state.user.username); console.log(this.$store.state.user.token);
  • 访问带命名空间的 getter
    javascript console.log(this.$store.getters['user/username']); console.log(this.$store.getters['user/token']);
  • 这里是一个完整的示例,说明如何正确访问 Vuex store 中的 state 和 getter。
  • BaseModule.js
  • UserModule.js
  • index.js
  • index.html
  • 解释
  • 访问模块 state: console.log(this.$store.state.user.username); console.log(this.$store.state.user.token); 这是正确的方式,因为 state 对象中 user 模块是一个子对象,直接访问子对象的属性即可。
  • 访问模块 getter:
    javascript console.log(this.$store.getters['user/username']); console.log(this.$store.getters['user/token']);
    使用带命名空间的 getter 访问方式,这样可以确保访问到正确的 getter。
  • 使用这些正确的方式,可以避免访问错误并确保能够正确读取 Vuex store 中的状态和 getter。
<!DOCTYPE html>
<html lang="zn-CH">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./lib/vue.min.js"></script>
    <script src="./lib/vuex.min.js"></script>
    <script src="./store/BaseModule.js"></script>
    <script src="./store/UserModule.js"></script>
    <script src="./store/index.js"></script>
    <link rel="stylesheet" href="./css/style.css">
</head>

<body>
    <div id="app">
        <div class="wrapper" style="width: 900px;">

            <!-- 2. 登录成功后的欢迎界面 -->
            <Panel v-if="token" :username="username">
                {{welcome}}
            </Panel>

            <!-- 1. 登录界面 -->
            <Login v-else @confirm="login">
                {{welcome}}
            </Login>

        </div>
    </div>

    <script src="./components/login.js"></script>
    <script src="./components/panel.js"></script>
    <script>


        var app = new Vue({
            el: '#app',
            store, // 添加 store
            computed: {
                welcome() {
                    return this.$store.getters['welcome'];
                },
                username() {
                    return this.$store.getters['user/username'];
                },
                token() {
                    console.log(this.$store.state['user/username'])
                    console.log(this.$store.state.user.username)
                    return this.$store.getters['user/token'];
                }
            },
            methods: {
                // 回车/点击确认的回调事件
                login(username) {
                    if (username) {
                        this.$store.commit('user/login', { username, token: 'sxgWKnLADfS8hUxbiMWyb' });
                        this.$store.commit('say', '登录成功,欢迎你回来!');
                    }
                }
            }
        });
    </script>
</body>

</html>
图片[3]曙光博客-随笔小窝Vuex曙光博客-随笔小窝曙光博客
© 版权声明
THE END
喜欢就支持一下吧
点赞14赞赏 分享
评论 抢沙发

    暂无评论内容