vue黑马案例之小黑记事本组件版(含素材)

2023-12-28 13:33:00

素材领取:点击我领取素材
提取码:1024

我们的需求如下:
1.拆分基础组件
2.渲染待办任务
3.添加任务
4.删除任务
5.底部合计 和 清空功能
6.持久化存储

分析:
渲染功能:
1.提供数据: 提供在公共的父组件 App.vue
2.通过父传子,将数据传递给TodoMain
3.利用 v-for渲染

添加功能:
1.手机表单数据 v-model
2.监听事件(回车+点击都要添加)
3.子传父,讲任务名称传递给父组件 App.vue
4.进行添加 unshift(自己的数据自己负责)
5.清空文本框输入的内容
6.对输入的空数据 进行判断

删除功能
1.监听事件(监听删除的点击) 携带id
2.子传父,讲删除的id传递给父组件的App.vue
3.进行删除filter(自己的数据 自己负责)

底部合计:父传子 传list 渲染
清空功能:子传父 通知父组件 → 父组件进行更新
持久化存储:watch深度监视list的变化 -> 往本地存储 ->进入页面优先读取本地数据

父组件代码:

<template>
  <!-- 主体区域 -->
  <section id="app">
    <!-- 监听子组件 -->
    <TodoHeader @add="handlerAdd"></TodoHeader>
    <!-- 我们父传子给子组件传入list 监听del -->
    <TodoMain :list="list" @handlerDel="del"></TodoMain>
    <TodoFooter @clear="handlerClear" :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: "踢足球" }
      ]
    }
  },
  methods: {
    handlerAdd(values) {
      // 我们使用unshift()方法向数组的最前面添加数据
      this.list.unshift({
        // 使用时间戳作为id值
        id: +new Date(),
        name: values
      })
    },
    del(id) {
      // 使用filter去过滤数组完成删除
      this.list = this.list.filter(item => item.id !== id)
    },
    handlerClear() {
      this.list = []
    }
  },
  watch: {
    list: {
      deep: true,
      handler(newValue) {
        localStorage.setItem("list", JSON.stringify(newValue))
      }
    }
  },
  components: {
    TodoHeader,
    TodoMain,
    TodoFooter
  }
}
</script>

子组件TodoHeader代码:

<template>
    <!-- 输入框 -->
    <header class="header">
        <h1>小黑记事本</h1>
        <!-- 使用v-model双向数据绑定 -->
        <!-- 我们点击按钮 与 回车都需要监听 -->
        <input @keyup.enter="handlerAdd" v-model="msg" placeholder="请输入任务" class="new-todo" />
        <!-- 添加功能 需要使用到子传父 -->
        <button @click="handlerAdd" class="add">添加任务</button>
    </header>
</template>
<script>
export default {
    data() {
        return {
            msg: ""
        };
    },
    methods: {
        handlerAdd() {
            // 当msg为空时 我们需要返回 
            if (this.msg.trim() == "") {
                alert("请输入值")
                return
            }
            // 子传父 使用this.$emit()
            this.$emit('add', this.msg);
            // 添加完之后 我们需要把表单的值赋为空
            this.msg = ""
        }
    },
};
</script>

子组件TodoMain代码:

<template>
    <!-- 列表区域 -->
    <section class="main">
        <ul class="todo-list">
            <!-- 我们使用v-for去渲染页面 -->
            <li class="todo" v-for="(item, index) in list" :key="item.id">
                <div class="view">
                    <!-- 需要使用到index -->
                    <span class="index">{{ index + 1 }}.</span> <label>{{ item.name }}</label>
                    <!-- 我们需要借助id去删除数据 -->
                    <button @click="del(item.id)" class="destroy"></button>
                </div>
            </li>
        </ul>
    </section>
</template>
<script>
export default {
    // 我们使用props
    props: {
        list: Array
    },
    methods: {
        del(id) {
            // 子传父
            this.$emit('handlerDel', id);
        }
    },
};
</script>

子组件TodoFooter代码:

<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 {
  // 我们把list通过父传子的方法传入
  props: {
    list: Array
  },
  methods: {
    clear() {
      // 子传父
      this.$emit('clear');
    }
  },
};
</script>

感谢大家的阅读,如有不对的地方,可以向我提出,感谢大家!

文章来源:https://blog.csdn.net/m0_74577714/article/details/135253803
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。