vue3入门13 - 组件化 todoMvc 项目-底部组件

161 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

前言

这一节我们对底部做一下组件封装

底部

数量显示

  • 这个组件主要做数据的过滤显示
  • Vue 3.0 中移除了过滤器,不再支持,我们可以使用函数或者计算属性来代替。
  • Count.vue
<template>
  <span class="todo-count"
    >进行中<strong>{{ remaining }}</strong
    >{{ pluralize(remaining) }} left
  </span>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
  props: {
    remaining: Number
  },
  setup() {
    const pluralize = (count) => {
      return count <= 1 ? 'item' : 'items';
    };
    return {
      pluralize
    };
  }
});
</script>

操作组件

  • 这里的封装主要是更新visibility值到父组件就可以了。
  • Filter.vue
<template>
  <ul class="filters">
    <li><a href="#/all" :class="{ selected: visibility === 'all' }">显示所有</a></li>
    <li><a href="#/active" :class="{ selected: visibility === 'active' }">进行中</a></li>
    <li><a href="#/completed" :class="{ selected: visibility === 'completed' }">已完成</a></li>
  </ul>
</template>
<script>
import { computed, defineComponent, onMounted, onUnmounted } from 'vue';
import { filters } from '@/utils/index';

export default defineComponent({
  props: {
    visibility: String
  },
  emits: ['update:visibility'],
  setup(props, { emit }) {
    const visibilityValue = computed({
      get: () => props.visibility,
      set: (v) => {
        emit('update:visibility', v);
      }
    });
    onMounted(() => {
      window.addEventListener('hashchange', onHashChange);
      onHashChange();
    });

    onUnmounted(() => {
      window.removeEventListener('hashchange', onHashChange);
    });

    const onHashChange = () => {
      const hash = window.location.hash.replace(/#\/?/, '');
      if (filters[hash]) {
        visibilityValue.value = hash;
      } else {
        visibilityValue.value = 'all';
        window.location.hash = '';
      }
    };
    return {};
  }
});
</script>

清空按钮

  • 这里的封装主要是更新todos的值到父组件
  • Completed.vue
<template>
  <button v-show="todos.length > remaining" @click="removeCompleted" class="clear-completed">
    清除已完成
  </button>
</template>
<script>
import { defineComponent, toRefs, computed } from 'vue';
import { filters } from '@/utils/index';

export default defineComponent({
  props: {
    todos: Array,
    remaining: Number
  },
  emits: ['update:todos'],
  setup(props, { emit }) {
    const { todos } = toRefs(props);
    const todosValue = computed({
      get: () => todos.value,
      set: (v) => {
        emit('update:todos', v);
      }
    });
    const removeCompleted = () => {
      todosValue.value = filters.active(todos.value);
    };
    return {
      removeCompleted
    };
  }
});
</script>

总结

组件的拆分做完了,我们可以做一下对比 image.png

  • 封装之前我们把所有样式、逻辑放到一个文件中,杂而且乱,如果想修改某部分功能需要上下翻看很多行代码。
  • 封装之后有没有感觉整体清爽了很多,需要修改哪部分逻辑,我们去对应的组件修改就可以了,不会被太多无关代码影响到。

那么下一节,我们来做下逻辑上的封装。

项目代码在GitHub,可以查阅