• 作者:老汪软件技巧
  • 发表时间:2024-09-25 04:00
  • 浏览量:

在现代前端框架中,状态管理是一个重要的组成部分,它有助于组织和维护应用程序的状态。Svelte 和 Vue.js 分别使用 Svelte Store 和 Vuex 作为它们的状态管理解决方案。

状态管理是单页应用(SPA)中的一个关键问题,特别是在大型应用中,状态的集中管理可以让状态变得更容易追踪和维护。Svelte 和 Vue.js 都提供了各自的状态管理机制,但它们的设计哲学和实现细节有所不同。

Svelte Store

Svelte 的状态管理是内置于框架之中的,它提供了一个叫做“store”的API,用于在组件之间共享状态。Svelte Store 可以分为三种类型:readable、writable 和 derived。

创建 Store

Readable StoreReadable store 只能被订阅,不能直接修改。

import { readable } from 'svelte/store';
const count = readable(0, set => {
  let latestCount = 0;
  const subscriber = count => {
    latestCount = count;
    set(latestCount);
  };
  return {
    subscribe: subscriber
  };
});

Writable Store

Writable store 可以被订阅也可以被修改。

import { writable } from 'svelte/store';
const count = writable(0);
count.set(1); // 修改值
count.update(n => n + 1); // 更新值

Derived Store

Derived store 是根据其他 store 计算得出的新 store。

import { derived } from 'svelte/store';
const doubleCount = derived(count, $count => $count * 2);

使用 Store

在 Svelte 组件中使用 store 很简单,只需要通过 $ 符号来访问 store 的值。


{localCount}

Vuex

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

创建 Store

首先需要安装 Vuex:

npm install vuex

然后创建 store:

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    increment({ commit }) {
      commit('increment');
    }
  },
  getters: {
    doubleCount(state) {
      return state.count * 2;
    }
  }
});

使用 Store

在 Vue 组件中使用 store:

<template>
  <div>
    <h1>{{ doubleCount }}h1>
    <button @click="increment">Incrementbutton>
  div>
template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
  computed: {
    ...mapGetters(['doubleCount'])
  },
  methods: {
    ...mapActions(['increment'])
  }
};
script>

Svelte Store复杂状态管理

Svelte Store 可以用于管理更复杂的状态,例如嵌套对象或数组。

示例:管理用户信息

import { writable } from 'svelte/store';
const user = writable({
  name: 'Alice',
  email: 'alice@example.com',
  posts: []
});
function addUserPost(post) {
  user.update(u => ({
    ...u,
    posts: [...u.posts, post]
  }));
}
export { user, addUserPost };

使用示例


User: {localUser.name}

Email: {localUser.email}

    {#each localUser.posts as post (post.title)}
  • {post.title}
  • {/each}

组合多个 Store

可以组合多个 Store 来创建更复杂的状态管理逻辑。

示例:组合多个 Store

import { writable } from 'svelte/store';
const count = writable(0);
const doubleCount = writable(0);
function updateCounts() {
  doubleCount.set($count * 2);
}
count.subscribe(updateCounts);
export { count, doubleCount };

使用示例


Count: {localCount}

Double Count: {localDoubleCount}

Vuex模块化状态管理

Vuex 支持模块化的状态管理,可以将状态拆分成多个模块,每个模块有自己的 state、mutations、actions 和 getters。

示例:模块化状态管理

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const userModule = {
  state: {
    name: 'Alice',
    email: 'alice@example.com',
    posts: []
  },
  mutations: {
    addPost(state, post) {
      state.posts.push(post);
    }
  },
  actions: {
    addPost({ commit }, post) {
      commit('addPost', post);
    }
  },
  getters: {
    allPosts(state) {
      return state.posts;
    }
  }
};
const store = new Vuex.Store({
  modules: {
    user: userModule
  }
});
export default store;

使用示例

<template>
  <div>
    <h1>User: {{ user.name }}h1>
    <h2>Email: {{ user.email }}h2>
    <ul>
      <li v-for="post in user.allPosts" :key="post.title">{{ post.title }}li>
    ul>
    <button @click="addPost">Add Postbutton>
  div>
template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
  computed: {
    ...mapState('user', ['name', 'email', 'allPosts'])
  },
  methods: {
    ...mapActions('user', ['addPost'])
  }
};
script>

