1.Vuex概述
2.Vuex基本使用
3.使用Vuex完成todo案例
1.Vuex概述
Vuex是實現(xiàn)組件全局狀態(tài)(數(shù)據(jù))管理的一種機制驱显,可以方便的實現(xiàn)組件之間的數(shù)據(jù)共享
使用Vuex管理數(shù)據(jù)的好處:
A.能夠在vuex中集中管理共享的數(shù)據(jù)家厌,便于開發(fā)和后期進行維護
B.能夠高效的實現(xiàn)組件之間的數(shù)據(jù)共享忿族,提高開發(fā)效率
C.存儲在vuex中的數(shù)據(jù)是響應(yīng)式的,當數(shù)據(jù)發(fā)生改變時寺酪,頁面中的數(shù)據(jù)也會同步更新
2.Vuex的基本使用
創(chuàng)建帶有vuex的vue項目态坦,打開終端,輸入命令:vue ui
當項目儀表盤打開之后哥蔚,我們點擊頁面左上角的項目管理下拉列表倒谷,再點擊Vue項目管理器
點擊創(chuàng)建項目,如下圖所示
第一步糙箍,設(shè)置項目名稱和包管理器
第二步渤愁,設(shè)置手動配置項目
第三步,設(shè)置功能項
第四步深夯,創(chuàng)建項目
3.使用Vuex完成計數(shù)器案例
打開剛剛創(chuàng)建的vuex項目抖格,找到src目錄中的App.vue組件,將代碼重新編寫如下:
<template>
<div>
<my-addition></my-addition>
<p>----------------------------------------</p>
<my-subtraction></my-subtraction>
</div>
</template>
<script>
import Addition from './components/Addition.vue'
import Subtraction from './components/Subtraction.vue'
export default {
data() {
return {}
},
components: {
'my-subtraction': Subtraction,
'my-addition': Addition
}
}
</script>
<style>
</style>
在components文件夾中創(chuàng)建Addition.vue組件咕晋,代碼如下:
<template>
<div>
<h3>當前最新的count值為:</h3>
<button>+1</button>
</div>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
<style>
</style>
在components文件夾中創(chuàng)建Subtraction.vue組件雹拄,代碼如下:
<template>
<div>
<h3>當前最新的count值為:</h3>
<button>-1</button>
</div>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
<style>
</style>
最后在項目根目錄(與src平級)中創(chuàng)建 .prettierrc 文件,編寫代碼如下:
{
"semi":false,
"singleQuote":true
}
4.Vuex中的核心特性
A.State
State提供唯一的公共數(shù)據(jù)源掌呜,所有共享的數(shù)據(jù)都要統(tǒng)一放到Store中的State中存儲
例如办桨,打開項目中的store.js文件,在State對象中可以添加我們要共享的數(shù)據(jù)站辉,如:count:0
在組件中訪問State的方式:
1).this.$store.state.全局數(shù)據(jù)名稱 如:this.$store.state.count
2).先按需導(dǎo)入mapState函數(shù): import { mapState } from 'vuex'
然后數(shù)據(jù)映射為計算屬性: computed:{ ...mapState(['全局數(shù)據(jù)名稱']) }
B.Mutation
Mutation用于修改變更$store中的數(shù)據(jù)
使用方式:
打開store.js文件,在mutations中添加代碼如下
mutations: {
add(state,step){
//第一個形參永遠都是state也就是$state對象
//第二個形參是調(diào)用add時傳遞的參數(shù)
state.count+=step;
}
}
然后在Addition.vue中給按鈕添加事件代碼如下:
<button @click="Add">+1</button>
methods:{
Add(){
//使用commit函數(shù)調(diào)用mutations中的對應(yīng)函數(shù)损姜,
//第一個參數(shù)就是我們要調(diào)用的mutations中的函數(shù)名
//第二個參數(shù)就是傳遞給add函數(shù)的參數(shù)
this.$store.commit('add',10)
}
}
使用mutations的第二種方式:
import { mapMutations } from 'vuex'
methods:{
...mapMutations(['add'])
}
如下:
import { mapState,mapMutations } from 'vuex'
export default {
data() {
return {}
},
methods:{
//獲得mapMutations映射的sub函數(shù)
...mapMutations(['sub']),
//當點擊按鈕時觸發(fā)Sub函數(shù)
Sub(){
//調(diào)用sub函數(shù)完成對數(shù)據(jù)的操作
this.sub(10);
}
},
computed:{
...mapState(['count'])
}
}
C.Action
在mutations中不能編寫異步的代碼饰剥,會導(dǎo)致vue調(diào)試器的顯示出錯。
在vuex中我們可以使用Action來執(zhí)行異步操作摧阅。
操作步驟如下:
打開store.js文件汰蓉,修改Action,如下:
actions: {
addAsync(context,step){
setTimeout(()=>{
context.commit('add',step);
},2000)
}
}
然后在Addition.vue中給按鈕添加事件代碼如下:
<button @click="AddAsync">...+1</button>
methods:{
AddAsync(){
this.$store.dispatch('addAsync',5)
}
}
第二種方式:
import { mapActions } from 'vuex'
methods:{
...mapMutations(['subAsync'])
}
如下:
import { mapState,mapMutations,mapActions } from 'vuex'
export default {
data() {
return {}
},
methods:{
//獲得mapMutations映射的sub函數(shù)
...mapMutations(['sub']),
//當點擊按鈕時觸發(fā)Sub函數(shù)
Sub(){
//調(diào)用sub函數(shù)完成對數(shù)據(jù)的操作
this.sub(10);
},
//獲得mapActions映射的addAsync函數(shù)
...mapActions(['subAsync']),
asyncSub(){
this.subAsync(5);
}
},
computed:{
...mapState(['count'])
}
}
D.Getter
Getter用于對Store中的數(shù)據(jù)進行加工處理形成新的數(shù)據(jù)
它只會包裝Store中保存的數(shù)據(jù)棒卷,并不會修改Store中保存的數(shù)據(jù)顾孽,當Store中的數(shù)據(jù)發(fā)生變化時,Getter生成的內(nèi)容也會隨之變化
打開store.js文件比规,添加getters若厚,如下:
export default new Vuex.Store({
.......
getters:{
//添加了一個showNum的屬性
showNum : state =>{
return '最新的count值為:'+state.count;
}
}
})
然后打開Addition.vue中,添加插值表達式使用getters
<h3>{{$store.getters.showNum}}</h3>
或者也可以在Addition.vue中蜒什,導(dǎo)入mapGetters测秸,并將之映射為計算屬性
import { mapGetters } from 'vuex'
computed:{
...mapGetters(['showNum'])
}
5.vuex案例
A.初始化案例
首先使用vue ui初始化一個使用vuex的案例
然后打開public文件夾,創(chuàng)建一個list.json文件灾常,文件代碼如下:
[
{
"id": 0,
"info": "Racing car sprays burning fuel into crowd.",
"done": false
},
{
"id": 1,
"info": "Japanese princess to wed commoner.",
"done": false
},
{
"id": 2,
"info": "Australian walks 100km after outback crash.",
"done": false
},
{
"id": 3,
"info": "Man charged over missing wedding girl.",
"done": false
},
{
"id": 4,
"info": "Los Angeles battles huge wildfires.",
"done": false
}
]
再接著霎冯,打開main.js,添加store.js的引入,如下:
import Vue from 'vue'
import App from './App.vue'
import store from './store.js'
// 1. 導(dǎo)入 ant-design-vue 組件庫
import Antd from 'ant-design-vue'
// 2. 導(dǎo)入組件庫的樣式表
import 'ant-design-vue/dist/antd.css'
Vue.config.productionTip = false
// 3. 安裝組件庫
Vue.use(Antd)
new Vue({
store,
render: h => h(App)
}).$mount('#app')
再接著打開store.js钞瀑,添加axios請求json文件獲取數(shù)據(jù)的代碼沈撞,如下:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
//所有任務(wù)列表
list: [],
//文本輸入框中的值
inputValue: 'AAA'
},
mutations: {
initList(state, list) {
state.list = list
},
setInputValue(state,value){
state.inputValue = value
}
},
actions: {
getList(context) {
axios.get('/list.json').then(({ data }) => {
console.log(data);
context.commit('initList', data)
})
}
}
})
最后,代開App.vue文件雕什,將store中的數(shù)據(jù)獲取并展示:
<template>
<div id="app">
<a-input placeholder="請輸入任務(wù)" class="my_ipt" :value="inputValue" @change="handleInputChange" />
<a-button type="primary">添加事項</a-button>
<a-list bordered :dataSource="list" class="dt_list">
<a-list-item slot="renderItem" slot-scope="item">
<!-- 復(fù)選框 -->
<a-checkbox :checked="item.done">{{item.info}}</a-checkbox>
<!-- 刪除鏈接 -->
<a slot="actions">刪除</a>
</a-list-item>
<!-- footer區(qū)域 -->
<div slot="footer" class="footer">
<!-- 未完成的任務(wù)個數(shù) -->
<span>0條剩余</span>
<!-- 操作按鈕 -->
<a-button-group>
<a-button type="primary">全部</a-button>
<a-button>未完成</a-button>
<a-button>已完成</a-button>
</a-button-group>
<!-- 把已經(jīng)完成的任務(wù)清空 -->
<a>清除已完成</a>
</div>
</a-list>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'app',
data() {
return {
// list:[]
}
},
created(){
// console.log(this.$store);
this.$store.dispatch('getList')
},
methods:{
handleInputChange(e){
// console.log(e.target.value)
this.$store.commit('setInputValue',e.target.value)
}
},
computed:{
...mapState(['list','inputValue'])
}
}
</script>
<style scoped>
#app {
padding: 10px;
}
.my_ipt {
width: 500px;
margin-right: 10px;
}
.dt_list {
width: 500px;
margin-top: 10px;
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
B.完成添加事項
首先缠俺,打開App.vue文件显晶,給“添加事項”按鈕綁定點擊事件,編寫處理函數(shù)
//綁定事件
<a-button type="primary" @click="addItemToList">添加事項</a-button>
//編寫事件處理函數(shù)
methods:{
......
addItemToList(){
//向列表中新增事項
if(this.inputValue.trim().length <= 0){
return this.$message.warning('文本框內(nèi)容不能為空')
}
this.$store.commit('addItem')
}
}
然后打開store.js編寫addItem
export default new Vuex.Store({
state: {
//所有任務(wù)列表
list: [],
//文本輸入框中的值
inputValue: 'AAA',
//下一個id
nextId:5
},
mutations: {
........
//添加列表項
addItem(state){
const obj = {
id :state.nextId,
info: state.inputValue.trim(),
done:false
}
//將創(chuàng)建好的事項添加到數(shù)組list中
state.list.push(obj)
//將nextId值自增
state.nextId++
state.inputValue = ''
}
}
......
})
C.完成刪除事項
首先晋修,打開App.vue文件吧碾,給“刪除”按鈕綁定點擊事件,編寫處理函數(shù)
//綁定事件
<a slot="actions" @click="removeItemById(item.id)">刪除</a>
//編寫事件處理函數(shù)
methods:{
......
removeItemById(id){
//根據(jù)id刪除事項
this.$store.commit('removeItem',id)
}
}
然后打開store.js編寫addItem
export default new Vuex.Store({
......
mutations: {
........
removeItem(state,id){
//根據(jù)id刪除事項數(shù)據(jù)
const index = state.list.findIndex( x => x.id === id )
// console.log(index);
if(index != -1) state.list.splice(index,1);
}
}
......
})
D.完成選中狀態(tài)的改變
首先墓卦,打開App.vue文件倦春,給“復(fù)選”按鈕綁定點擊事件,編寫處理函數(shù)
//綁定事件
<a-checkbox :checked="item.done" @change="cbStateChanged(item.id,$event)">{{item.info}}</a-checkbox>
//編寫事件處理函數(shù)
methods:{
......
cbStateChanged(id,e){
//復(fù)選框狀態(tài)改變時觸發(fā)
const param = {
id:id,
status:e.target.checked
}
//根據(jù)id更改事項狀態(tài)
this.$store.commit('changeStatus',param)
}
}
然后打開store.js編寫addItem
export default new Vuex.Store({
......
mutations: {
........
changeStatus(state,param){
//根據(jù)id改變對應(yīng)事項的狀態(tài)
const index = state.list.findIndex( x => x.id === param.id )
if(index != -1) state.list[index].done = param.status
}
}
......
})
E.剩余項統(tǒng)計
打開store.js落剪,添加getters完成剩余項統(tǒng)計
getters:{
unDoneLength(state){
const temp = state.list.filter( x => x.done === false )
console.log(temp)
return temp.length
}
}
打開App.vue睁本,使用getters展示剩余項
//使用映射好的計算屬性展示剩余項
<!-- 未完成的任務(wù)個數(shù) -->
<span>{{unDoneLength}}條剩余</span>
//導(dǎo)入getters
import { mapState,mapGetters } from 'vuex'
//映射
computed:{
...mapState(['list','inputValue']),
...mapGetters(['unDoneLength'])
}
F.清除完成事項
首先,打開App.vue文件忠怖,給“清除已完成”按鈕綁定點擊事件呢堰,編寫處理函數(shù)
<!-- 把已經(jīng)完成的任務(wù)清空 -->
<a @click="clean">清除已完成</a>
//編寫事件處理函數(shù)
methods:{
......
clean(){
//清除已經(jīng)完成的事項
this.$store.commit('cleanDone')
}
}
然后打開store.js編寫addItem
export default new Vuex.Store({
......
mutations: {
........
cleanDone(state){
state.list = state.list.filter( x => x.done === false )
}
}
......
})
G.點擊選項卡切換事項
打開App.vue,給“全部”凡泣,“未完成”枉疼,“已完成”三個選項卡綁定點擊事件,編寫處理函數(shù)
并將列表數(shù)據(jù)來源更改為一個getters鞋拟。
<a-list bordered :dataSource="infoList" class="dt_list">
......
<!-- 操作按鈕 -->
<a-button-group>
<a-button :type="viewKey ==='all'?'primary':'default'" @click="changeList('all')">全部</a-button>
<a-button :type="viewKey ==='undone'?'primary':'default'" @click="changeList('undone')">未完成</a-button>
<a-button :type="viewKey ==='done'?'primary':'default'" @click="changeList('done')">已完成</a-button>
</a-button-group>
......
</a-list>
//編寫事件處理函數(shù)以及映射計算屬性
methods:{
......
changeList( key ){
//點擊“全部”骂维,“已完成”,“未完成”時觸發(fā)
this.$store.commit('changeKey',key)
}
},
computed:{
...mapState(['list','inputValue','viewKey']),
...mapGetters(['unDoneLength','infoList'])
}
打開store.js贺纲,添加getters航闺,mutations,state
export default new Vuex.Store({
state: {
......
//保存默認的選項卡值
viewKey:'all'
},
mutations: {
......
changeKey(state,key){
//當用戶點擊“全部”猴誊,“已完成”潦刃,“未完成”選項卡時觸發(fā)
state.viewKey = key
}
},
......
getters:{
.......
infoList(state){
if(state.viewKey === 'all'){
return state.list
}
if(state.viewKey === 'undone'){
return state.list.filter( x => x.done === false )
}
if(state.viewKey === 'done'){
return state.list.filter( x => x.done === true )
}
}
}
})