如何从零实现一个todo list(1)

一、开始前准备

实现一个想要的功能前,可以先理清它的功能,最好画一张思维导图,再按着导图实现的话会轻松很多,好记性不如烂笔头

如我们今天要实现的一个todo list的功能 那我的规划是这样的首先先实现网页版本->再实现用electron包装起来加入sqlite数据库操作的功能。

实现一个TodoList前 我们首先观察windows 自带的Microsoft To Do的功能 画出导图

这样就可以很清晰的看到我们要实现的功能 那功能的大概罗列出来以后我们就要开始想界面如何实现 可以对界面打一个草稿做一个原型 这个一个demo项目的话 我们就直接根据Microsoft To Do布局做参考。

二、技术选型

demo来说的话 我个人习惯敏捷开发出原型 比起先打磨样式的情况 我更喜欢先把功能实现

首先进行技术选型:vue+vuex+vueitfy(同时兼容移动端)

三、原型编写

既然是要实现一个Todo List 那我们就先把注意力放在核心功能上 开始编写

首先通过vue ui 或者 vue-cli 创建一个空项目

shell 复制代码
# 若vue命令报错的话 请先安装脚手架 npm install -g @vue/cli
# 根据上面的选型 我们闯建项目的时候 只需要保留Babel与vuex
vue create todo-list
# 等编译完毕后 进入文件夹
cd todo-list
# 安装我们需要的vuetify 为什么其他UI也兼容移动端要选择它呢?它有内置的css规范 可以少写很多css
cnpm install vuetify@v2-stable -S
cnpm install sass@~1.32 sass-loader@10.x deepmerge -D #不建议直接安装官方的命令 sass-loader太高会报错
# 进入vueitfy 官网 https://v2.vuetifyjs.com/zh-Hans/getting-started/installation/#nuxt-5b8988c5
# 找到webpack安装 要看完上面网址webpack安装

安装完后步骤

  1. 引入vuetify

  2. 删除HellowWorld.vue

  3. 删除App.vue不需要的东西

  4. 引入样式文件

    1. public/index.html下加入 但是加载很慢

    ini 复制代码
       <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
       <link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css" rel="stylesheet">
  5. 在components创建TaskList.vue的组件 并引入到App.vue里

  6. 下载需要的库vue-uuid、momentjs原型开发

原型开发

html 复制代码
    <!--App.vue -->
    <template>
      <div
        id="app"
        class="v-application"
      >

        <v-card
          width="100%"
          flat
        >
          <v-system-bar
            color="#303F9F"
            dark
          >
            <v-spacer></v-spacer>

            <v-icon>mdi-window-minimize</v-icon>

            <v-icon>mdi-window-maximize</v-icon>

            <v-icon>mdi-close</v-icon>
          </v-system-bar>

          <v-toolbar
            color="#3F51B5"
            dark
          >
            <v-app-bar-nav-icon></v-app-bar-nav-icon>

            <v-toolbar-title>我的一天</v-toolbar-title>

            <v-spacer></v-spacer>

          </v-toolbar>

          <v-container>
            <task-list />
          </v-container>
        </v-card>
      </div>
    </template>

    <script>
    import TaskList from "./components/TaskList.vue";
    export default {
      name: "App",
      components: {
        TaskList,
      },
    };
    </script>

    <style lang="scss">
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      color: #2c3e50;
      height: 100vh;
      overflow: auto;
    }
    </style>
html 复制代码
    <!-- components/TaskList.vue -->
    <template>
      <div class="py-4">
        <v-text-field
          v-model="todo"
          counter="25"
          placeholder="请输入待办事项"
          label="待办事项"
          outlined
          dense
          persistent-placeholder
          @keydown.enter="addTodo"
        ></v-text-field>

        <v-list dense>
          <div
            v-for="list in lists"
            :key="list.name"
          >
            <template v-if="list.data.length">
              <v-subheader>{{list.name}}</v-subheader>
              <v-list-item
                v-for="(item, i) in list.data"
                :key="i"
                class="task-item mb-4"
                :class="{complete:item.complete}"
              >
                <v-list-item-avatar>
                  <v-checkbox
                    v-model="item.complete"
                    @change="forceUpdate"
                    v-if="refresh"
                  />
                </v-list-item-avatar>
                <v-list-item-content>
                  <v-list-item-title>{{item.title}}</v-list-item-title>
                </v-list-item-content>
                <v-list-item-action>
                  <v-icon
                    v-if="!item.complete"
                    @click="deleteItem(item.id)"
                  >mdi-close</v-icon>
                </v-list-item-action>
              </v-list-item>
            </template>
          </div>
        </v-list>
      </div>
    </template>

    <script>
    import { uuid } from "vue-uuid";
    export default {
      data() {
        return {
          // 当前完整列表
          current_list: [],
          // 待办事项输入值
          todo: "",
          // 这里处理渲染的时候v-checkbox值变动样式不刷新的问题
          refresh: true,
        };
      },
      computed: {
        // 为了能用v-for 渲染写的列表目录
        lists() {
          return [
            {
              name: "待办列表",
              data: this.current_list.filter((list_item) => !list_item.complete),
            },
            {
              name: "已完成",
              data: this.current_list.filter((list_item) => list_item.complete),
            },
          ];
        },
      },
      methods: {
        // 新增todolist
        addTodo() {
          if (!this.todo) return;
          this.current_list.push({
            // 增加id是因为使用了computed 它的index是不准的
            id: uuid.v4(),
            title: this.todo,
            complete: false,
            create_time: new Date(),
          });
          this.todo = "";
        },
        // 强制刷新
        forceUpdate() {
          this.refresh = false;
          this.$nextTick(() => {
            this.refresh = true;
          });
        },
        // 删除事项
        deleteItem(id) {
          this.current_list.splice(
            this.current_list.findIndex((item) => item.id == id),
            1
          );
        },
      },
    };
    </script>

    <style lang="scss" scoped>
    ::v-deep .v-label {
      left: -13px !important;
    }
    .task-item {
      background-color: #eee;
      border-radius: 10px;
    }
    .task-item.complete {
      .v-list-item__title {
        text-decoration: line-through;
        color: #ccc;
      }
    }
    </style>

这样就完成了一个最基础的todolist的原型功能 后续我们开始对布局进行调整 把思维导图上的大模块上的功能加上去 我们就可以继续对原型功能开发

相关推荐
卸任4 小时前
Vibe coding工具使用心得
前端·ai编程
brien95 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance5 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M5 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写5 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李5 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易6 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马6 小时前
前沿视界
前端
kyriewen6 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易6 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员