Vuex + Mockjs = ToDoList
目标对Vuex、mockjs、Element_UI进行强化练习拿下Vuex写在前面写在前面:本 demo 为Vue脚手架搭建的简洁版的ToDoList;主要用到技术栈:Vuex、mockjs、Element_UI。希望有能对大家有用的地方。
·
目标
对Vuex、mockjs、Element_UI进行强化练习
拿下Vuex
写在前面
写在前面:本 demo 为Vue脚手架
搭建的简洁版的ToDoList;主要用到技术栈:Vuex、mockjs、axios、Element_UI
。所有数据均有 mockjs动态模拟;axios来发送请求;Vuex 来管理;页面以Element_UI来搭建。项目源码地址:https://github.com/cwen-jdoit/vuex_todolist
看一下效果吧
1. 步骤实现
1.1 初始化项目
用vue 脚手架,搭建项目,切记一定要安装 vuex
1.2 使用mock模拟数据
- 首先安装mock,用命令行
npm i mockjs --save-dev
或者可视化面板安装mockjs依赖
- 在项目根目录下新建
mock
文件夹,并新建mock.js
文件(写入要使用的mock数据) - 在
main.js
中导入mock.js
示例:
mock.js
//# 引入mock
const Mock = require('mockjs');
//# 获取list数据的接口
Mock.mock('/todolist', 'get', function(options) {
let a = [];
for (let i = 0; i < 5; i++) {
let o = Mock.mock({
_id: "@id()",
title: '@string("lower",5)',
completed: "@boolean"
})
a.push(o)
}
return a
});
//# 添加数据的接口
Mock.mock('/addtodo', 'post', function(options) {
let o = JSON.parse(options.body);
return Mock.mock({
_id: "@id()",
title: o.title,
completed: false
})
});
main.js导入mock.js
import '../mock/mock.js'
了解更多mock使用技巧:https://blog.csdn.net/cwq521o/article/details/106736474
1.3 编辑store数据
代码注释超详尽,此处略去概述
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
list: [],
inputValue: '',
viewKey: 'all'
},
mutations: {
//# 切记只有mutations里面的函数才有权限修改state的数据
// 初始化数据
initList(state, list) {
state.list = list
},
// 给inputValue赋值
setInputValue(state, val) {
state.inputValue = val
},
// 增加任务,并清空输入框
addmyTodo(state, task) {
state.list.push(task)
state.inputValue = ''
},
// 删除任务
deletemyTodo(state, id) {
const index = state.list.findIndex(item => item._id === id)
if (index !== -1) {
state.list.splice(index, 1)
}
},
// 修改完成状态
modefyTodo(state, params) {
const index = state.list.findIndex(item => item._id === params.id)
if (index !== -1) {
state.list[index].completed = params.completed
}
},
// 清空已完成任务
removeDone(state) {
state.list = state.list.filter(item => item.completed === false)
},
// 按钮切换为viewKey赋值,切换高亮
changeLight(state, key) {
state.viewKey = key
}
},
actions: {
//# 获取todo列表
async getList(context) {
const { data: res } = await axios.get('/todolist');
//# 只有mutations内的函数才可操作数据,所以此处调用函数赋值
context.commit('initList', res);
},
//# 发送添加任务请求
async addTodo(context) {
const { data: res } = await axios.post('/addtodo', {
title: context.state.inputValue
});
context.commit('addmyTodo', res)
}
},
getters: {
//# 返回未完成任务数
doneTodo(state) {
return state.list.filter(item => item.completed === false).length
},
//# 返回全部任务(对任务进行过滤返回)
infolist(state) {
if (state.viewKey === 'all') {
return state.list
} else if (state.viewKey === 'done') {
return state.list.filter(item => item.completed === true)
} else if (state.viewKey === 'nodone') {
return state.list.filter(item => item.completed === false)
}
}
}
})
1.4 重构App.vue
此处主要用到Element_UI 组件,实现页面的快速搭建。逻辑部分注释清晰
<template>
<div id="app">
<!-- 标题部分 -->
<h1>ToDoList</h1>
<!-- 输入框部分 -->
<el-row class="add_text">
<el-col :span="9" :offset="7">
<div class="myinput">
<input
type="text"
placeholder="请输入todo"
:value="inputValue"
@change="changeInput"
@keyup.enter="todoAdd"
/>
</div>
</el-col>
<el-col :span="1">
<i class="el-icon-plus mycursor" style="color:green;font-size:19px" @click="todoAdd"></i>
</el-col>
</el-row>
<!-- 展示任务部分 -->
<div class="add_todo">
<el-row v-for="(item,index) in infolist" :key="index">
<el-col :span="1" :offset="7">
<el-switch
v-model="item.completed"
active-color="#13ce66"
inactive-color="#ff4949"
@change="switchChange(item._id,item.completed)"
></el-switch>
</el-col>
<el-col :span="8">
<label :class="item.completed ? 'already' : ''">{{item.title}}</label>
</el-col>
<el-col :span="1">
<i
class="el-icon-delete mycursor"
style="color:red;font-size:19px"
@click="deleteById(item._id)"
></i>
</el-col>
</el-row>
</div>
<!-- footer部分 -->
<div class="todo_order">
<el-row>
<el-col :span="2" :offset="7" class="mystyle">
<label>
<strong>{{doneTodo}}</strong> nodone
</label>
</el-col>
<el-col :span="4" :offset="1">
<el-button
size="mini"
:type="viewKey === 'all' ? 'warning' : ''"
icon="el-icon-coin"
@click="changeList('all')"
></el-button>
<el-button
size="mini"
:type="viewKey === 'done' ? 'success' : ''"
icon="el-icon-check"
@click="changeList('done')"
></el-button>
<el-button
size="mini"
:type="viewKey === 'nodone' ? 'danger' : ''"
icon="el-icon-close"
@click="changeList('nodone')"
></el-button>
</el-col>
<el-col :span="1">
<el-button size="mini" type="danger" icon="el-icon-delete" @click="deleteDoneTodo">删除已完成</el-button>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
//# 导入list数据
import { mapState } from 'vuex';
//# 导入发送请求的方法
import { mapActions } from 'vuex';
//# 导入getters
import { mapGetters } from 'vuex';
//# 向外暴露
export default {
name: 'app',
data() {
return {};
},
created() {
//# 获取任务列表
this.getList();
},
methods: {
//# 拿到vuex中发送请求的函数
...mapActions(['getList', 'addTodo']),
//# 监听输入框改变事件
changeInput(e) {
this.$store.commit('setInputValue', e.target.value);
},
//# 监听添加按钮,完成添加任务
todoAdd() {
if (this.inputValue.trim().length <= 0) {
return this.$message.error('请输入内容');
}
this.addTodo();
this.$message.success('已成功添加新任务');
},
//# 监听删除按钮,完成删除功能
async deleteById(id) {
// 弹出确认框(返回值为promise对象,所以用async,await)
const confirmResult = await this.$confirm(
'此操作将永久删除该任务, 是否继续?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).catch(err => err);
// 如果确认删除,返回字符串,confirm;否则返回cancel
if (confirmResult !== 'confirm') {
return this.$message.info('取消删除');
}
this.$store.commit('deletemyTodo', id);
this.$message.success('删除任务成功');
},
//# 监听修改任务状态
switchChange(id, completed) {
const params = {
id,
completed
};
this.$store.commit('modefyTodo', params);
this.$message.success('状态修改成功');
},
//# 监听清空已完成任务按钮
async deleteDoneTodo() {
const confirmResult = await this.$confirm(
'此操作将永久删除该任务, 是否继续?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).catch(err => err);
if (confirmResult !== 'confirm') {
return this.$message.info('取消了删除');
}
this.$store.commit('removeDone');
this.$message.success('删除了全部的已完成');
},
//# 监听按钮切换事件
changeList(key) {
this.$store.commit('changeLight', key);
}
},
computed: {
//# 把数据写入计算属性中
...mapState(['inputValue', 'viewKey']),
//# 把getters修饰的数据写入计算属性
...mapGetters(['doneTodo', 'infolist'])
}
};
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
margin-top: 60px;
}
h1 {
margin-left: 550px;
font-size: 100px;
color: pink;
text-shadow: 0 6px 6px red;
}
.el-input__inner {
padding: 0;
}
.add_text input {
width: 100%;
font-size: 18px;
padding-left: 9px;
border: none;
outline: none;
}
.add_todo {
margin-top: 18px;
}
.myinput {
border-bottom: 1px solid red;
}
.todo_order {
margin-top: 18px;
}
.mystyle {
font-size: 19px;
color: red;
}
.mycursor {
cursor: pointer;
}
.el-row {
margin-top: 21px;
}
.already {
color: #ccc;
text-decoration: line-through;
}
</style>
注意:值得注意的是,vuex的思想,一定要确保数据只能由mutations 中的函数来修改,且函数都必须传递state 参数。了解更多Vuex:https://blog.csdn.net/cwq521o/article/details/107289221
奥利给
更多推荐
已为社区贡献20条内容
所有评论(0)