前端面试十之vuex

发布于:2025-06-24 ⋅ 阅读:(15) ⋅ 点赞:(0)

Vuex 是一个专为 Vue.js 应用程序设计的状态管理模式和库,它集中管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。以下是关于 Vuex 的详细介绍:

1. 核心概念

  • State(状态)

    • 它是 Vuex 中存储状态的地方,类似于普通 Vue 组件的 data 选项。所有组件的状态都存储在 Vuex 的 state 中,组件通过 mapState 或直接从 Vuex 中读取状态。

      const store = new Vuex.Store({
        state: {
          count: 0
        }
      });

      Getter(获取器)

    • 类似于 Vue 组件中的计算属性,用于从 state 中派生出一些状态。Getter 接收 state 作为第一个参数,返回一个计算后的值。

      const store = new Vuex.Store({
        state: {
          todos: [
            { id: 1, text: '...', done: true },
            { id: 2, text: '...', done: false }
          ]
        },
        getters: {
          doneTodos: state => {
            return state.todos.filter(todo => todo.done);
          }
        }
      });

      Mutation(变异)

    • 是修改 Vuex 中状态的唯一方法。Mutation 是同步函数,接收 state 作为第一个参数,接收额外的参数作为第二个参数。

    • 例如:

      const store = new Vuex.Store({
        state: {
          count: 1
        },
        mutations: {
          increment(state) {
            state.count++;
          }
        }
      });

      Action(动作)

    • 类似于 Mutation,但它可以包含异步操作。Action 提交的是 Mutation,而不是直接修改状态。Action 接收一个上下文对象(包含 statecommit 等方法)作为第一个参数。

    • 例如:

      const store = new Vuex.Store({
        state: {
          count: 0
        },
        mutations: {
          increment(state) {
            state.count++;
          }
        },
        actions: {
          incrementAsync({ commit }) {
            setTimeout(() => {
              commit('increment');
            }, 1000);
          }
        }
      });

      Module(模块)

    • Vuex 允许将状态分割成模块(Module)。每个模块拥有自己的 statemutationactiongetter,使得代码更加模块化。

      const moduleA = {
        state: { ... },
        mutations: { ... },
        actions: { ... },
        getters: { ... }
      };
      const moduleB = {
        state: { ... },
        mutations: { ... },
        actions: { ... }
      };
      const store = new Vuex.Store({
        modules: {
          a: moduleA,
          b: moduleB
        }
      });

      2. 工作原理

    • Vuex 的核心是 store,它是一个全局的存储对象,用于存储应用的状态。

    • 组件通过 this.$store.statemapState 辅助函数来读取状态。

    • 当需要修改状态时,组件通过 this.$store.commit 提交一个 Mutation,Mutation 通过同步方式修改状态。

    • 如果需要执行异步操作,组件通过 this.$store.dispatch 触发一个 Action,Action 内部再提交 Mutation 来修改状态。

    • Vuex 的状态更新是响应式的,当状态发生变化时,Vue 组件会自动更新

3. 使用场景

  • Vuex 主要用于管理全局状态,例如用户登录状态、主题切换、购物车数据等。

  • 当应用的状态变得复杂,多个组件需要共享状态时,使用 Vuex 可以更好地管理状态。

4. 优点

  • 集中管理状态:Vuex 将状态集中管理,避免了组件之间复杂的通信方式。

  • 状态可预测:通过 Mutation 和 Action 的规则,确保状态的变化是可预测的。

  • 方便调试:Vuex 提供了开发者工具,可以方便地查看状态的变化历史。

5.实战 

下面是一个完整的示例,展示如何将 Vuex 的逻辑写在一个单独的 JavaScript 文件中,并在 Vue 组件中使用它来修改姓名。

1. 创建 Vuex Store

首先,创建一个名为 store.js 的文件,用于定义 Vuex 的逻辑。

// store.js
import Vue from 'vue';
import Vuex from 'vuex';

// 使用 Vuex 插件
Vue.use(Vuex);

// 定义状态
const state = {
  name: '张三' // 初始姓名
};