命名空间

在模块化状态下,可以使用命名空间来避免状态和方法冲突。

示例:使用命名空间

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const userModule = {
  namespaced: true,
  state: {
    name: 'Alice',
    email: 'alice@example.com',
    posts: []
  },
  mutations: {
    addPost(state, post) {
      state.posts.push(post);
    }
  },
  actions: {
    addPost({ commit }, post) {
      commit('addPost', post);
    }
  },
  getters: {
    allPosts(state) {
      return state.posts;
    }
  }
};
const store = new Vuex.Store({
  modules: {
    user: userModule
  }
});
export default store;

使用示例

<template>
  <div>
    <h1>User: {{ user.name }}h1>
    <h2>Email: {{ user.email }}h2>
    <ul>
      <li v-for="post in user.allPosts" :key="post.title">{{ post.title }}li>
    ul>
    <button @click="addPost">Add Postbutton>
  div>
template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
  computed: {
    ...mapState('user', ['name', 'email', 'allPosts'])
  },
  methods: {
    ...mapActions('user', ['addPost'])
  }
};
script>

实战案例Svelte Store 实战案例

假设我们需要实现一个简单的待办事项列表应用。

Store 文件 (store.js)

import { writable } from 'svelte/store';
const todos = writable([
  { id: 1, text: 'Learn Svelte', done: false },
  { id: 2, text: 'Build an app', done: false }
]);
function addTodo(text) {
  todos.update(todos => [
    ...todos,
    { id: Date.now(), text, done: false }
  ]);
}
function toggleTodo(id) {
  todos.update(todos => todos.map(todo =>
    todo.id === id ? { ...todo, done: !todo.done } : todo
  ));
}
function removeTodo(id) {
  todos.update(todos => todos.filter(todo => todo.id !== id));
}
export { todos, addTodo, toggleTodo, removeTodo };

主组件 (App.svelte)


To-Do List

    {#each localTodos as todo (todo.id)}
  • handleToggleTodo(todo.id)} /> {todo.text}
  • {/each}

Vuex 实战案例

同样,我们实现一个待办事项列表应用,这次使用 Vuex 进行状态管理。

Store 文件 (store.js)

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: 'Learn Vue', done: false },
      { id: 2, text: 'Build an app', done: false }
    ]
  },
  mutations: {
    addTodo(state, text) {
      state.todos.push({ id: Date.now(), text, done: false });
    },
    toggleTodo(state, id) {
      const todo = state.todos.find(todo => todo.id === id);
      if (todo) {
        todo.done = !todo.done;
      }
    },
    removeTodo(state, id) {
      state.todos = state.todos.filter(todo => todo.id !== id);
    }
  },
  actions: {
    addTodo({ commit }, text) {
      commit('addTodo', text);
    },
    toggleTodo({ commit }, id) {
      commit('toggleTodo', id);
    },
    removeTodo({ commit }, id) {
      commit('removeTodo', id);
    }
  },
  getters: {
    todos: state => state.todos
  }
});
export default store;

主组件 (App.vue)

<template>
  <main>
    <h1>To-Do Listh1>
    <input type="text" v-model="newTodoText" placeholder="Add a new to-do" />
    <button @click="addTodo">Addbutton>
    <ul>
      <li v-for="todo in todos" :key="todo.id">
        <input type="checkbox" :checked="todo.done" @change="toggleTodo(todo.id)" />
        <span :style="{ 'text-decoration': todo.done ? 'line-through' : 'none' }">{{ todo.text }}span>
        <button @click="removeTodo(todo.id)">Removebutton>
      li>
    ul>
  main>
template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
  data() {
    return {
      newTodoText: ''
    };
  },
  computed: {
    ...mapState(['todos'])
  },
  methods: {
    ...mapActions(['addTodo', 'toggleTodo', 'removeTodo'])
  }
};
script>

对比分析

性能

学习曲线

生态系统

适用场景