4.基于vuex的案例——todos任务记录工具
4.1我们重新初始化一个vue-cli项目,配置时别忘了选中Vuex配置。
4.2我们还要安装几个依赖:axios和ant-design-vue(ant-designUI组件库,也可以不使用或者使用其他擅长的组件库)
npm install axios ant-design-vue -S
4.3在mian.js中引入ant-design和ant-design的样式文件
import Vue from 'vue'
import App from './App.vue'
import store from './store'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'
Vue.config.productionTip = false
Vue.use(Antd)
new Vue({
store,
render: h => h(App)
}).$mount('#app')
4.4实现基本布局
4.5在public路径下新增一个list.json文件进行数据存储,并且将我们在App.vue中list里面的数据放到这里。
[
{
"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
}
]
我们的目的是通过请求这个json文件,来控制我们这个任务列表的内容。
4.6通过axios请求获取到list.json中的数据
在store路径下的index.js文件中引入axios,并且进行异步请求,我们需要将请求到的数据挂载到state中的list数组中,但是由于挂载数据只能在mutation中进行,所以我们要在mutation中声明一个方法,将获取到的数据挂载到list中。在actions中的getList方法获取到数据后,调用mutation中的initList方法,将数据传递给list。
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
list: []
},
mutations: {
initList (state, list) {
state.list = list
}
},
actions: {
getList (context) {
axios.get('/list.json').then(({ data }) => {
context.commit('initList', data)
})
}
},
modules: {
}
})
4.7在App.vue引入state中的list变量,我们通过引入mapState,在computed属性中展开获取。
import { mapState } from 'vuex'
computed: {
...mapState(['list'])
},
4.8输入值的双向绑定
在state中定义一个inputValue属性,默认值为空,存放文本框输入的信息。
并且在App.vue中获取到这个属性后,绑定在标签上。并且给文本框绑定一个change方法,监听input组件值的变化,将这个值传递给state中的inputValue。
在motation中定义一个接收inputValue的方法:
setInputValue (state, value) {
state.inputValue = value
}
在App.vue中定义handlInputChange方法:
methods: {
handlInputChange (e) {
this.$store.commit('setInputValue', e.target.value)
}
}
4.9 给各个组件绑定事件
4.9.1给添加事项按钮绑定点击事件
在vuex中的state数据中定义nextId属性,用于存放下一项数据的id(添加项的id)
在vuex中定义addItem方法,将id,info(输入内容,trim去除空格),done(是否完成的标识,默认为false未完成)添加到一个对象内;将这个对象push到state属性的list中,并且将nextId数值加一,并且清空inputValue(清空输入框)。
addItem (state) {
const obj = {
id: state.nextId,
info: state.inputValue.trim(),
done: false
}
state.list.push(obj)
state.nextId++
state.inputValue = ''
},
在App.vue中定义一个向列表中新增item项的方法,并且将这个方法绑定给“添加事项”按钮,方法首先判断输入内容是否为空,如果为空则进行提示,不为空则调用vuex中的addItem方法:
addItemToList () {
if (this.inputValue.trim().length <= 0) {
return this.$notification.open({
message: '文本框内容不能为空!',
type: 'warning'
})
}
this.$store.commit('addItem')
},
4.9.2给删除按钮绑定点击事件
在vuex中定义removeItem方法,根据调用该方法时传入的id查找到对应id的索引值,然后使用splice方法将该索引的项删除。
removeItem (state, id) {
// 1.根据id查找对应项索引
const index = state.list.findIndex(i => i.id === id)
// 2.根据索引删除对应项
if (index !== -1) {
state.list.splice(index, 1)
}
},
在App.vue中定义一个向列表中删除item项的方法,并且将这个方法绑定给“删除”按钮,并且将checkbox的id传递给方法,removeItemById方法调用removeIitem方法,将id传入,删除选中项。
removeItemById (id) {
this.$store.commit('removeItem', id)
},
4.9.3给checkbox绑定点击事件
checkbox的点击事件是改变list中选中项的done属性,和删除一样,传入id值后查找索引,如果索引值存在,则改变该项的done属性。
changeDone (state, id) {
const index = state.list.findIndex(i => i.id === id)
if (index !== -1) {
state.list[index].done = !state.list[index].done
}
},
在App.vue中定义changeDoneById方法,并且将这个方法绑定给checkbox,并且将checkbox的id传递给方法,changeDoneById方法调用changeDone方法,将id传入,改变选中项状态。
changeDoneById (id) {
this.$store.commit('changeDone', id)
},
4.9.4给状态选择按钮绑定点击事件
项目底部的状态选择框在点击后需要切换样式,并且获取对应的item项,我们献给这些按钮绑定事件和样式。绑定事件时,将对应的状态传给方法,绑定type时进行判断,如果为当前选中的type,则以primary样式展示,否则以默认样式展示:
全部
未完成
已完成
上面我们用了viewKey判断样式,所以我们需要在vuex的state中定义viewKey,并且定义ChangeList点击事件:
state: {
viewKey: 'undone'
},
changeViewKey (state, key) {
state.viewKey = key
}
},
并且在getters中判断viewKey,如果viewKey为all,返回list;如果viewKey为undone,返回done为false的list;如果viewKey为done,返回done值为true的list:
infoList (state) {
if (state.viewKey === 'all') {
return state.list
} else if (state.viewKey === 'undone') {
return state.list.filter(x => x.done === false)
} else if (state.viewKey === 'done') {
return state.list.filter(x => x.done === true)
} else {
return state.list
}
}
同样,在App.vue中定义ChangeList方法,调用changeViewKey方法,并且返回key值即可
ChangeList (key) {
this.$store.commit('changeViewKey', key)
}
4.9.5给清除已完成按钮绑定点击事件
清除已完成是将done属性为done的项删除,我们在vuex中定义cleanDone方法,将过滤后的list赋值给原来的list即可:
cleanDone (state) {
state.list = state.list.filter(x => x.done === false)
},
在App.vue中定义clean方法调用该cleanDone方法,并且绑定给清除已完成按钮:
clean () {
this.$store.commit('cleanDone')
},
-------------------------------------------------至此,vuex内容完结,附源代码---------------------------------------
github地址:https://github.com/weizhuren/VuexDemo.git
App.vue
vuex(src/store/index.js)
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
list: [],
inputValue: '',
// 下一个id
nextId: 5,
viewKey: 'undone'
},
mutations: {
initList (state, list) {
state.list = list
},
setInputValue (state, value) {
state.inputValue = value
},
// 添加项目列表
addItem (state) {
const obj = {
id: state.nextId,
info: state.inputValue.trim(),
done: false
}
state.list.push(obj)
state.nextId++
state.inputValue = ''
},
// 根据id删除对应任务事项
removeItem (state, id) {
// 1.根据id查找对应项索引
const index = state.list.findIndex(i => i.id === id)
// 2.根据索引删除对应项
if (index !== -1) {
state.list.splice(index, 1)
}
},
changeDone (state, id) {
const index = state.list.findIndex(i => i.id === id)
if (index !== -1) {
state.list[index].done = !state.list[index].done
}
},
// 清除已完成的任务
cleanDone (state) {
state.list = state.list.filter(x => x.done === false)
},
// 修改页面上展示列表数据
changeViewKey (state, key) {
state.viewKey = key
}
},
actions: {
getList (context) {
axios.get('/list.json').then(({ data }) => {
context.commit('initList', data)
})
}
},
getters: {
// 统计未完成的任务条数
unDoneLength (state) {
return state.list.filter(x => x.done === false).length
},
infoList (state) {
if (state.viewKey === 'all') {
return state.list
} else if (state.viewKey === 'undone') {
return state.list.filter(x => x.done === false)
} else if (state.viewKey === 'done') {
return state.list.filter(x => x.done === true)
} else {
return state.list
}
}
}
})