// 定义 Mutation
const mutations = {
  // 修改姓名的 Mutation
  setName(state, newName) {
    state.name = newName;
  }
};

// 创建 Vuex Store
export default new Vuex.Store({
  state,
  mutations
});
2. 在 Vue 应用中引入 Vuex Store

在主文件(如 main.jsapp.js)中引入 store.js,并将其挂载到 Vue 实例中。

// main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store'; // 引入 Vuex Store

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

 

3. 在组件中使用 Vuex

在 Vue 组件中,通过 this.$store 来访问 Vuex 的状态和提交 Mutation。

示例组件代码:
<template>
  <div>
    <h1>当前姓名:{{ name }}</h1>
    <input v-model="newName" placeholder="请输入新姓名" />
    <button @click="updateName">修改姓名</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      newName: '' // 用于双向绑定输入框的值
    };
  },
  computed: {
    // 从 Vuex 中获取姓名
    name() {
      return this.$store.state.name;
    }
  },
  methods: {
    // 修改姓名的方法
    updateName() {
      // 提交 Mutation 来修改姓名
      this.$store.commit('setName', this.newName);
      // 清空输入框
      this.newName = '';
    }
  }
};
</script>
5. 运行效果
  • 页面上显示当前姓名(初始为“张三”)。

  • 用户可以在输入框中输入新的姓名,并点击“修改姓名”按钮。

  • 点击按钮后,姓名会更新为输入框中的值,并且输入框清空。

6. 关键点总结
  • 状态存储:姓名存储在 Vuex 的 state 中。

  • 修改状态:通过提交 Mutation(setName)来修改状态。

  • 组件交互:组件通过 this.$store.state 获取状态,通过 this.$store.commit 提交 Mutation。

 6.mapState

mapState 是 Vuex 中的一个非常有用的辅助函数,它可以帮助我们更方便地在组件中生成与 Vuex 状态相关的计算属性,从而避免手动编写冗长的代码。使用 mapState,可以从 Vuex 的 state 中直接提取出状态,并将其映射为组件的计算属性。

1. mapState 的作用

mapState 的主要作用是简化从 Vuex 的 state 中提取状态的过程。它会根据传入的参数自动生成计算属性,并确保这些计算属性能够响应式地更新。

2. 使用 mapState 生成多个计算属性的示例

假设我们有一个 Vuex Store,其中存储了用户的名字和年龄。我们希望在组件中使用 mapState 来生成对应的计算属性,并提供修改名字和年龄的功能。

步骤 1:定义 Vuex Store

store.js 文件中定义 Vuex 的状态、Mutation 和 Action。

// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const state = {
  name: '张三', // 初始名字
  age: 20 // 初始年龄
};

const mutations = {
  setName(state, newName) {
    state.name = newName;
  },
  setAge(state, newAge) {
    state.age = newAge;
  }
};

export default new Vuex.Store({
  state,
  mutations
});
步骤 2:在组件中使用 mapState

在 Vue 组件中,通过 mapState 生成计算属性,并提供修改名字和年龄的方法。

首先,需要从 vuex 中导入 mapState

import { mapState } from 'vuex';

然后,在组件中使用 mapState 来生成计算属性:

<template>
  <div>
    <h1>用户信息</h1>
    <p>名字:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <input v-model="newName" placeholder="请输入新名字" />
    <button @click="updateName">修改名字</button>
    <input v-model.number="newAge" placeholder="请输入新年龄" type="number" />
    <button @click="updateAge">修改年龄</button>
  </div>
</template>

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

export default {
  data() {
    return {
      newName: '', // 用于双向绑定输入框的新名字
      newAge: null // 用于双向绑定输入框的新年龄
    };
  },
  computed: {
    // 使用 mapState 生成计算属性
    ...mapState(['name', 'age'])
  },
  methods: {
    // 修改名字
    updateName() {
      this.$store.commit('setName', this.newName);
      this.newName = ''; // 清空输入框
    },
    // 修改年龄
    updateAge() {
      this.$store.commit('setAge', this.newAge);
      this.newAge = null; // 清空输入框
    }
  }
};
</script>
3. mapState 的不同用法

