Bootstrap

记事本案例组件版本(源码分享)

  💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。



非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
 

案例效果图:

咱们可以把记事本原有的结构拆成三部分内容:头部(TodoHeader)、列表(TodoMain)、底部(TodoFooter)

列表渲染

思路分析:

  1. 提供数据:提供在公共的父组件 App.vue

  2. 通过父传子,将数据传递给TodoMain

  3. 利用v-for进行渲染

添加功能

思路分析:

  1. 收集表单数据 v-model

  2. 监听时间 (回车+点击 都要进行添加)

  3. 子传父,将任务名称传递给父组件App.vue

  4. 父组件接受到数据后 进行添加 unshift(自己的数据自己负责)

删除功能

  1. 监听时间(监听删除的点击)携带id

  2. 子传父,将删除的id传递给父组件App.vue

  3. 进行删除 filter (自己的数据自己负责)

底部功能及持久化存储

  1. 底部合计:父组件传递list到底部组件 —>展示合计

  2. 清空功能:监听事件 —> 子组件通知父组件 —>父组件清空

  3. 持久化存储:watch监听数据变化,持久化到本地

源码分享

App.vue

<template>
  <!-- 主体区域 -->
  <section id="app">
    <TodoHeader @add="handleAdd"></TodoHeader>
    <TodoMain @del="handleDel" :list="list"></TodoMain>
    <TodoFooter @clear="handleClear" :list="list"></TodoFooter>
  </section>
</template>

<script>
import TodoHeader from "./components/TodoHeader.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoFooter from "./components/TodoFooter.vue";
export default {
  data() {
    return {
      list: JSON.parse(localStorage.getItem("list")) || [
        { id: 1, name: "打篮球" },
        { id: 2, name: "踢足球" },
        { id: 3, name: "打棒球" },
      ],
    };
  },
  methods: {
    handleAdd(todoName) {
      this.list.unshift({
        id: +new Date(),
        name: todoName,
      });
    },
    handleDel(id) {
      this.list = this.list.filter((item) => item.id != id);
    },
    handleClear() {
      this.list = [];
    },
  },
  watch: {
    list: {
      deep: true,
      handler(newValue) {
        localStorage.setItem("list", JSON.stringify(newValue));
      },
    },
  },
  components: {
    TodoHeader,
    TodoMain,
    TodoFooter,
  },
};
</script>

<style>
</style>

TodoHeader.vue

<template>
  <!-- 输入框 -->
  <header class="header">
    <h1>记事本</h1>
    <input
      @keyup.enter="handleAdd"
      v-model="todoName"
      placeholder="请输入任务"
      class="new-todo"
    />
    <button @click="handleAdd" class="add">添加任务</button>
  </header>
</template>

<script>
export default {
  data() {
    return {
      todoName: "",
    };
  },
  methods: {
    handleAdd() {
      if (this.todoName.trim() === "") {
        alert("任务名称不能为空");
        return;
      }
      this.$emit("add", this.todoName);
      this.todoName = "";
    },
  },
};
</script>

<style>
</style>

TodoMain.vue

<template>
  <!-- 列表区域 -->
  <section class="main">
    <ul class="todo-list">
      <li v-for="(item, index) in list" :key="item.id" class="todo">
        <div class="view">
          <span class="index">{{ index + 1 }}.</span>
          <label>{{ item.name }}</label>
          <button @click="handleDel(item.id)" class="destroy"></button>
        </div>
      </li>
    </ul>
  </section>
</template>

<script>
export default {
  props: {
    list: Array,
  },
  methods: {
    handleDel(id) {
      this.$emit("del", id);
    },
  },
};
</script>

<style>
</style>

TodoFooter.vue

<template>
  <!-- 统计和清空 -->
  <footer class="footer">
    <!-- 统计 -->
    <span class="todo-count"
      >合 计:<strong> {{ list.length }} </strong></span
    >
    <!-- 清空 -->
    <button @click="clear" class="clear-completed">清空任务</button>
  </footer>
</template>

<script>
export default {
  props: {
    list: Array,
  },
  methods: {
    clear() {
      this.$emit("clear");
    },
  },
};
</script>

<style>
</style>

❤️❤️❤️小郑是普通学生水平,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

;