备忘录案例

1.todo-list组件

1.1.渲染列表组件结构
<div class="home container">
    <ul class="list-group">
      <!-- 列表组 -->
      <li class="list-group-item d-flex justify-content-between align-items-center">
       <!-- 复选框 -->
        <div class="form-group form-check">         
          <input type="checkbox" class="form-check-input" id="customCheck1" />
          <label class="form-check-label" for="customCheck1"
            >Check this custom checkbox</label>          
        </div>
        <!-- 徽标 -->
        <span class="badge badge-success badge-pill">完成</span>
        <span class="badge badge-warning badge-pill">未完成</span>
      </li>
    </ul>
  </div>

在这里插入图片描述

1.2.循环渲染列表组数据
//在App.vue中
const todolist = ref([
  { id: 1, task: "周一早晨9点开会", done: false },
  { id: 2, task: "周一晚上8点聚餐", done: false },
  { id: 3, task: "准备周三上午的演讲稿", done: true },
]);

<TodoList :list="todolist" />
//在todolist.vue中
<script setup>
defineProps({
  list: Array,
  default: [],
});
</script>

<template>
  <div class="home container">
    <ul class="list-group">
      <!-- 列表组 -->
      <li
        class="list-group-item d-flex justify-content-between align-items-center"
        v-for="item in list"
        :key="item.id"
      >
        <!-- 复选框 -->
        <div class="form-group form-check">
          <!-- 复选框和完成状态间的双向绑定,当勾选之后,会改变item.done中的值 -->
          <input type="checkbox" class="form-check-input" :id="item.id" />
          <label class="form-check-label" :for="item.id">{{ item.task }}</label>
        </div>

        <!-- 徽标 -->
        <span class="badge badge-success badge-pill" v-if="item.done"
          >完成</span
        >
        <span class="badge badge-warning badge-pill" v-else>未完成</span>
      </li>
    </ul>
  </div>
</template>

在这里插入图片描述

1.3.复选框和状态的双向绑定(即勾选之后,状态变换:未完成/完成)
<input type="checkbox" class="form-check-input" :id="item.id" v-model="item.done"/>

在这里插入图片描述

1.4.已完成的任务样式变化(删除的横线)
<label class="form-check-label" :class="item.done?'delete':''" :for="item.id">{{ item.task }}</label>

.delete {
  text-decoration: line-through;
  color: gray;
  font-style: iitalic;
}

在这里插入图片描述

2.todo-input组件

2.1.渲染输入框组件
<template>
  <div class="home container">
    <form class="form-inline">
      <div class="input-group mb-2 mr-sm-2">
        <div class="input-group-prepend">
          <div class="input-group-text">任务</div>
        </div>
        <input
          type="text"
          class="form-control"
          placeholder="请输入任务信息"
          style="width: 376px"          
        />
      </div>
      <button type="submit" class="btn btn-primary mb-2">添加</button>
    </form>
  </div>
</template>

在这里插入图片描述

2.2.子传父(添加的新任务追加到App.vue组件中)
//在todoinput组件中
<script setup>
import { ref } from "vue";
// 点击提交时,将新建任务传到app组件中,然后在app组件中添加到todolist列表中
const taskname = ref("");
//声明一个自定义事件,【子传父,不带参数】
const emits = defineEmits(["add"]);
//表单的提交事件处理函数
const onFormSubmit = () => {
  if (!taskname.value) return alert("任务名称不能为空");
  //触发自定义事件,并向外界传递数据
  emits("add", taskname.value);
  //清空文本框
  taskname.value = "";
};
</script>

//1.监听form表单的提交事件;2.双向绑定输入框
<template>
  <div class="home container">
    <form class="form-inline" @submit.prevent="onFormSubmit">
      <div class="input-group mb-2 mr-sm-2">
        <div class="input-group-prepend">
          <div class="input-group-text">任务</div>
        </div>
        <input
          type="text"
          class="form-control"
          placeholder="请输入任务信息"
          style="width: 376px"
          v-model.trim="taskname"
        />
      </div>
      <button type="submit" class="btn btn-primary mb-2">添加</button>
    </form>
  </div>
</template>

//在App组件中,监听todolist组件的自定义事件,获取要添加的任务名称
<TodoInput @add="onAddNewTask" />

const onAddNewTask = (taskname) => {
  console.log(taskname); //值就传过来了  
};
2.3.实现添加新任务功能(将一个对象添加到列表中)
const nextId = ref(4);
const onAddNewTask = (taskname) => {
  console.log(taskname); //值就传过来了
  todolist.value.push({
    id: nextId.value,
    task: taskname,
    done: false,
  });
  nextId.value++;
  console.log(nextId.value);
};

3.todo-button组件

3.1.渲染按钮组件
<template>
  <div class="home container">
    <div class="mt-3 btn-container">
      <button type="button" class="btn btn-primary">全部</button>
      <button type="button" class="btn btn-secondary">完成</button>
      <button type="button" class="btn btn-secondary">未完成</button>
    </div>
  </div>
</template>
3.2.按钮样式激活(动态绑定class类名)
//在App.vue中
const activeIndex = ref(0);

<TodoButton :active="activeIndex" />

//在todo-button.vue中
<script setup>
const props = defineProps({
  active: Number
});
</script>

// 默认激活索引值为0的按钮(全部:0,已完成:1,未完成:2)
<template>
  <div class="home container">
    <div class="mt-3 btn-container">
      <button
        type="button"
        class="btn"
        :class="active === 0 ? 'btn-primary' : 'btn-secondary'"
      >
        全部
      </button>
      <button
        type="button"
        class="btn"
        :class="active === 1 ? 'btn-primary' : 'btn-secondary'"
      >
        完成
      </button>
      <button
        type="button"
        class="btn"
        :class="active === 2 ? 'btn-primary' : 'btn-secondary'"
      >
        未完成
      </button>
    </div>
  </div>
</template>

在这里插入图片描述

3.3.通过v-model激活按钮索引
需求分析:
父--->子:通过defineProps传递了激活项的索引(active)
子--->父:需要更新父组件中激活的索引
//在todo-button中
<template>
  <div class="home container">
    <div class="mt-3 btn-container">
      <button
        type="button"
        class="btn"
        :class="active === 0 ? 'btn-primary' : 'btn-secondary'"
        @click="onBtnClick(0)"
      >
        全部
      </button>
      <button
        type="button"
        class="btn"
        :class="active === 1 ? 'btn-primary' : 'btn-secondary'"
        @click="onBtnClick(1)"
      >
        完成
      </button>
      <button
        type="button"
        class="btn"
        :class="active === 2 ? 'btn-primary' : 'btn-secondary'"
        @click="onBtnClick(2)"
      >
        未完成
      </button>
    </div>
  </div>
</template>

//声明一个自定义事件,【子传父,带参数】
const emits = defineEmits(["onBtnChange"]);
const onBtnClick = (index) => {
  if (index === props.active) return;
  emits("onBtnChange", index);
};

//在App.vue中
<TodoButton :active="activeIndex" @onBtnChange="onBtnChange" />

const onBtnChange = (index) => {
  activeIndex.value = index;
};
3.4.用计算属性过滤数据
//在App.vue中
const tasklist = computed(() => {
  switch (activeIndex.value) {
    case 0:
      return todolist.value;
    case 1:
      return todolist.value.filter((x) => x.done === true);
    case 2:
      return todolist.value.filter((x) => x.done !== true);
  }
});


<TodoList :list="tasklist"/>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值