目录😋
介绍
通常网站上会有搜索功能,方便用户定位搜索。本次试题我们要使用 Vue 2 的语法来完成一个关键字匹配的搜索功能。
准备
本题已经内置了初始代码,打开实验环境,目录结构如下:
├── css │ └── style.css ├── images ├── index.html └── vue.min.js
其中:
css/style.css
是样式文件。images
是项目所用到的图片文件。index.html
是实现搜索功能的页面。vue.min.js
是 Vue 文件。选中
index.html
右键启动 Web Server 服务(Open with Live Server),让项目运行起来。 打开环境右侧的【Web 服务】,当前页面无法正常显示。
目标
请完善
index.html
文件,让页面具有如下所示的效果:
规定
- 请严格按照考试步骤操作,切勿修改考试默认提供项目中的文件名称、文件夹路径等。
- 满足题目需求后,保持 Web 服务处于可以正常访问状态,点击「提交检测」系统会自动判分。
通关代码✔️
//index.html <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <script src="vue.min.js"></script> <link rel="stylesheet" href="./css/style.css" /> </head> <body> <div id="app"> <div class="search-wrapper"> <input type="text" v-model="search" placeholder="请搜索" /> </div> <div class="wrapper"> <div class="card" v-for="post in filteredList"> <a v-bind:href="post.link" target="_blank"> <img v-bind:src="post.img" /> {{ post.title }} </a> </div> </div> </div> <script> class Post { constructor(title, link, img) { this.title = title; this.link = link; this.img = img; } } const app = new Vue({ el: "#app", data: { search: "", postList: [ new Post( "小猫咪", "https://unsplash.com/s/photos/cat", "./images/cat.png" ), new Post( "小狗狗", "https://unsplash.com/@joeyc", "./images/dog.png" ), new Post( "北极熊", "https://unsplash.com/@hansjurgen007", "./images/bar.png" ), new Post( "狮子", "https://unsplash.com/@hansjurgen007", "./images/lion.png" ), new Post( "小鸟", "https://unsplash.com/@eugenechystiakov", "./images/birds.png" ), new Post( "狐狸", "https://unsplash.com/@introspectivedsgn", "./images/fox.png" ), ], }, computed: { filteredList() { // TODO: 请补充代码 if(this.search === ''){ return this.postList; }else{ return this.postList.filter(post=>{ return post.title.toLowerCase().includes(this.search.toLowerCase()); }) } }, }, }); </script> </body> </html>
代码解析📑
1. HTML 部分
<html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <script src="vue.min.js"></script> <link rel="stylesheet" href="./css/style.css" /> </head> <body> <div id="app"> <div class="search-wrapper"> <input type="text" v-model="search" placeholder="请搜索" /> </div> <div class="wrapper"> <div class="card" v-for="post in filteredList"> <a v-bind:href="post.link" target="_blank"> <img v-bind:src="post.img" /> {{ post.title }} </a> </div> </div> </div> <script> // JavaScript 代码部分 </script> </body> </html>
解释:
<input type="text" v-model="search" placeholder="请搜索">
:
v-model="search"
:使用 Vue 的v-model
指令将输入框的值与 Vue 实例中的search
数据属性进行双向绑定。这意味着当用户在输入框中输入文本时,输入的内容会自动更新search
的值,反之亦然。
2. JavaScript 部分
class Post { constructor(title, link, img) { this.title = title; this.link = link; this.img = img; } } const app = new Vue({ el: "#app", data: { search: "", postList: [ new Post( "小猫咪", "https://unsplash.com/s/photos/cat", "./images/cat.png" ), new Post( "小狗狗", "https://unsplash.com/@joeyc", "./images/dog.png" ), new Post( "北极熊", "https://unsplash.com/@hansjurgen007", "./images/bar.png" ), new Post( "狮子", "https://unsplash.com/@hansjurgen007", "./images/lion.png" ), new Post( "小鸟", "https://unsplash.com/@eugenechystiakov", "./images/birds.png" ), new Post( "狐狸", "https://unsplash.com/@introspectivedsgn", "./images/fox.png" ), ], }, computed: { filteredList() { if(this.search === ''){ return this.postList; }else{ return this.postList.filter(post=>{ return post.title.toLowerCase().includes(this.search.toLowerCase()); }) } }, }, });
解释:
class Post
:
- 定义了一个
Post
类,用于存储每个帖子的信息,包括title
、link
和img
。
const app = new Vue({...})
:创建一个 Vue 实例。
data
:
search
:存储用户在输入框中输入的搜索关键字。postList
:存储一个Post
对象的数组,每个Post
对象包含一个帖子的信息。
computed
:
filteredList()
:一个计算属性,用于根据用户输入的关键字筛选postList
中的元素。
if(this.search === '')
:检查search
属性是否为空。
- 如果
search
为空,说明用户没有输入任何搜索关键字,直接返回整个postList
,显示所有帖子。
else
:如果search
不为空,使用filter
方法对postList
进行过滤。
this.postList.filter(post=>{...})
:
post => {...}
是filter
方法的回调函数,会对postList
中的每个post
对象进行操作。post.title.toLowerCase().includes(this.search.toLowerCase())
:
post.title.toLowerCase()
:将当前post
对象的title
属性转换为小写,确保搜索不区分大小写。this.search.toLowerCase()
:将用户输入的搜索关键字转换为小写。includes()
:检查post
的title
是否包含用户输入的关键字。- 如果包含,
includes()
方法返回true
,该post
对象会被添- 加到新数组中;否则,返回
false
,该post
对象会被排除。3. 工作流程▶️
- 用户在输入框中输入关键字。
- 输入的关键字通过
v-model
绑定到 Vue 实例的search
属性。- Vue 的响应式系统会检测到
search
属性的变化。- 由于
filteredList
是一个计算属性,它会重新计算。- 在
filteredList
的计算逻辑中:
- 如果
search
为空,返回完整的postList
数组。- 若
search
不为空,使用filter
方法遍历postList
数组,对每个post
对象检查其title
是否包含输入的关键字(不区分大小写),将符合条件的post
对象添加到一个新数组中。
- 最终,
v-for="post in filteredList"
会根据filteredList
计算属性的结果更新页面显示,只显示符合搜索关键字的帖子。4. 小总结😎
通过 Vue 的数据绑定(
v-model
)、计算属性(computed
)和数组的filter
方法,实现了一个简单但有效的关键字匹配搜索功能。用户输入的关键字会触发 Vue 实例中数据的更新,进而触发计算属性的重新计算,最终更新页面上显示的帖子列表,仅显示那些标题中包含用户输入关键字的帖子。这展示了 Vue 数据驱动视图的特性,让数据的更新自动反映在页面上,减少了手动操作 DOM 的繁琐,提高了开发效率。
测试结果👍