mapState 可以接受多种参数形式,来生成不同的计算属性:

直接使用数组

如果你只需要将 Vuex 的 state 中的状态直接映射为组件的计算属性,可以直接传递一个数组:

computed: {
  ...mapState(['name', 'age'])
}

这会生成两个计算属性 nameage,它们的内容分别等于 Vuex 的 state.namestate.age

使用对象映射

如果你需要对生成的计算属性进行重命名或进行一些额外的处理,可以通过对象映射的方式使用 mapState

computed: {
  ...mapState({
    userName: state => state.name, // 将 Vuex 的 state.name 映射为计算属性 userName
    userAge: state => state.age // 将 Vuex 的 state.age 映射为计算属性 userAge
  })
}

在模板中,你可以直接使用 userNameuserAge,而不是 nameage

完整示例代码

以下是完整的项目代码:

store.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const state = {
  name: '张三',
  age: 20
};

const mutations = {
  setName(state, newName) {
    state.name = newName;
  },
  setAge(state, newAge) {
    state.age = newAge;
  }
};

export default new Vuex.Store({
  state,
  mutations
});

main.js

import Vue from 'vue';
import App from './App.vue';
import store from './store';

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

组件(App.vue

<template>
  <div>
    <h1>用户信息</h1>
    <p>名字:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <input v-model="newName" placeholder="请输入新名字" />
    <button @click="updateName">修改名字</button>
    <input v-model.number="newAge" placeholder="请输入新年龄" type="number" />
    <button @click="updateAge">修改年龄</button>
  </div>
</template>

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

export default {
  data() {
    return {
      newName: '',
      newAge: null
    };
  },
  computed: {
    // 使用 mapState 生成计算属性
    ...mapState(['name', 'age'])
  },
  methods: {
    updateName() {
      this.$store.commit('setName', this.newName);
      this.newName = '';
    },
    updateAge() {
      this.$store.commit('setAge', this.newAge);
      this.newAge = null;
    }
  }
};
</script>
4. 总结
  • mapState 是一个非常便捷的工具,可以简化从 Vuex 状态到组件计算属性的映射过程。

  • 它可以接受数组或对象作为参数,满足不同的使用需求。

  • 使用 mapState 可以让组件的代码更加简洁,也更容易维护。

7.mapMutations

mapMutations 是 Vuex 提供的一个辅助函数,用于简化在组件中提交 Mutation 的操作。它允许你直接在组件的方法中调用 Mutation,而无需手动使用 this.$store.commit。这使得代码更加简洁,也更容易维护。

1. mapMutations 的作用

mapMutations 的主要作用是将 Vuex 的 Mutation 映射为组件方法。它接受一个数组或对象作为参数,根据参数的类型生成对应的组件方法。

2. 使用 mapMutations 的示例

假设我们有一个 Vuex Store,其中定义了修改名字和年龄的 Mutation。我们希望在组件中使用 mapMutations 来简化提交这些 Mutation 的操作。

store.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const state = {
  name: '张三',
  age: 20
};

const mutations = {
  setName(state, newName) {
    state.name = newName;
  },
  setAge(state, newAge) {
    state.age = newAge;
  }
};

export default new Vuex.Store({
  state,
  mutations
});

main.js

import Vue from 'vue';
import App from './App.vue';
import store from './store';

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

组件(App.vue

<template>
  <div>
    <h1>用户信息</h1>
    <p>名字:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <input v-model="newName" placeholder="请输入新名字" />
    <button @click="setName(newName)">修改名字</button>
    <input v-model.number="newAge" placeholder="请输入新年龄" type="number" />
    <button @click="setAge(newAge)">修改年龄</button>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex';

export default {
  data() {
    return {
      newName: '',
      newAge: null
    };
  },
  computed: {
    // 使用 mapState 生成计算属性
    ...mapState(['name', 'age'])
  },
  methods: {
    // 使用 mapMutations 生成组件方法
    ...mapMutations(['setName', 'setAge'])
  }
};
</script>
3. 总结
  • mapMutations 是一个非常便捷的工具,可以简化在组件中提交 Mutation 的操作。

  • 它可以接受数组或对象作为参数,满足不同的使用需求。

  • 使用 mapMutations 可以让组件的代码更加简洁,也更容易维护。

8.mapActions 

mapActions 是 Vuex 提供的一个辅助函数,用于简化在组件中触发 Action 的操作。它允许你直接在组件的方法中调用 Action,而无需手动使用 this.$store.dispatch。这使得代码更加简洁,也更容易维护。 

1. mapActions 的作用

mapActions 的主要作用是将 Vuex 的 Action 映射为组件方法。它接受一个数组或对象作为参数,根据参数的类型生成对应的组件方法。

2. 使用 mapActions 的示例

假设我们有一个 Vuex Store,其中定义了修改名字和年龄的 Action。我们希望在组件中使用 mapActions 来简化触发这些 Action 的操作。

步骤 1:定义 Vuex Store

store.js 文件中定义 Vuex 的状态、Mutation 和 Action。

// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const state = {
  name: '张三', // 初始名字
  age: 20 // 初始年龄
};

const mutations = {
  setName(state, newName) {
    state.name = newName;
  },
  setAge(state, newAge) {
    state.age = newAge;
  }
};

const actions = {
  updateName({ commit }, newName) {
    commit('setName', newName);
  },
  updateAge({ commit }, newAge) {
    commit('setAge', newAge);
  }
};

export default new Vuex.Store({
  state,
  mutations,
  actions
});
步骤 2:在组件中使用 mapActions

在 Vue 组件中,通过 mapActions 生成组件方法,并调用这些方法来触发 Action。

首先,需要从 vuex 中导入 mapActions

import { mapState, mapActions } from 'vuex';

然后,在组件中使用 mapActions 来生成方法:

<template>
  <div>
    <h1>用户信息</h1>
    <p>名字:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <input v-model="newName" placeholder="请输入新名字" />
    <button @click="updateName(newName)">修改名字</button>
    <input v-model.number="newAge" placeholder="请输入新年龄" type="number" />
    <button @click="updateAge(newAge)">修改年龄</button>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex';

export default {
  data() {
    return {
      newName: '', // 用于双向绑定输入框的新名字
      newAge: null // 用于双向绑定输入框的新年龄
    };
  },
  computed: {
    // 使用 mapState 生成计算属性
    ...mapState(['name', 'age'])
  },
  methods: {
    // 使用 mapActions 生成组件方法
    ...mapActions(['updateName', 'updateAge'])
  }
};
</script>
3. mapActions 的不同用法

mapActions 可以接受多种参数形式,来生成不同的组件方法:

直接使用数组

如果你只需要将 Vuex 的 Action 直接映射为组件方法,可以直接传递一个数组:

methods: {
  ...mapActions(['updateName', 'updateAge'])
}

这会生成两个组件方法 updateNameupdateAge,它们的内容分别等于 this.$store.dispatch('updateName', ...)this.$store.dispatch('updateAge', ...)

使用对象映射

如果你需要对生成的组件方法进行重命名或进行一些额外的处理,可以通过对象映射的方式使用 mapActions

methods: {
  ...mapActions({
    changeName: 'updateName', // 将 Vuex 的 updateName 映射为组件方法 changeName
    changeAge: 'updateAge' // 将 Vuex 的 updateAge 映射为组件方法 changeAge
  })
}

在模板中,你可以直接使用 changeNamechangeAge,而不是 updateNameupdateAge

5. 总结
  • mapActions 是一个非常便捷的工具,可以简化在组件中触发 Action 的操作。

  • 它可以接受数组或对象作为参数,满足不同的使用需求。

  • 使用 mapActions 可以让组件的代码更加简洁,也更容易维护。

9.dispatch方法 

dispatch 是 Vuex 中用于触发 Action 的方法。它允许你在组件或其他地方调用 Vuex 的 Action,从而执行异步操作或一系列的 Mutation。dispatch 是 Vuex 中处理异步逻辑的核心方法,它提供了灵活的方式来管理复杂的状态更新。

1. dispatch 的作用

dispatch 的主要作用是触发 Vuex 的 Action。Action 可以包含异步操作,如 API 请求、延时操作等。通过 dispatch,你可以在组件中调用这些 Action,从而间接地修改 Vuex 的状态。

2. dispatch 的基本用法

dispatch 的基本语法如下:

this.$store.dispatch('actionName', payload);
  • actionName:要触发的 Action 的名称。

  • payload:传递给 Action 的参数,可以是任何类型(字符串、数字、对象等)。

3. 示例

假设我们有一个 Vuex Store,其中定义了一个 Action 用于更新用户信息。我们将在组件中使用 dispatch 来触发这个 Action。

步骤 1:定义 Vuex Store

store.js 文件中定义 Vuex 的状态、Mutation 和 Action。

// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const state = {
  user: {
    name: '张三',
    age: 20
  }
};

