Vuex入门教程:状态管理库的安装、使用和实例演示

简介:

Vuex是Vue.js的官方状态管理库,用于管理应用程序的状态。本篇博客将介绍如何安装Vuex、创建Vuex Store,并在Vue应用中使用Vuex来访问和修改状态。同时,我们将提供一个实例演示,以更具体地展示Vuex的用法。

正文:

安装Vuex:

首先,我们使用npm或yarn在项目的根目录下安装Vuex:

```
npm install vuex
```

创建Vuex Store:

在项目中创建一个新的JavaScript文件,例如store.js,并编写以下代码:

```js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  },
  actions: {
    increment(context) {
      context.commit('increment')
    }
  },
  getters: {
    doubleCount(state) {
      return state.count * 2
    }
  }
})

export default store
```

在Vue应用中使用Vuex:

在Vue应用的入口文件(一般是main.js)中导入并使用Vuex Store:

```javascript
import Vue from 'vue'
import App from './App.vue'
import store from './store'

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

在组件中访问和修改状态:

现在,我们可以在组件中访问和修改Vuex Store中的状态。在计算属性和方法中使用this.$store.state来访问状态,使用this.$store.commit()来触发状态的变更。

    <template>
      <div>
        <p>Count: {{ count }}</p>
        <p>Double Count: {{ doubleCount }}</p>
        <button @click="increment">Increment</button>
      </div>
    </template>

    <script>
    export default {
      computed: {
        count() {
          return this.$store.state.count
        },
        doubleCount() {
          return this.$store.getters.doubleCount
        }
      },
      methods: {
        increment() {
          this.$store.dispatch('increment')
        }
      }
    }
    </script>

在上述示例中,我们使用this.$store.state.count访问状态,使用this.$store.getters.doubleCount获取计算属性的值,通过this.$store.dispatch('increment')来触发状态的变更。

mapState 辅助函数

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

在组件的computed选项中,使用mapState函数将Vuex状态映射为计算属性。你可以传递一个数组或者对象给mapState函数。

  • 数组语法:

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

computed: mapState(['count'])
  • 对象语法:
computed: mapState({
  count: 'count'
})

上述两种语法只能提供映射,不能计算.如果想要实现计算,需要这样写:

computed: {
  ...mapState(['count']),
  doubleCount() {
    return this.count * 2
  }
}
  • 更高级的对象语法:
computed: mapState({
  count: state => state.count,
  // 或者使用箭头函数
  doubleCount: state => state.count * 2
})

上述代码可以对状态进行更高级的处理,例如对状态进行计算或者过滤。

// 在单独构建的版本中辅助函数为 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
    }
  })
}

Getter

有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

如果有多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它——无论哪种方式都不是很理想。

以下是Getter的用法和示例:

  1. 定义Getter: 在Vuex的Store中,通过定义getters对象来声明Getter。
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: 'Buy groceries', completed: false },
      { id: 2, text: 'Clean the house', completed: true },
      { id: 3, text: 'Walk the dog', completed: false }
    ]
  },
  getters: {
    // Getter用于计算未完成的任务数量
    unfinishedTasks(state) {
      return state.todos.filter(todo => !todo.completed).length
    }
  }
})

在上述示例中,我们定义了一个名为unfinishedTasks的Getter,用于计算未完成的任务数量。

  1. 在组件中使用Getter: 在组件中使用Getter可以通过this.$store.getters来访问。Getter会作为Store的一个属性暴露出来。
<template>
  <div>
    <p>Unfinished Tasks: {{ unfinishedTasks }}</p>
  </div>
</template>

<script>
export default {
  computed: {
    unfinishedTasks() {
      return this.$store.getters.unfinishedTasks
    }
  }
}
</script>

在上述示例中,我们在组件的计算属性中使用this.$store.getters.unfinishedTasks来获取未完成的任务数量。

  1. 在辅助函数中使用Getter: 我们还可以使用mapGetters辅助函数将Getter映射为组件的计算属性,以简化代码。
<template>
  <div>
    <p>Unfinished Tasks: {{ unfinishedTasks }}</p>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters(['unfinishedTasks'])
  }
}
</script>

在上述示例中,我们使用mapGetters将Getter映射为计算属性,可以直接在模板中使用unfinishedTasks

Getter的优势:

  • 提供了一种集中计算和过滤状态的方式,避免了重复计算。
  • 可以将复杂的逻辑封装在Getter中,使组件更加简洁和可维护。
  • Getter是响应式的,当Getter所依赖的状态发生变化时,Getter会自动更新。

总结: Getter是Vuex中用于计算和过滤状态的一种机制,类似于组件中的计算属性。通过定义Getter并在组件中使用,我们可以方便地获取和重用派生状态,提高代码的可读性和可维护性。使用Getter可以有效地管理和操作Store中的状态数据。

Action是Vuex中用于处理异步操作的对象,它可以包含任意的异步操作、调用API请求、提交Mutation等。Action提供了一种将逻辑和异步操作从组件中分离的方式,使得代码更加清晰、可维护,并且方便进行单元测试。

Action的用法和示例:

  1. 定义Action: 在Vuex的Store中,通过定义actions对象来声明Action。
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  },
  actions: {
    incrementAsync(context) {
      setTimeout(() => {
        context.commit('increment')
      }, 1000)
    }
  }
})

在上述示例中,我们定义了一个名为incrementAsync的Action,它会在1秒后调用commit方法来触发incrementMutation。

  1. 在组件中使用Action: 在组件中使用Action可以通过this.$store.dispatch来触发。Action会作为Store的一个方法暴露出来。
  <template>
  <div>
  <p>Count: {{ count }}</p>
  <button @click="incrementAsync">Increment Async</button>
  </div>
  </template>

  <script>
export default {
  computed: {
    count() {
      return this.$store.state.count
    }
  },
  methods: {
    incrementAsync() {
      this.$store.dispatch('incrementAsync')
    }
  }
}
  </script>

在上述示例中,我们在组件的方法中使用this.$store.dispatch来触发incrementAsyncAction。

  1. 在辅助函数中使用Action: 我们还可以使用mapActions辅助函数将Action映射为组件的方法,以简化代码。
<template>
  <div>
  <p>Count: {{ count }}</p>
  <button @click="incrementAsync">Increment Async</button>
  </div>
  </template>

  <script>
  import { mapActions } from 'vuex'

export default {
  computed: {
    count() {
      return this.$store.state.count
    },
  },
  methods: {
    ...mapActions(['incrementAsync'])
  }
}
  </script>

在上述示例中,我们使用mapActions将Action映射为组件的方法,可以直接在模板中使用incrementAsync方法。

Action的优势:

  • 处理异步操作:Action适用于处理异步操作,例如API请求、定时器、延迟等。它们不会阻塞主线程,可以让应用保持响应性。
  • 提交Mutation:Action可以通过commit方法提交Mutation,保持了对状态变更的一致性和追踪性。
  • 组织复杂逻辑:Action可以包含多个异步操作、条件判断、API请求等,使得逻辑更加清晰、可维护,并且可以重用。
  • 方便测试:由于Action是纯函数,不依赖组件实例,因此可以更容易地进行单元测试和模拟。

总而言之,Action提供了一种组织和处理异步操作的方式,使得代码更加清晰、可维护,并且能够更好地管理应用状态的变化。它是Vuex中重要的概念之一,帮助我们构建复杂的应用程序。

Module的用法和示例:

Module是Vuex中用于组织和管理状态的模块化机制。它允许我们将大型的Vuex应用程序拆分为更小、可维护的模块,每个模块都具有自己的状态、mutations、actions、getters等。

通过使用Module,我们可以将相关的状态和逻辑组合在一起,提高代码的可读性、可维护性,并支持团队协作开发。

  1. 定义Module: 在Vuex的Store中,通过使用modules选项来定义Module。
const store = new Vuex.Store({
  modules: {
    cart: {
      state: {
        items: []
      },
      mutations: {
        addItem(state, item) {
          state.items.push(item)
        }
      },
      actions: {
        addToCart(context, item) {
          context.commit('addItem', item)
        }
      },
      getters: {
        cartItemsCount(state) {
          return state.items.length
        }
      }
    }
  }
})

在上述示例中,我们定义了一个名为cart的Module,它包含了items状态、addItemMutation、addToCartAction和cartItemsCountGetter。

  1. 在组件中使用Module: 在组件中使用Module的状态、Mutation、Action和Getter时,需要通过模块路径进行访问。
<template>
  <div>
    <p>Cart Items: {{ cartItemsCount }}</p>
    <button @click="addToCart">Add to Cart</button>
  </div>
</template>

<script>
  export default {
    computed: {
      cartItemsCount() {
        return this.$store.state.cart.items.length
      }
    },
    methods: {
      addToCart() {
        this.$store.dispatch('cart/addToCart', { name: 'Product 1', price: 10 })
      }
    }
  }
</script>

在上述示例中,我们在组件中使用

this.$store.state.cart.items 

来访问cart模块的状态,并使用this.$store.dispatch(‘cart/addToCart’) 来触发addToCartAction。

  1. 在辅助函数中使用Module: 我们还可以使用namespaced选项和mapStatemapMutationsmapActionsmapGetters等辅助函数简化对Module的访问。
<template>
  <div>
    <p>Cart Items: {{ cartItemsCount }}</p>
    <button @click="addToCart">Add to Cart</button>
  </div>
</template>

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

  export default {
    computed: {
      ...mapState('cart', ['cartItemsCount'])
    },
    methods: {
      ...mapActions('cart', ['addToCart'])
    }
  }
</script>

在上述示例中,我们使用mapStatecartItemsCount映射为组件的计算属性,并使用mapActionsaddToCart映射为组件的方法。

例子

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 的状态

模块的局部状态

对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象

const moduleA = {
  state: () => ({
    count: 0
  }),
  mutations: {
    increment (state) {
      // 这里的 `state` 对象是模块的局部状态
      state.count++
    }
  },
  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}

同样,对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState:

const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum ({ state, commit, rootState }) {
      if ((state.count + rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}

对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:

const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

通过使用Module,我们可以将应用状态拆分为更小的模块,使得代码结构更清晰、可维护。每个Module都可以独立开发和测试,且可以嵌套使用,形成层次化的状态管理结构。这对于大型应用程序和团队协作开发非常有益。

实例演示:

在本示例中,我们将创建两个组件:Counter.vue和Button.vue。Counter组件用于显示计数值,Button组件用于触发计数器的增加。

  <!-- Counter.vue -->
  <template>
    <div>
      <p>Count: {{ count }}</p>
    </div>
  </template>

  <script>
  import { mapState } from 'vuex'

  export default {
    computed: {
      ...mapState(['count'])
    }
  }
  </script>
  
    <!-- Button.vue -->
    <template>
      <div>
        <button @click="increment">Increment</button>
      </div>
    </template>

    <script>
    import { mapActions } from 'vuex'

    export default {
      methods: {
        ...mapActions(['increment'])
      }
    }
    </script>

创建根组件:
在App.vue中,使用Counter和Button组件,并通过Vuex共享状态。

    <template>
      <div>
        <h1>Counter App</h1>
        <Counter />
        <Button />
      </div>
    </template>

    <script>
    import Counter from './Counter.vue'
    import Button from './Button.vue'

    export default {
      components: {
        Counter,
        Button
      }
    }
    </script>
    

在这个示例中,Counter组件通过计算属性使用mapState辅助函数将Vuex的状态映射为组件的数据。Button组件通过方法使用mapActions辅助函数将Vuex的动作映射为组件的方法。

这样,当我们在浏览器中访问应用时,将会看到一个计数器和一个按钮。点击按钮会增加计数值,并实时更新到Counter组件上。文章来源地址https://uudwc.com/A/dMNq1

原文地址:https://blog.csdn.net/kilig_CSM/article/details/131403791

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年06月27日 16:10
Python之numpy函数
下一篇 2023年06月27日 16:10