vue3-03筛选任务

前置知识:生命周期函数在vue3不再是配置式的,而是一个普通函数。
步骤:

  1. 确认筛选条件是通过hash值
  2. 声明filter函数:通过hash改变的筛选得到对应的任务列表
  3. userFilter.js文件:用于任务的筛选。
    1. 使用一个响应式变量visibilityRef 来取得筛选条件hash
    2. 使用声明周期函数onMounted,监听hash的变化
    3. 使用声明周期函数onUnmounted,销毁hash的监听
    4. 明确筛选后的任务列表,是需要通过初始的任务列表todosRef和筛选条件visibilityRef 来计算得到的。而todosRef在另外一个js,因此需要在App.vue文件中传递过来。
    5. 根据页面需要展示的信息来计算出对应的内容。在这里插入图片描述
filter函数
/**
 * 任务筛选
 * @param {*} todos 任务列表
 * @param {*} visibility 筛选条件
 */
export function filter(todos,visibility = 'all') {
    if(visibility === 'all'){
        return todos;
    }
    else if (visibility === 'active'){
        return todos.filter((it) => !it.completed);
    }
    else if(visibility === 'completed') {
        console.log(todos.filter((it) => it.completed),'todos.filter((it) => it.completed)')
        return todos.filter((it) => it.completed);
    }
    throw new Error ("invalid visibility value");
}
userFilter.js
// 生命周期函数在vue3不再是配置式的,而是一个普通函数
import {
    computed,
    onMounted,
    onUnmounted,
    ref
} from "vue";
import {
    filter
} from "../util/todoStorage";

const validHash = ['all', 'active', 'completed']
export default function useFilter(todosRef) {
    const visibilityRef = ref("all") // 筛选条件

    // 根据哈希值取得筛选条件
    const onHashChange = () => {
        // 通过调用 replace(/#\/?/, ""),我们使用正则表达式将 # 或 #/ 替换为空字符串,从而得到去除 # 或 #/ 的结果。
        const hash = location.hash.replace(/#\/?/, "");
        if (validHash.includes(hash)) {
            // 存在的
            visibilityRef.value = hash;
        } else {
            location.hash = '';
            visibilityRef.value = 'all';
        }
    }

    // 1. 组件挂载完成的生命周期函数
    onMounted(() => {
        // hashchange: 此方法是用于监听hash的变化
        return window.addEventListener('hashchange', onHashChange);
    });
    // 2. 组件销毁过后的生命周期函数
    onUnmounted(() => {
        window.removeEventListener("hashchange", onHashChange);
    });

    // 根据筛选条件去筛选列表任务,进而计算出应该展示的任务列表
    const filteredTodosRef = computed(() => {
        return filter(todosRef.value, visibilityRef.value);
    })

    // 计算出未完成的数量:用于页面左下角的待完成的数量
    const remainingRef = computed(() => {
        return filter(todosRef.value, 'active').length;
    })

    // 计算已完成的数量:用于页面判断是否展示右下角的 Clear completed按钮
    const completedRef = computed(() => {
        return filter(todosRef.value, 'completed').length;
    })

    return {
        visibilityRef,
        filteredTodosRef,
        remainingRef,
        completedRef
    }
}
App.vue
<template>
  <link rel="stylesheet" href="./style.css" />
  <div id="app">
    <section class="todoapp">
      <header class="header">
        <h1>todos</h1>
        <input class="new-todo" autofocus="" autocomplete="off" placeholder="What needs to be done?" v-model="newTodoRef"
          @keyup.enter="addTodo" />
      </header>
      <section class="main">
        <input id="toggle-all" class="toggle-all" type="checkbox"/>
        <label for="toggle-all">Mark all as complete</label>
        <ul class="todo-list">
          <li class="todo" v-for="todo in filteredTodosRef" :key="todo.id" :class="{completed:todo.completed}">
            <div class="view">
              <input class="toggle" type="checkbox" v-model="todo.completed" />
              <label>{{todo.title}}</label>
              <button class="destroy"></button>
            </div>
            <input class="edit" type="text" />
          </li>
        </ul>
      </section>
      <footer class="footer">
        <span class="todo-count">
          <strong>{{remainingRef}}</strong>
          <span>item{{remainingRef === 1 ?'' : 's'}} left</span>
        </span>
        <ul class="filters">
          <li><a href="#/all" :class="{selected: visibilityRef === 'all'}">All</a></li>
          <li><a href="#/active" :class="{selected: visibilityRef === 'active'}">Active</a></li>
          <li><a href="#/completed" :class="{selected: visibilityRef === 'completed'}">Completed</a></li>
        </ul>
        <button class="clear-completed" v-show="completedRef">
          Clear completed
        </button>
      </footer>
    </section>
  </div>
</template>

<script>
import useTodoList from "./composition/useTodoList"
import useNewTodo from "./composition/useNewTodo"
import useFilter from "./composition/useFilter";
export default {
  setup() {
    const { todosRef } = useTodoList();
    return {
      todosRef,
      ...useNewTodo(todosRef),
      ...useFilter(todosRef)
    }
  }
}
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值