详解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技术站