const mutations = {
  updateUser(state, userData) {
    state.user.name = userData.name;
    state.user.age = userData.age;
  }
};

const actions = {
  updateUser({ commit }, userData) {
    // 模拟异步操作
    setTimeout(() => {
      commit('updateUser', userData);
    }, 1000);
  }
};

export default new Vuex.Store({
  state,
  mutations,
  actions
});
步骤 2:在组件中使用 dispatch

在 Vue 组件中,通过 this.$store.dispatch 调用 Action。

<template>
  <div>
    <h1>用户信息</h1>
    <p>名字:{{ user.name }}</p>
    <p>年龄:{{ user.age }}</p>
    <input v-model="newName" placeholder="请输入新名字" />
    <input v-model.number="newAge" placeholder="请输入新年龄" type="number" />
    <button @click="updateUser">更新用户信息</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      newName: '',
      newAge: null
    };
  },
  computed: {
    user() {
      return this.$store.state.user;
    }
  },
  methods: {
    updateUser() {
      this.$store.dispatch('updateUser', {
        name: this.newName,
        age: this.newAge
      });
    }
  }
};
</script>
4. dispatch 的高级用法

dispatch 也可以返回一个 Promise,这使得你可以处理 Action 的异步结果。例如,你可以在 Action 中执行异步操作,并在组件中等待这些操作完成。

