Vue 入门:从一个能筛选文章的组件开始

先做一个小到能看完的功能:输入关键词,文章列表跟着变化。你不用手动找 DOM、删除旧节点再插入新节点,只要描述“现在应该显示什么”。这就是声明式界面的起点。

把这个组件放进 Vue 3 项目

以下是完整单文件组件,替换独立 Vite Vue TypeScript 工程的 src/App.vue 即可使用;本仓库多页面实验的对应文件是 examples/frontend/vue/App.vue:

vue
<script setup lang="ts"> import { computed, ref } from 'vue' const query = ref('') const articles = ref([ { id: 'vue', title: 'Vue 响应式入门' }, { id: 'react', title: 'React 状态入门' }, ]) const visibleArticles = computed(() => { const keyword = query.value.trim().toLocaleLowerCase() return articles.value.filter((article) => article.title.toLocaleLowerCase().includes(keyword), ) }) </script> <template> <main> <label for="query">搜索文章</label> <input id="query" v-model="query" type="search" /> <p role="status">找到 {{ visibleArticles.length }} 篇文章</p> <ul v-if="visibleArticles.length"> <li v-for="article in visibleArticles" :key="article.id"> {{ article.title }} </li> </ul> <p v-else>没有匹配的文章,换个词试试。</p> </main> </template>

ref 保存可追踪的值,脚本中通过 .value 访问;模板中顶层 ref 可以自动解包。v-model 连接输入值和状态,computed 从现有数据计算筛选结果。<script setup> 在每个组件实例创建时执行,不是每次更新都重跑一遍整个 setup。

几个指令分别在管什么

v-if 决定一块内容是否存在,切换可能创建和销毁组件;v-show 主要切换显示样式,初始内容仍会渲染。频繁显隐和条件从不成立时的成本不同,按场景选。

v-for 描述列表,稳定的 key 帮助框架识别每条记录身份。可增删、排序的输入列表不要随手用数组下标,否则输入框本地状态可能跟错文章。@click 绑定事件,:disabled 绑定属性;它们只是 v-on、v-bind 的常用缩写。

ref 和 reactive 的边界

普通 let query = '' 改值不够,它没有接入 Vue 的响应式追踪。reactive 用代理包装对象;把其中的原始值直接解构到普通变量,通常会失去这条属性访问关系,可以用 toRef 或 toRefs 保留关联。

不要把这个结论生硬套到所有解构:Vue 3.5 在同一个 <script setup> 中对 defineProps 的解构有编译支持;它不是 JavaScript 解构突然具有了响应式。跨函数传参时仍要想清楚传的是当前值、ref,还是读取值的函数。

练习与参考

添加“只看收藏”复选框。请只保存关键词、复选框和原始文章数据,把结果数量继续作为派生值。输入空格、无匹配词、再清空,确认三种状态都正常。

从 JavaScript 基础过渡到这份 TypeScript 组件

本章是基础课后的第二遍练习。还不清楚 .vue、ref 或模板是什么时,先读“从网页基础开始”中的 Vue 完整页面。这里额外出现 lang=“ts”,表示脚本交给 TypeScript 工具处理;类型检查发生在开发与构建链中,浏览器并不会直接执行类型标注。

逐步改造:先只显示固定文章;再声明 query 并用插值把输入值显示出来;接入 v-model 后,确认输入状态确实变化;最后加入 computed 和列表筛选。每次只加一个环节,遇到问题就知道是输入绑定还是筛选计算出了错。

本例 ref 包住文章数组,因此以后 articles.value.push(…) 或修改响应式文章属性也可以触发相关更新。不要把 Vue 中这种响应式修改照搬到 React 的数组 state;两者约定不同。也不要因为这里支持深层追踪,就认为 shallowRef 的内部对象修改有同样语义。

“只看收藏”的参考实现需要在文章类型中增加 favorite 布尔字段,新增 favoritesOnly=ref(false),计算时同时满足标题条件与 !favoritesOnly.value || article.favorite。结果数量仍读 visibleArticles.length。运行空查询、只看收藏、无收藏三种情况,能够验证状态没有分叉。