Files
2026-03-26 21:45:32 +08:00

75 lines
1.9 KiB
JavaScript

Vue.component("course-badge", {
props: {
label: {
type: String,
default: "默认角标",
},
},
template: `<span style="display:inline-block;margin-bottom:8px;padding:4px 10px;border-radius:999px;background:#eef4ff;color:#2d6cdf;">{{ label }}</span>`,
});
const CourseCard = {
props: {
course: {
type: Object,
required: true,
},
theme: {
type: String,
default: "normal",
validator(value) {
return ["normal", "accent"].includes(value);
},
},
},
template: `
<article class="card" :style="theme === 'accent' ? 'border-color:#2d6cdf;' : ''">
<course-badge :label="course.level"></course-badge>
<h2>{{ course.title }}</h2>
<p :class="{ done: course.finished }">
{{ course.finished ? "已完成" : "学习中" }}
</p>
<button type="button" @click="$emit('toggle', course.id)">
<slot name="action">操作</slot>
</button>
</article>
`,
};
new Vue({
el: "#app",
components: {
CourseCard,
},
data: {
keyword: "",
courses: [
{ id: 1, title: "Vue 实例", finished: true, level: "基础" },
{ id: 2, title: "模板语法", finished: false, level: "基础" },
{ id: 3, title: "组件通信", finished: false, level: "进阶" },
],
},
computed: {
filteredCourses() {
// 任务:根据 keyword 过滤课程列表
let value = this.keyword.trim().toUpperCase()
return this.courses.filter(item => item.title.toUpperCase().includes(value))
},
},
methods: {
toggleCourse(courseId) {
// 任务:根据 courseId 切换 finished
const a = this.courses.find(item => {
if (item.id === courseId) {
item.finished = !item.finished
}
return;
})
},
focusInput() {
// 任务:通过 ref 聚焦输入框
this.$refs.keywordInput.focus()
},
},
});