当前位置:首页 » 《随便一记》 » 正文

Vue项目实战——实现一个任务清单【基于 Vue3.x 全家桶(简易版)】

27 人参与  2022年10月23日 08:12  分类 : 《随便一记》  评论

点击全文阅读


Vue3.x 项目实战(一)

项目名参考链接
Vue2.x_todoList基于 Vue2.x 实现一个任务清单
Vue2.x_GitHub搜素案例基于 Vue2.x GitHub 搜素案例

文章目录

Vue3.x 项目实战(一)Vue3.x 实现 todoList1、前言2、项目演示(一睹为快)3、涉及知识点4、项目详情5、写在最后的话6、附源码


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、附源码

如果这篇文章对你有些许帮助的话,不妨 三连 + 关注 支持一下~~

下方微信小程序,回复【任务清单】即可获取源码


点击全文阅读


本文链接:http://zhangshiyu.com/post/45430.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1