详解Vue中状态管理Vuex

详解Vue中状态管理Vuex

在Vue的大型应用中,数据状态的管理变得异常重要。Vuex是Vue中一个集中式的状态管理器,可以帮助我们方便地管理不同组件之间共享的数据。

Vuex核心概念

State

Vuex使用单一状态树,即用一个对象来包含全部应用层级的状态。所有组件的状态存储在一个对象中,这个对象我们称之为state。Vuex的state是响应式的,当state中的数据发生改变时,对应的组件会自动重新渲染。

// 定义一个state
const state = {
  count: 0
}

Mutations

进行状态的改变可以使用mutations。每个mutation都有一个字符串的事件类型和一个回调函数。我们需要改变store的状态,唯一的方法就是明确地提交mutation。

// 定义一个mutation
const mutations = {
  increment(state) {
    state.count++
  }
}

Actions

Actions类似于Mutations,不同之处在于Actions提交mutation而不是直接变更状态。Actions可以包含任意异步操作。

// 定义一个action
const actions = {
  increment(context) {  // context是一个对象,包含state、commit、dispatch等属性
    context.commit('increment')
  }
}

Getters

Vuex的getters用于从store中的state中派生出一些状态,例如我们需要对state中的数据进行一些操作再返回。Getters接受state作为其第一个参数。

// 定义一个getter
const getters = {
  doubleCount(state) {
    return state.count * 2
  }
}

使用Vuex

安装Vuex:

npm install vuex --save

在main.js中引入Vuex并注册:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

创建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
    }
  }
})

在组件中使用Vuex:

<template>
  <div>
    <p>{{count}}</p>
    <button @click="increment">Increment</button>
    <p>{{doubleCount}}</p>
  </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>

我们可以看到,在组件中使用不同的方式来获取state、commit mutation、dispatch action和获取getter。

示例1

现在我们有一个需要展示的列表数据,可以进行筛选、排序和分页等操作。我们使用Vuex来存储和管理这个数据列表,同时处理筛选、排序和分页等状态。

我们的state需要包含:

  • 列表数据
  • 当前页码
  • 每页展示数量
  • 筛选条件
  • 排序方式

我们定义一个mutations,用来改变列表数据:

const mutations = {
  setList(state, list) {
    state.list = list
  }
}

我们定义一个actions,获取列表数据并提交mutation:

const actions = {
  getList(context) {
    // 这里是异步操作获取数据
    const list = [...]
    context.commit('setList', list)
  }
}

我们定义一些getters,用于获取当前页数据、当前页总数、筛选后的数据等:

const getters = {
  currentPageData(state) {
    const begin = (state.currentPage - 1) * state.pageSize
    const end = begin + state.pageSize - 1
    return state.list.slice(begin, end + 1)
  },
  currentPageTotal(state, getters) {
    return Math.ceil(getters.filteredList.length / state.pageSize)
  },
  filteredList(state) {
    let list = [...state.list]
    if (state.filter) {
      list = list.filter(item => item.name === state.filter)
    }
    if (state.sort) {
      const sortBy = state.sort.split('_')[0]
      const sortDir = state.sort.split('_')[1]
      list = list.sort((a, b) => {
        if (sortDir === 'asc') {
          return a[sortBy] - b[sortBy]
        } else {
          return b[sortBy] - a[sortBy]
        }
      })
    }
    return list
  }
}

在组件中使用Vuex:

<template>
  <div>
    <table>
      <thead>
        <tr>
          <th>
            <button @click="sort('id')">ID</button>
          </th>
          <th>
            <button @click="sort('name')">Name</button>
          </th>
          <th>
            <button @click="sort('age')">Age</button>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in list" :key="item.id">
          <td>{{item.id}}</td>
          <td>{{item.name}}</td>
          <td>{{item.age}}</td>
        </tr>
      </tbody>
    </table>
    <div>
      <button :disabled="currentPage === 1" @click="setCurrentPage(currentPage - 1)">Prev</button>
      <button v-for="page in currentPageTotal" :key="page" :class="{ active: page === currentPage }" @click="setCurrentPage(page)">{{page}}</button>
      <button :disabled="currentPage === currentPageTotal" @click="setCurrentPage(currentPage + 1)">Next</button>
    </div>
  </div>
</template>

<script>
export default {
  computed: {
    list() {
      return this.$store.getters.currentPageData
    },
    currentPage() {
      return this.$store.state.currentPage
    },
    currentPageTotal() {
      return this.$store.getters.currentPageTotal
    }
  },
  methods: {
    getList() {
      this.$store.dispatch('getList')
    },
    setCurrentPage(page) {
      this.$store.state.currentPage = page
    },
    sort(sortBy) {
      if (this.$store.state.sort === sortBy + '_asc') {
        this.$store.state.sort = sortBy + '_desc'
      } else {
        this.$store.state.sort = sortBy + '_asc'
      }
    }
  },
  created() {
    this.getList()
  }
}
</script>

示例2

现在我们有一个需要在线编辑的用户信息表单,表单中包含了用户名、性别和年龄等信息。我们使用Vuex来存储和管理这个表单数据。

我们的state需要包含:

  • 用户名
  • 性别
  • 年龄

我们定义一个mutations,用来改变表单数据:

const mutations = {
  setUsername(state, username) {
    state.username = username
  },
  setGender(state, gender) {
    state.gender = gender
  },
  setAge(state, age) {
    state.age = age
  }
}

我们定义一些getters,用于获取表单数据:

const getters = {
  formData(state) {
    return {
      username: state.username,
      gender: state.gender,
      age: state.age
    }
  }
}

在组件中使用Vuex:

<template>
  <div>
    <input type="text" v-model="username">
    <input type="radio" name="gender" value="M" v-model="gender"> Male
    <input type="radio" name="gender" value="F" v-model="gender"> Female
    <input type="number" v-model="age">
  </div>
</template>

<script>
export default {
  computed: {
    username: {
      get() {
        return this.$store.state.username
      },
      set(newValue) {
        this.$store.commit('setUsername', newValue)
      }
    },
    gender: {
      get() {
        return this.$store.state.gender
      },
      set(newValue) {
        this.$store.commit('setGender', newValue)
      }
    },
    age: {
      get() {
        return this.$store.state.age
      },
      set(newValue) {
        this.$store.commit('setAge', newValue)
      }
    },
    formData() {
      return this.$store.getters.formData
    }
  }
}
</script>

我们可以看到,在组件中使用了computed属性来获取state和提交mutation。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Vue中状态管理Vuex - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • 项目中一键添加husky实现详解

    下面是项目中一键添加Husky实现的完整攻略示例,分为如下几个步骤: 步骤一:初始化项目 首先,我们需要创建一个新项目并初始化它。我们可以通过以下命令创建并初始化一个名为“my-project”的新项目。 mkdir my-project cd my-project npm init -y 这个命令会创建一个名为“my-project”的文件夹,并初始化一个…

    Vue 2023年5月28日
    00
  • vue源码学习之Object.defineProperty 对数组监听

    下面我来为您介绍一下“Vue源码学习之Object.defineProperty对数组监听”的攻略。 1. Object.defineProperty的基本用法 首先,我们来了解一下Object.defineProperty的基本用法及其作用。 Object.defineProperty是ES5新增的一个API,它可以用来精确添加或修改对象的属性。该方法将直…

    Vue 2023年5月29日
    00
  • Vue.js 前端路由和异步组件介绍

    Vue.js前端路由和异步组件是Vue.js框架中非常重要的两个概念。接下来,我将详细讲解Vue.js前端路由和异步组件的使用方法和注意事项。 前端路由 前端路由是指通过改变URL地址来实现页面的切换和显示的技术。在Vue.js中,有两种前端路由实现方法:hash路由和history路由。 hash路由 hash路由是指在URL的#符号后面加上路由的路径,实…

    Vue 2023年5月27日
    00
  • vue之elementUi的el-select同时获取value和label的三种方式

    让我们来详细讲解一下“Vue之Element UI的el-select同时获取value和label的三种方式”的完整攻略。 介绍 在 Vue 中使用 Element UI 的 el-select 组件时,有时候我们需要同时获取到选中的 value 和 label 值,这时候就需要用到一些技巧来实现这个需求。在本文中,我将为大家介绍三种方式来同时获取 el-…

    Vue 2023年5月27日
    00
  • vue路由传参-如何使用encodeURI加密参数

    标题:Vue 路由传参 – 如何使用 encodeURI 加密参数 概述 Vue 路由传参是开发中常用的功能之一,通常我们直接在路由后面带上参数,例如:/blog?id=1。但是在实际应用中,由于参数内容可能包含一些特殊字符,如中文、空格等,因此需要对参数进行编码,以防止路由传参失效。其中,encodeURI() 可以将字符串进行编码,以便在 URI 中使用…

    Vue 2023年5月27日
    00
  • SpringBoot使用Shiro实现动态加载权限详解流程

    下面是”SpringBoot使用Shiro实现动态加载权限详解流程”的完整攻略: 1. 确定需求 首先,我们需要明确本次实现的需求。我们将使用Shiro来实现认证和权限控制,同时,我们的权限控制将支持动态的添加和删除。具体来说,我们需要实现以下功能: 用户登录 用户退出 用户认证 用户权限控制 动态添加权限 动态删除权限 2. 搭建SpringBoot项目 …

    Vue 2023年5月28日
    00
  • js回调函数原理与用法案例分析

    JS回调函数原理与用法 在JavaScript中,函数作为一等公民,可以作为参数传递给其他函数,也可以作为另一个函数的返回值。其中,回调函数是一种常见的应用场景,它是由一个函数作为参数传递给另一个函数,并在执行完之后通过参数的形式返回执行结果。 回调函数的基本原理 回调函数的基本原理就是函数的参数可以接受一个函数作为值传递,并在函数执行过程中将这个函数执行。…

    Vue 2023年5月29日
    00
  • 详解vue中axios请求的封装

    下面我会详细讲解vue中axios请求的封装。 前言 在vue项目开发中,我们经常需要使用到axios进行数据请求。但是,每次使用axios都需要重复的书写请求代码,一方面增加了代码量,另一方面也容易造成代码的维护成本变高。 所以,我们需要将axios请求进行封装,以便于复用和维护代码。 封装步骤 1. 安装axios 在vue项目中,使用axios请求前,…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部