持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情
前言
我们已经完成了整个todoMvc项目迁移使用脚手架的需求。接下来我们要对组件进行拆分。主要包括以下需求:
- 头部组件
- 全选操作组件
- 输入框组件
- 主体内容
- 主体内容容器组件
- todos列表组件
- 底部组件
- 数量显示组件
- 操作组件
- 清空按钮
那么接下来就让我们开始吧。
头部组件
- 头部组件包括两部分:全选操作、输入框,需要写两个组件
输入框
- 首先,vue3中已经不限制一个组件只能有一个自定义v-model了,我们可以通过
update:xxx来更新对应的值。 - 我们这里为了让
todos能在组件上响应式更新,采用了自定义v-model,通过computed的get函数接收props的值,set函数更新props的值,达到自定义v-model的效果。可以查看相关文档的使用方式 - 我们发送的
emit事件,需要通过emits先定义好,再进行使用,不然会直接报错说找不到相关事件,这样也方便我们知道组件中定义了多少自定义事件。 Header.vue
<template>
<header class="header">
<h1>todos</h1>
<input
v-model.trim="input"
@keyup.enter="addTodo"
class="new-todo"
placeholder="你需要做什么"
autocomplete="off"
autofocus
/>
</header>
</template>
<script>
import { computed, ref, toRefs, defineComponent } from 'vue';
export default defineComponent({
props: {
todos: String
},
emits: ['update:todos'],
setup(props, { emit }) {
const { todos } = toRefs(props);
const input = ref('');
const todosValue = computed({
get: () => todos.value,
set: (v) => {
emit('update:todos', v);
}
});
const addTodo = () => {
const text = input.value;
if (!text) return;
todosValue.value.push({ id: todosValue.value.length + 1, text, completed: false });
input.value = '';
};
return {
input,
addTodo
};
}
});
</script>
- 使用
<Header v-model:todos="todos" />
全选操作
- 全选操作需要处理的也是自定义
v-model - CheckAll.vue
<template>
<input v-model="allDoneValue" id="toggle-all" class="toggle-all" type="checkbox" />
<label for="toggle-all">点击完成所有事项</label>
</template>
<script>
import { computed, defineComponent } from 'vue';
export default defineComponent({
props: {
allDone: Boolean
},
emits: ['update:allDone'],
setup(props, { emit }) {
const allDoneValue = computed({
get() {
return props.allDone;
},
set(value) {
emit('update:allDone', value);
}
});
return { allDoneValue };
}
});
</script>
- 使用
<CheckAll v-model:allDone="allDone" />
总结
这一节我们对整体的组件拆分需求做了梳理,然后对头部组件做了对应的封装。
项目代码在GitHub,可以查阅