修改 Action

让 Action 返回一个 Promise:

const actions = {
  updateUser({ commit }, userData) {
    return new Promise((resolve, reject) => {
      // 模拟异步操作
      setTimeout(() => {
        commit('updateUser', userData);
        resolve();
      }, 1000);
    });
  }
};
在组件中处理 Promise

在组件中等待 Action 完成:

<template>
  <div>
    <h1>用户信息</h1>
    <p>名字:{{ user.name }}</p>
    <p>年龄:{{ user.age }}</p>
    <input v-model="newName" placeholder="请输入新名字" />
    <input v-model.number="newAge" placeholder="请输入新年龄" type="number" />
    <button @click="updateUser">更新用户信息</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      newName: '',
      newAge: null
    };
  },
  computed: {
    user() {
      return this.$store.state.user;
    }
  },
  methods: {
    async updateUser() {
      try {
        await this.$store.dispatch('updateUser', {
          name: this.newName,
          age: this.newAge
        });
        alert('用户信息更新成功!');
      } catch (error) {
        alert('用户信息更新失败:' + error.message);
      }
    }
  }
};
</script>
5. 总结
  • dispatch 是 Vuex 中用于触发 Action 的方法,允许你在组件或其他地方调用 Action。

  • 基本用法this.$store.dispatch('actionName', payload)

  • 高级用法dispatch 可以返回一个 Promise,使得你可以处理 Action 的异步结果。

  • 灵活性dispatch 是一个通用方法,可以在任何地方调用,适用于复杂的调用场景。


网站公告

今日签到

点亮在社区的每一天
去签到