Files
front-end-example/07-vue2/09-final-course-dashboard/answer.js
charlie 3435848495 feat: add Vue2 exercises for dynamic styles, lifecycle methods, component communication, and course management dashboard
- Implement dynamic styles and event handling in Vue2 with a card component.
- Create lifecycle methods exercise to simulate async data loading and instance destruction.
- Develop a component communication exercise with props, events, and slots.
- Build a comprehensive course management dashboard with filtering, statistics, and component interactions.
2026-03-23 10:09:29 +08:00

100 lines
2.4 KiB
JavaScript

Vue.component("level-badge", {
props: {
level: {
type: String,
default: "基础",
},
},
computed: {
badgeClass() {
return this.level === "进阶" ? "badge advanced" : "badge";
},
},
template: `<span :class="badgeClass">{{ level }}</span>`,
});
const CourseItem = {
props: {
course: {
type: Object,
required: true,
},
},
template: `
<article class="course-card" :class="{ 'is-done': course.finished }">
<div class="meta">
<level-badge :level="course.level"></level-badge>
<strong>{{ course.title }}</strong>
</div>
<p>{{ course.finished ? "当前已完成" : "当前学习中" }}</p>
<button type="button" @click="$emit('toggle', course.id)">
<slot name="action">操作</slot>
</button>
</article>
`,
};
new Vue({
el: "#app",
components: {
CourseItem,
},
data: {
keyword: "",
statusFilter: "all",
courses: [
{ id: 1, title: "Vue 实例基础", finished: true, level: "基础" },
{ id: 2, title: "模板语法与指令", finished: false, level: "基础" },
{ id: 3, title: "组件通信实战", finished: false, level: "进阶" },
{ id: 4, title: "生命周期和异步", finished: true, level: "进阶" },
],
},
computed: {
filteredCourses() {
const keyword = this.keyword.trim().toLowerCase();
return this.courses.filter((course) => {
const matchStatus =
this.statusFilter === "all" ||
(this.statusFilter === "done" && course.finished) ||
(this.statusFilter === "doing" && !course.finished);
const matchKeyword = !keyword || course.title.toLowerCase().includes(keyword);
return matchStatus && matchKeyword;
});
},
totalCount() {
return this.courses.length;
},
finishedCount() {
return this.courses.filter((course) => course.finished).length;
},
visibleCount() {
return this.filteredCourses.length;
},
},
watch: {
keyword(newValue) {
console.log("搜索关键字变化:", newValue);
},
},
methods: {
toggleCourse(courseId) {
this.courses = this.courses.map((course) => {
if (course.id === courseId) {
return {
...course,
finished: !course.finished,
};
}
return course;
});
},
focusSearch() {
this.$refs.searchInput.focus();
},
},
});