1.vue3.0允许在template里写多个根组件
效果:
目录结构:
TodoList.vue:
<template>
<Header @onAdd="handleAdd"></Header>
<List
:list="state.list"
@onChecked="handleChecked"
@onDelete="handleDelete"
></List>
</template>
<script>
import { reactive } from "vue";
import Header from "../components/Header";
import List from "../components/List";
export default {
components: {
Header,
List,
},
setup() {
const state = reactive({
list: [],
});
const handleAdd = (title) => {
state.list.push({
id: Date.now(),
title,
done: false,
});
};
const handleChecked = (payload) => {
let index = state.list.findIndex((item) => item.id === payload.id);
state.list[index].done = payload.checked;
};
const handleDelete = (payload) => {
state.list = state.list.filter((item) => item.id !== payload.id);
};
return {
state,
handleAdd,
handleChecked,
handleDelete,
};
},
};
</script>
<style>
</style>
Header.vue:
<template>
<div>
<input type="text" :value="title" @input="handleTitle" @keyup.enter="handleAdd" autofocus placeholder="请输入">
</div>
</template>
<script>
import { ref } from 'vue'
export default {
emits: ['onAdd'],
setup(props, context) {
const title = ref('')
const handleTitle = (e) => {
title.value = e.target.value
}
const handleAdd = () => {
context.emit('onAdd', title.value)
title.value = ''
}
return {
title,
handleTitle,
handleAdd
}
}
}
</script>
<style>
</style>
List.vue:
<template>
<div>正在进行({{ doningList.length }})</div>
<ListItem
v-for="item in doningList"
:key="item.id"
:item="item"
@onChecked="handleChecked"
@onDelete="handleDelete"
></ListItem>
<div>已经完成({{ doneList.length }})</div>
<ListItem
v-for="item in doneList"
:key="item.id"
:item="item"
@onChecked="handleChecked"
@onDelete="handleDelete"
></ListItem>
</template>
<script>
import { computed } from "vue";
import ListItem from "./ListItem";
export default {
props: ["list"],
components: {
ListItem,
},
setup(props, context) {
const doningList = computed(() => {
return props.list.filter((item) => !item.done);
});
const doneList = computed(() => props.list.filter((item) => item.done));
const handleChecked = (payload) => {
context.emit("onChecked", payload);
};
const handleDelete = (payload) => context.emit("onDelete", payload);
return {
doningList,
doneList,
handleChecked,
handleDelete,
};
},
};
</script>
<style>
</style>
ListItem.vue:
<template>
<div>
<input type="checkbox" :id="item.id" :checked="item.done" @change="handleChange"/>
<label :for="item.id">{{item.title}}</label>
<button @click="handleDelete">删除</button>
</div>
</template>
<script>
export default {
props: ['item'],
setup(props, context) {
const handleChange = (e) => {
context.emit('onChecked', { id: props.item.id, checked: e.target.checked })
}
const handleDelete = () => {
context.emit('onDelete', { id : props.item.id })
}
return {
handleChange,
handleDelete
}
}
}
</script>
<style>
</style>
参考链接: