当然, 我们可以扩展之前的 Todo 例程, 加入编辑功能和 Markdown 支持。我们将使用一个简单的 Markdown 解析器 (如 marked. Js)来实现 Markdown 功能。以下是更新后的代码:
- 首先, 安装必要的依赖:
bun add marked- 更新
src/App.vue:
<template>
<div class="p-4 max-w-2xl mx-auto">
<h1 class="text-3xl font-bold mb-4">Todo App with Markdown</h1>
<form @submit.prevent="addTodo" class="mb-4">
<input v-model="newTodo" type="text" placeholder="Add a new todo" class="border p-2 mr-2 w-full mb-2">
<button type="submit" class="bg-blue-500 text-white p-2 rounded hover:bg-blue-600">Add</button>
</form>
<ul>
<li v-for="todo in todos" :key="todo.id" class="mb-4 bg-gray-100 p-4 rounded">
<div v-if="editingId !== todo.id">
<div class="flex items-center mb-2">
<input type="checkbox" v-model="todo.completed" class="mr-2">
<span :class="{ 'line-through': todo.completed }">{{ todo.text }}</span>
<button @click="startEditing(todo)" class="ml-auto text-blue-500 mr-2">Edit</button>
<button @click="removeTodo(todo.id)" class="text-red-500">Remove</button>
</div>
<div v-html="renderMarkdown(todo.text)" class="markdown-content text-sm text-gray-600"></div>
</div>
<div v-else>
<textarea v-model="editingText" class="w-full p-2 border rounded mb-2"></textarea>
<button @click="saveEdit(todo)" class="bg-green-500 text-white p-2 rounded mr-2">Save</button>
<button @click="cancelEdit" class="bg-gray-500 text-white p-2 rounded">Cancel</button>
</div>
</li>
</ul>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import { marked } from 'marked'
interface Todo {
id: number
text: string
completed: boolean
}
export default defineComponent({
name: 'App',
setup() {
const newTodo = ref('')
const todos = ref<Todo[]>([])
const editingId = ref<number | null>(null)
const editingText = ref('')
const addTodo = () => {
if (newTodo.value.trim()) {
todos.value.push({
id: Date.now(),
text: newTodo.value,
completed: false
})
newTodo.value = ''
}
}
const removeTodo = (id: number) => {
todos.value = todos.value.filter(todo => todo.id !== id)
}
const startEditing = (todo: Todo) => {
editingId.value = todo.id
editingText.value = todo.text
}
const saveEdit = (todo: Todo) => {
if (editingText.value.trim()) {
todo.text = editingText.value
cancelEdit()
}
}
const cancelEdit = () => {
editingId.value = null
editingText.value = ''
}
const renderMarkdown = (text: string) => {
return marked(text)
}
return {
newTodo,
todos,
editingId,
editingText,
addTodo,
removeTodo,
startEditing,
saveEdit,
cancelEdit,
renderMarkdown
}
}
})
</script>
<style>
.markdown-content {
@apply prose prose-sm;
}
</style>- 更新
uno.config.ts以支持 Markdown 样式:
import { defineConfig, presetUno, presetTypography } from 'unocss'
export default defineConfig({
presets: [
presetUno(),
presetTypography(),
],
})这个更新后的 Todo 应用现在具有以下新功能:
- 编辑功能: 用户可以点击 “Edit” 按钮来编辑现有的 Todo 项目。
- Markdown 支持: Todo 项目的文本内容支持 Markdown 格式, 并会被渲染为 HTML。
- 改进的 UI: 使用了更多的 UnoCSS 类来美化界面。
使用说明:
- 添加新的 Todo 项目时, 可以使用 Markdown 语法。
- 点击 “Edit” 按钮可以编辑现有的 Todo 项目。
- 编辑时, 可以查看和修改原始的 Markdown 文本。
- 保存编辑后, Markdown 内容会被重新渲染。
这个例子展示了如何将 UnoCSS 与 Vue 3、TypeScript 和 Markdown 功能结合使用, 创建一个功能更丰富的 Todo 应用。UnoCSS 的 prose 类用于美化渲染后的 Markdown 内容, 使其更易读。
注意: 为了安全起见, 在实际应用中, 你可能需要使用一个 Markdown 解析器, 它可以防止 XSS 攻击, 例如使用 DOMPurify 来清理 HTML 输出。