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

这篇具有很好参考价值的文章主要介绍了Vue项目实战——实现一个任务清单【基于 Vue3.x 全家桶(简易版)】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Vue3.x 项目实战(一)

内容 参考链接
Vue2.x全家桶 Vue2.x 全家桶参考链接
Vue2.x项目(一) Vue2.x 实现一个任务清单
Vue2.x项目(二) Vue2.x 实现GitHub搜索案例
Vue3.x项目(三) Vue3.x 实现一个任务清单


Vue3.x 实现 todoList

1、前言

如果你对 vue3 的基础知识还很陌生,推荐先去学习一下 vue 基础

内容 参考链接
Vue2.x全家桶 Vue2.x全家桶参考链接
Vue3.x的基本使用 Vue3.x基本使用参考链接
  • 如果你 刚学完 vue3 基础知识,想检查一下自己的学习成果
  • 如果你 已学完 vue3 基础知识,想快速回顾复习
  • 如果你 已精通 vue3 基础知识,想做个小案例
  • 那不妨看完这篇文章,我保证你一定会有收获的!

2、项目演示(一睹为快)

Vue3.x_任务清单

用vue 完成一个任务清单,Vue2.x&Vue3.x项目实战(demo),vue.js,前端,javascript,Vue3.x

用vue 完成一个任务清单,Vue2.x&Vue3.x项目实战(demo),vue.js,前端,javascript,Vue3.x

3、涉及知识点

麻雀虽小,五脏俱全,接下来开始我们的项目之旅吧~~

  • Vue3.x基础:插值语法,常用指令,键盘事件,列表渲染,计算属性,生命周期
  • Vue3.x进阶:props(父传子),自定义事件(任意组件间通信)
  • Vuex4.x:状态管理库的使用
  • Vue-router4.x:使用路由进行页面跳转

备注:

  1. 任意组件间的通信方式有很多种(全局事件总线,消息订阅预发布…),熟练掌握一种即可(推荐自定义事件,配置简单,容易理解)
  2. 本文是 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 完成一个任务清单,Vue2.x&amp;Vue3.x项目实战(demo),vue.js,前端,javascript,Vue3.x文章来源地址https://www.toymoban.com/news/detail-781155.html


到了这里,关于Vue项目实战——实现一个任务清单【基于 Vue3.x 全家桶(简易版)】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3项目引入本地js文件,实现一个音频播放按钮

    目前有一个需求就是在网页上放置一个音乐控制按钮,并且是在vue3项目里面。于是小白的我遇到了2个问题,第一个问题是如何实现没有进度条的播放按钮,这个网上有现成的代码,可以通过js代码切换不同的图片或者是别的样式,并不算难;第二个问题是如何在vue3项目中引

    2024年02月19日
    浏览(29)
  • 项目实战:《智慧线上购物商城》:基于vue3+vite+vant4组件(一)

    本项目主要是基于vue3和vite以及vant4组件所开发的移动端购物商城。项目没有接口,所运用的存储数据为json数据通过axios请求,以及Localstorage等技术实现数据。 开发的模型参考以下的网站,感兴趣的小伙伴可以去看看。 AxureShop原型演示 AxureShop原型演示 https://demo.axureshop.com/?

    2024年02月02日
    浏览(74)
  • 记录--Vue3基于Grid布局简单实现一个瀑布流组件

    在学习Grid布局之时,我发现其是CSS中的一种强大的布局方案,它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,在刷某书和某宝首页时,我们发现其展示方式就是一种瀑布流,是一种流行的网站页面布局,视觉表现为参差不齐的多栏布局,随着页

    2024年02月05日
    浏览(37)
  • 基于Vue3和Element Plus组件库实现一个完整的登录功能

    先看一下最终要实现的效果: 登录页面: 注册页面: (1)引入element-plus组件库 引入组件库的方式有好多种,在这里我就在main.js全局引入了. main.js中代码: 引入之后自己可以用几个按钮测试一下是否引入成功. (2)登录及注册页面 html部分 views/account/Login.vue js部分 css部分(使用了scss) (

    2024年02月05日
    浏览(24)
  • 基于vscode实现vue3项目创建启动+安装配置路由vue-router实现单页面组件切换

    访问https://nodejs.org/en,点击下载最新版本的nodejs,并安装。 在项目目录文件下,通过cmd运行下述指令。 依次输入下列命令,启动vue项目 在浏览器中加载http://localhost:5173/,页面加载成功,说明vue项目安装启动成功。 建议安装第三方库通过vscode中的终端来操作,项目启动通过

    2024年02月03日
    浏览(42)
  • vue3 一个基于pinia简单易懂的系统权限管理实现方案,vue-router动态路由异步问题解决

    作为项目经验稀少的vue开发者来说,在关键技术点上的经验不多,我希望通过我的思想和实践,把好的东西分享在这里,目的是进一步促进技术交流。项目即将完成,权限是最后的收尾工作,好的权限实现方案,可以让我们没有后顾之忧,也可以提升项目的运行速度。 在开发

    2023年04月08日
    浏览(33)
  • axios 实战进阶练习——基于 Vue3 + Node.js + ElementPlus 实现的联系人列表管理后台

    书接上回,上一篇文章介绍了一个基于 Vue3 和 ElementPlus 的联系人列表管理后台小 demo (Vue3 + ElementPlus实战学习——模拟简单的联系人列表管理后台),在有了上一篇文章的基础上,我们试着用 axios 来获取数据,而不是用写死的数据,然后用 Node.js + Vue3 + ElementPlus 来实现联系

    2024年02月10日
    浏览(34)
  • axios实战进阶练习——基于 Vue3 + Node.js + ElementPlus 实现的联系人列表管理后台

    书接上回,上一篇文章介绍了一个基于 Vue3 和 ElementPlus 的联系人列表管理后台小 demo (Vue3 + ElementPlus实战学习——模拟简单的联系人列表管理后台),在有了上一篇文章的基础上,我们试着用 axios 来获取数据,而不是用写死的数据,然后用 Node.js + Vue3 + ElementPlus 来实现联系

    2024年02月09日
    浏览(29)
  • Vue3项目实战

    目录 一、项目准备 二、基础语法应用 2.1、mixin应用 2.2、网络请求 2.3、显示与隐藏 2.4、编程式路由跳转 2.5、下载资料 2.6、调用方法 2.7、监听路由变化 2.8、pinia应用 (1)存储token(user.js) (2)全选全不选案例(car.js) 下载: cnpm i unplugin-auto-import -D   //setup 语法糖插件 npm i -D @types

    2024年02月11日
    浏览(42)
  • axios 实战进阶练习( axios 封装篇)——基于 Vue3 + Node.js + ElementPlus 实现的联系人列表管理后台的 axios 封装实战

    在之前的文章 axios 实战进阶练习——基于 Vue3 + Node.js + ElementPlus 实现的联系人列表管理后台 中,我们完成了这个 基于 Vue3 + Node.js + ElementPlus 实现的联系人列表管理后台 的项目,其中项目的后端接口是用 Node.js 编写的,通过 axios 来获取接口,所以这篇文章我们来对这个 axi

    2024年02月11日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包