Vue项目实战——实现一个任务清单基于 Vue3.x 全家桶(简易版)
Posted 前端杂货铺
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue项目实战——实现一个任务清单基于 Vue3.x 全家桶(简易版)相关的知识,希望对你有一定的参考价值。
Vue3.x 项目实战(一)
项目名 | 参考链接 |
---|---|
Vue2.x_todoList | 基于 Vue2.x 实现一个任务清单 |
Vue2.x_GitHub搜素案例 | 基于 Vue2.x GitHub 搜素案例 |
文章目录
Vue3.x 实现 todoList
1、前言
如果你对 vue3 的基础知识还很陌生,推荐先去学习一下 vue 基础
内容 | 参考链接 |
---|---|
Vue2.x全家桶 | Vue2.x全家桶参考链接 |
Vue3.x的基本使用 | Vue3.x基本使用参考链接 |
- 如果你 刚学完 vue3 基础知识,想检查一下自己的学习成果
- 如果你 已学完 vue3 基础知识,想快速回顾复习
- 如果你 已精通 vue3 基础知识,想做个小案例
- 那不妨看完这篇文章,我保证你一定会有收获的!
2、项目演示(一睹为快)
Vue3.x_任务清单
3、涉及知识点
麻雀虽小,五脏俱全,接下来开始我们的项目之旅吧~~
- Vue3.x基础:插值语法,常用指令,键盘事件,列表渲染,计算属性,生命周期
- Vue3.x进阶:props(父传子),自定义事件(任意组件间通信)
- Vuex4.x:状态管理库的使用
- Vue-router4.x:使用路由进行页面跳转
备注:
- 任意组件间的通信方式有很多种(全局事件总线,消息订阅预发布…),熟练掌握一种即可(推荐自定义事件,配置简单,容易理解)
- 本文是 vue 基础的练习项目,也涉及 vue 周边(Vuex,Vue-Router)
4、项目详情
main.js
- 导入 store 和 router,并且使用
import createApp from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app')
./router/index.js
- 配置路由
- 直接导入 VS 按需导入(节约性能)
- 使用了 history 路由模式
import createRouter, createWebHistory from 'vue-router'
// 直接引入
import Start from '../views/Start.vue'
const routes = [
path: '/',
name: 'Start',
component: Start
,
path: '/home',
name: 'Home',
// 按需引入,节约性能
component: () => import('../views/Home.vue')
]
// 创建路由对象
const router = createRouter(
history: createWebHistory(process.env.BASE_URL),
routes
)
export default router
./store/index.js
- state 中定义初始化数据
- mutations 中定义方法
import
createStore
from 'vuex'
export default createStore(
// 定义初始化状态
state:
list: [
title: "吃饭",
complete: false,
,
title: "睡觉",
complete: false,
,
title: "敲代码",
complete: true,
,
]
,
// 同步修改 state 都是方法
// 第一个参数 state 第二个参数是需要修改的值
mutations:
// 添加任务
addTodo(state, payload)
state.list.push(payload)
,
// 删除任务
delTodo(state, payload)
state.list.splice(payload, 1)
,
// 清除已完成
clear(state, payload)
// 把过滤之后的数组传进来
state.list = payload
,
// 异步提交 mutation
// 第一个参数是 store 第二个参数是修改的值
actions:
,
// 模块化
modules:
)
App.vue 组件
- 做呈现的组件
<router-view />
呈现内容
<template>
<router-view/>
</template>
<style lang="scss">
*
margin: 0;
padding: 0;
</style>
Start.vue 组件
- 初始化页面
- 点击开启任务,跳转到任务页面
<template>
<div class="title">
<h1>欢迎来到前端杂货铺</h1>
<button @click="start">开始任务</button>
</div>
</template>
<script>
import ref from "vue";
import useRouter from "vue-router";
export default
name: "Start",
setup()
// router 是全局路由对象
let router = useRouter();
let name = ref(10);
// 点击进行路由跳转
let start = () =>
router.push(
name: "Home",
params:
name: name.value,
,
);
;
return
start,
;
,
;
</script>
<style lang="scss" scoped>
.title
color: orange;
text-align: center;
margin-top: 20%;
button
margin-top: 20px;
width: 100px;
height: 50px;
background: skyblue;
color: white;
font-weight: bold;
font-size: 15px;
cursor: pointer;
button:hover
font-weight: bold;
background: white;
color: skyblue;
cursor: pointer;
</style>
Home.vue 组件
- 其他组件 表演的舞台
- 传递数据
- 自定义事件,进行组件间通信
<template>
<div class="container">
<nav-header @add="add"></nav-header>
<nav-main :list="list" @del="del"></nav-main>
<nav-footer :list="list" @clear="clear"></nav-footer>
</div>
</template>
<script>
import NavHeader from "@/components/navHeader/NavHeader";
import NavMain from "@/components/navMain/NavMain";
import NavFooter from "@/components/navFooter/NavFooter";
import ref, computed from "vue";
import useStore from "vuex";
export default
name: "Home",
// 接收父组件的数据
props: ,
// 定义子组件
components:
NavHeader,
NavMain,
NavFooter,
,
// 接收的数据,上下文
setup(props, ctx)
let store = useStore();
let list = computed(() =>
return store.state.list;
);
let value = ref("");
// 添加任务
let add = (val) =>
value.value = val;
// 任务存在 不能重复添加
let flag = true;
list.value.map((item) =>
if (item.title === value.value)
// 有重复任务
flag = false;
alert("任务已存在");
);
// 没有重复任务
if (flag == true)
// 调用 mutation
store.commit("addTodo",
title: value.value,
complete: false,
);
;
// 删除任务
let del = (val) =>
// 调用删除的 mutation
store.commit('delTodo', val)
console.log(val);
// 清除已完成
let clear = (val) =>
store.commit('clear', val)
return
add,
list,
del,
clear
;
,
;
</script>
NavHeader.vue 组件
- 头部组件(输入框)
- 输入任务按下回车进行任务的添加
emit
,使用分发的事务
<template>
<div>
<div class="container">
<input
type="text"
placeholder="请输入任务名称"
v-model="value"
@keyup.enter="enter"
/>
</div>
</div>
</template>
<script>
import ref from "vue";
export default
name: "navHeader",
// 接收的数据,上下文
setup(props, ctx)
let value = ref("");
// 按回车键确认
let enter = () =>
// 把输入框的内容传递给父组件
ctx.emit("add", value.value);
// 清空输入框
value.value = "";
;
return
value,
enter,
;
,
;
</script>
<style lang="scss" scoped>
.container
text-align: center;
margin-top: 220px;
.container input
height: 25px;
width: 200px;
margin-bottom: 10px;
</style>
NavMain.vue 组件
props
接收 list 数据v-for
遍历出来内容- 使用条件判断做呈现
<template>
<div class="container">
<div v-if="list.length > 0">
<div v-for="(item, index) in list" :key="index">
<div class="item">
<input type="checkbox" v-model="item.complete" />
item.title
<button class="del" @click="del(item, index)">删除</button>
</div>
</div>
</div>
<div v-else>
暂无任务
</div>
</div>
</template>
<script>
export default
name: "navMain",
props:
list:
type: Array,
required: true,
,
,
// 分发事件的属性名
emits: ["del"],
setup(props, ctx)
// 删除任务
let del = (item, index) =>
ctx.emit("del", index);
console.log(index, item);
;
return
del,
;
,
;
</script>
<style lang="scss" scoped>
.container
margin: auto;
border: 2px solid #ccc;
width: 200px;
margin-bottom: 20px;
.item
height: 35px;
line-height: 35px;
position: relative;
width: 200px;
button
cursor: pointer;
position: absolute;
right: 4px;
top: 6px;
display: none;
z-index: 99;
&:hover
background: #ddd;
button
display: block;
</style>
NavFooter.vue 组件
- 过滤出已完成的任务,获取到已完成任务的个数
- 过滤出未完成的任务,清除的时候保留未完成的任务
<template>
<div class="container">
已完成 isCompelete / 全部 list.length
<span v-if="isCompelete" class="btn">
<button @click="clear">清除已完成</button>
</span>
</div>
</template>
<script>
import computed from "vue";
export default
name: "navFooter",
props:
list:
type: Array,
required: true,
,
,
setup(props, ctx)
let isCompelete = computed(() =>
// 过滤已完成
let arr = props.list.filter((item) =>
return item.complete;
);
return arr.length;
);
// 清除已完成
let clear = () =>
// 过滤未完成的
let arr = props.list.filter((item) =>
return item.complete === false;
);
ctx.emit("clear", arr);
console.log("clear");
;
return
isCompelete,
clear,
;
,
;
</script>
<style lang="scss" scoped>
.container
text-align: center;
</style>
至此,此项目就实现了,如果什么问题,欢迎评论区或私信留言,看到定会第一时间解决!
5、写在最后的话
如果你是 看完全篇 阅读到了这里,我相信你一定是有收获的!
那么下面不妨打开自己的电脑,启动自己的编译器,来跟着做 / 自己做一遍吧!
有机会的话,在不久的将来还会对这个小案例进行升级(功能以及样式的升级)敬请期待吧~~
6、附源码
如果这篇文章对你有些许帮助的话,不妨 三连 + 关注 支持一下~~
下方微信小程序,回复【任务清单】即可获取源码
以上是关于Vue项目实战——实现一个任务清单基于 Vue3.x 全家桶(简易版)的主要内容,如果未能解决你的问题,请参考以下文章
Vue项目实战——基于 Vue3.x + Vant UI实现一个多功能记账本(开发导航栏及公共部分)
Vue项目实战——实现一个任务清单(学以致用,两小时带你巩固和强化Vue知识点)