vue3
解释
移除 export default:<script setup> 语法是一个编译时的语法糖,不需要显式地定义一个组件对象。
直接声明变量:在 <script setup> 中,所有的顶层变量和函数都直接暴露给模板使用,因此你可以直接声明并使用 rootTask。
组件导入:组件导入和使用方式保持不变,依然通过 import 语句导入组件。
这种方式不仅简化了代码,而且提高了性能,因为 Vue 可以在编译阶段进行一些优化。
< script setup >
<template>
<div>{{ dev }}
<div @click="dev='aaaaaaaaaaaaaaa'">改成a</div>
<div @click="dev='bbbbbbbbbbbbbbb'">改成b</div>
<RecursiveCard :data="rootTask" :dev="dev" />
</div>
</template>
<script setup>
import { reactive } from 'vue';
import RecursiveCard from './test.vue'; // 递归组件的路径
const rootTask = reactive({
list: [
'List item 1',
'List item 2',
'List item 3',
'List item 4'
],
children: []
});
</script>
<style>
/* 这里可以添加一些全局样式 */
</style>
< script >
<template>
<div>
<RecursiveCard :data="rootTask" />
</div>
</template>
<script >
import { reactive } from 'vue';
import RecursiveCard from './test.vue'; // 递归组件的路径
export default {
components: {
RecursiveCard,
},
setup() {
const rootTask = reactive({
list: [
'List item 1',
'List item 2',
'List item 3',
'List item 4'
],
children: []
});
return {
rootTask
};
}
};
</script>
<style>
/* 这里可以添加一些全局样式 */
</style>
test.vue
<template>
<el-card style="margin-bottom: 20px;">
<template #header>
<div class="card-header">
<span><el-button type="primary" @click="addSubTask">新增子作业</el-button></span>
</div>
</template>
<p v-for="(item, index) in data.list" :key="index" class="text item">
{{ item }}
</p>
<template #footer>Footer content</template>
<div v-if="data.children && data.children.length">
<RecursiveCard v-for="(child, index) in data.children" :key="index" :data="child" />
</div>
</el-card>
</template>
<script>
export default {
name: 'RecursiveCard',
props: {
data: {
type: Object,
required: true,
},
},
methods: {
addSubTask() {
// 这里添加子作业逻辑
const newSubTask = {
list: ['List item 1', 'List item 2', 'List item 3', 'List item 4'],
children: [] // 你可以根据需要初始化子作业的 children
};
if (!this.data.children) {
this.$set(this.data, 'children', []);
}
this.data.children.push(newSubTask);
},
},
};
</script>
<style scoped>
/* 这里可以添加一些局部样式 */
</style>
将子组件转换为 <script setup>
语法可以让代码更加简洁和高效。以下是你的子组件转换后的代码:
<template>
<el-card style="margin-bottom: 20px;">
<template #header>
<div class="card-header">
<span><el-button type="primary" @click="addSubTask">新增子作业</el-button></span>
</div>
</template>
<p v-for="(item, index) in data.list" :key="index" class="text item">
{{ item }}
</p>
<template #footer>Footer content</template>
<div v-if="data.children && data.children.length">
<RecursiveCard v-for="(child, index) in data.children" :key="index" :data="child" />
</div>
</el-card>
</template>
<script setup>
import { toRefs } from 'vue';
import RecursiveCard from './test.vue'; // 递归组件的路径
const props = defineProps({
data: {
type: Object,
required: true,
},
});
const { data } = toRefs(props);
const addSubTask = () => {
const newSubTask = {
list: ['List item 1', 'List item 2', 'List item 3', 'List item 4'],
children: [] // 你可以根据需要初始化子作业的 children
};
if (!data.value.children) {
data.value.children = [];
}
data.value.children.push(newSubTask);
};
</script>
<style scoped>
/* 这里可以添加一些局部样式 */
</style>
解释
- 使用
defineProps
:在<script setup>
中,使用defineProps
来定义组件的props
。 - 使用
toRefs
:将props
转换为响应式引用,以便在模板和方法中更方便地使用。 - 直接声明方法:在
<script setup>
中,直接声明方法,不需要methods
选项。 - 访问
props
:通过解构toRefs
的结果来访问props
,这样可以保持响应性。
这样改写不仅简化了代码,而且可以利用 Vue 3 的编译时优化,提高性能。
设置子组件监听事件
<template>
<div>{{ dev }}
<div @click="dev='aaaaaaaaaaaaaaa'">改成a</div>
<div @click="dev='bbbbbbbbbbbbbbb'">改成b</div>
<RecursiveCard :data="rootTask" :dev="dev" />
</div>
</template>
<script setup>
import { reactive } from 'vue';
import RecursiveCard from './test.vue'; // 递归组件的路径
const dev = ref('wwwwwwwwwwwwwwwww');
const rootTask = reactive({
list: [
'List item 1',
'List item 2',
'List item 3',
'List item 4'
],
children: []
});
</script>
<style>
/* 这里可以添加一些全局样式 */
</style>