“今宵酒醒何处,杨柳岸晓风残月”,“蓦然回首,那人却在灯火阑珊处”,“试问闲愁都几许?一川烟草,满城风絮,梅子黄时雨” ...... 宋词可谓是古代文学桂冠上一颗璀璨的明珠,本题将实现一个在搜索框中输入关键字,实时显示符合条件的完整宋词的功能。
本题已经内置了初始代码,打开实验环境,目录结构如下:
├── css
│ └── style.css
├── data.json
├── index.html
└── js
├── axios.min.js
└── vue.min.js
其中:
index.html
是主页面。js/vue.min.js
是项目用到的 vue2.x 版本文件。js/axios.min.js
是 axios 文件。data.json
是项目中需要用到宋词数据。css/style.css
是样式文件。选中 index.html
右键启动 Web Server 服务(Open with Live Server),让项目运行起来。
接着,打开环境右侧的【Web 服务】,就可以在浏览器中看到如下效果:
请使用 Vue ,完成 index.html
文件中的 TODO 部分。
1. 完成数据请求(数据来源 ./data.json
),data.json
是宋词数据,poetry_content
表示词句,title
表示词牌名,author
表示词人。
2. 在输入框输入关键词时在 ul
(class = suggestions
)的元素中实时显示词牌名、词句、词人中包含关键词的完整词句(包含词牌名、词人)列表,当关键词为空或者匹配不到时 ul
(class = suggestions
)元素的子节点为空。完整词句的 DOM 结构按照如下规定显示:
<!-- 每一首完整词句用一个 li 包裹 -->
<li>
<span class="poet">词句</span>
<span class="title">词牌名 - 词人</span>
</li>
例:
<li>
<span class="poet"
>常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭</span
>
<span class="title">如梦令 - 李清照</span>
</li>
3. 高亮匹配到的所有词句中的关键词。即使用 <span class="highlight"></span>
标签包裹所有关键词。
例:(关键词:雨)
<li>
<span class="poet"
>寒蝉凄切,对长亭晚,骤<span class="highlight">雨</span
>初歇。都门帐饮无绪,方留恋处,兰舟催发。执手相看泪眼,竟无语凝噎。念去去千里烟波,暮霭沉沉楚天阔。多情自古伤离别,更那堪冷落清秋节。今宵酒醒何处,杨柳岸晓风残月。此去经年,应是良辰美景虚设。便纵有千种风情,更与何人说</span
>
<span class="title"><span class="highlight">雨</span>霖铃 - 柳永</span>
</li>
注意:本题要求的是实时显示,即输入完成的同时显示结果,非失去焦点显示。
完成后,最终页面效果如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>绝美宋词</title>
<link rel="stylesheet" href="css/style.css" />
<script src="./js/vue.min.js"></script>
<script src="./js/axios.min.js"></script>
</head>
<body>
<div id="app">
<h1 style="text-align: center">输入关键字,找一首词</h1>
<!-- 绑定输入框的输入事件 -->
<div class="search-form">
<input type="text" id="search" class="search" placeholder="词牌名 词句 词人" v-model="keyword" @input="filterPoetry"/>
<ul class="suggestions">
<!-- 循环渲染符合条件的词句 -->
<li v-for="poetry in filteredPoetry" :key="poetry.id">
<span class="poet" v-html="highlightKeyword(poetry.poetry_content, keyword)"></span>
<span class="title" v-html="highlightKeyword(poetry.title + ' - ' + poetry.author, keyword)"></span>
</li>
</ul>
</div>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
keyword: '', // 输入的关键词
poetryList: [], // 存储从 data.json 获取的所有宋词数据
filteredPoetry: [] // 存储过滤后的符合条件的宋词数据
},
mounted() {
// 组件挂载后请求数据
this.fetchPoetryData();
},
methods: {
fetchPoetryData() {
// 使用 axios 请求 data.json 文件
axios.get('./data.json')
.then(response => {
this.poetryList = response.data;
})
.catch(error => {
console.error('数据请求失败:', error);
});
},
filterPoetry() {
if (this.keyword === '') {
this.filteredPoetry = [];
} else {
this.filteredPoetry = this.poetryList.filter(poetry => {
// 检查词牌名、词句、词人中是否包含关键词
return poetry.poetry_content.includes(this.keyword) || poetry.title.includes(this.keyword) || poetry.author.includes(this.keyword);
});
}
},
highlightKeyword(text, keyword) {
if (!keyword) return text;
// 使用正则表达式替换关键词,并用 <span class="highlight"></span> 包裹
const regex = new RegExp(keyword, 'gi');
return text.replace(regex, '<span class="highlight">$&</span>');
}
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>绝美宋词</title>
<link rel="stylesheet" href="css/style.css" />
<script src="./js/vue.min.js"></script>
<script src="./js/axios.min.js"></script>
</head>
<body>
<div id="app">
<h1 style="text-align: center">输入关键字,找一首词</h1>
<!-- 绑定输入框的输入事件 -->
<div class="search-form">
<input type="text" id="search" class="search" placeholder="词牌名 词句 词人" v-model="keyword" @input="filterPoetry"/>
<ul class="suggestions">
<!-- 循环渲染符合条件的词句 -->
<li v-for="poetry in filteredPoetry" :key="poetry.id">
<span class="poet" v-html="highlightKeyword(poetry.poetry_content, keyword)"></span>
<span class="title" v-html="highlightKeyword(poetry.title + ' - ' + poetry.author, keyword)"></span>
</li>
</ul>
</div>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
keyword: '', // 输入的关键词
poetryList: [], // 存储从 data.json 获取的所有宋词数据
filteredPoetry: [] // 存储过滤后的符合条件的宋词数据
},
mounted() {
// 组件挂载后请求数据
this.fetchPoetryData();
},
methods: {
fetchPoetryData() {
// 使用 axios 请求 data.json 文件
axios.get('./data.json')
.then(response => {
this.poetryList = response.data;
})
.catch(error => {
console.error('数据请求失败:', error);
});
},
filterPoetry() {
if (this.keyword === '') {
this.filteredPoetry = [];
} else {
this.filteredPoetry = this.poetryList.filter(poetry => {
// 检查词牌名、词句、词人中是否包含关键词
return poetry.poetry_content.includes(this.keyword) || poetry.title.includes(this.keyword) || poetry.author.includes(this.keyword);
});
}
},
highlightKeyword(text, keyword) {
if (!keyword) return text;
// 使用正则表达式替换关键词,并用 <span class="highlight"></span> 包裹
const regex = new RegExp(keyword, 'gi');
return text.replace(regex, '<span class="highlight">$&</span>');
}
}
});
</script>
</body>
</html>
<head>
部分:
meta charset="UTF-8"
:设置文档的字符编码为 UTF - 8。<title>
:设置页面标题为 “绝美宋词”。<link>
:引入外部 CSS 文件 css/style.css
,用于页面样式。<script>
:引入 Vue.js 和 Axios 库,分别用于构建交互式界面和发送 HTTP 请求。<body>
部分:
<div id="app">
:Vue 实例的挂载点。<h1>
:显示标题 “输入关键字,找一首词”。<input>
:输入框,使用 v-model
指令绑定 keyword
数据属性,实现双向数据绑定;使用 @input
指令监听输入事件,调用 filterPoetry
方法进行数据过滤。<ul>
:用于显示符合条件的宋词列表,使用 v-for
指令循环渲染 filteredPoetry
数组中的元素。<span>
:分别显示词句和词牌名 - 词人信息,使用 v-html
指令插入经过高亮处理的 HTML 内容。<script>
部分:
#app
元素上。data
:定义三个数据属性:keyword
用于存储用户输入的关键词,poetryList
用于存储从 data.json
获取的所有宋词数据,filteredPoetry
用于存储过滤后的符合条件的宋词数据。mounted
:组件挂载后调用 fetchPoetryData
方法,发送 GET 请求获取 data.json
文件中的数据。methods
: fetchPoetryData
:使用 Axios 发送 GET 请求,将响应数据存储在 poetryList
中。filterPoetry
:根据 keyword
过滤 poetryList
中的数据,将符合条件的宋词数据存储在 filteredPoetry
中。highlightKeyword
:使用正则表达式替换文本中的关键词,并用 <span class="highlight"></span>
包裹,实现关键词高亮显示。html {
box-sizing: border-box;
background: hsl(145deg 30% 63%);
font-family: "Kaiti", "SimHei", "Hiragino Sans GB ", "helvetica neue";
font-size: 20px;
font-weight: 200;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
input {
width: 100%;
padding: 20px;
font-family: "Kaiti", "helvetica neue";
}
.search-form {
max-width: 700px;
margin: 50px auto;
}
input.search {
margin: 0;
text-align: center;
outline: 0;
border: 10px solid #f7f7f7;
width: 120%;
left: -10%;
position: relative;
top: 10px;
z-index: 2;
border-radius: 5px;
font-size: 40px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.12), inset 0 0 2px rgba(0, 0, 0, 0.19);
}
.suggestions {
margin: 0;
padding: 0;
position: relative;
/*perspective:20px;*/
}
.suggestions li {
background: white;
list-style: none;
border-bottom: 1px solid #d8d8d8;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.14);
margin: 0;
padding: 20px;
transition: background 0.2s;
display: flex;
justify-content: center;
}
.suggestions li:nth-child(even) {
transform: perspective(100px) rotateX(3deg) translateY(2px) scale(1.001);
background: linear-gradient(to bottom, #ffffff 0%, #efefef 100%);
}
.suggestions li:nth-child(odd) {
transform: perspective(100px) rotateX(-3deg) translateY(3px);
background: linear-gradient(to top, #ffffff 0%, #efefef 100%);
}
span.population {
font-size: 15px;
}
span.info {
display: flex;
flex-direction: column;
}
span.author,
span.title {
font-size: 0.8em;
/* right: 0;*/
}
span.title {
color: #7c8e94;
position: absolute;
right: 5px;
bottom: 1px;
}
.details {
text-align: center;
font-size: 15px;
}
.highlight {
color: #ff0000;
}
.love {
text-align: center;
}
a {
color: black;
background: rgba(0, 0, 0, 0.1);
text-decoration: none;
}
html
:设置页面的背景颜色、字体家族、字体大小和字体粗细。*, *:before, *:after
:使用 box-sizing: inherit
继承 html
元素的盒模型设置。input
:设置输入框的宽度、内边距和字体家族。.search-form
:设置搜索表单的最大宽度和外边距。input.search
:设置输入框的样式,包括边框、宽度、位置、字体大小和阴影等。.suggestions
:设置搜索结果列表的外边距和内边距。.suggestions li
:设置列表项的背景颜色、边框、阴影和内边距等。.suggestions li:nth-child(even)
和 .suggestions li:nth-child(odd)
:为偶数和奇数列表项设置不同的背景渐变和 3D 效果。span.population
、span.info
、span.author
、span.title
:设置不同元素的字体大小和颜色。.highlight
:设置高亮关键词的颜色为红色。[
{
"poetry_content": "寒蝉凄切,对长亭晚,骤雨初歇。都门帐饮无绪,方留恋处,兰舟催发。执手相看泪眼,竟无语凝噎。念去去千里烟波,暮霭沉沉楚天阔。多情自古伤离别,更那堪冷落清秋节。今宵酒醒何处,杨柳岸晓风残月。此去经年,应是良辰美景虚设。便纵有千种风情,更与何人说",
"title": "雨霖铃",
"author": "柳永"
},
// 其他宋词数据...
]
这是一个包含多个宋词对象的数组,每个宋词对象包含三个属性:
poetry_content
:存储宋词的具体词句。title
:存储词牌名。author
:存储词人姓名。四、工作流程 ▶️
#app
元素上,在 mounted
钩子函数中调用 fetchPoetryData
方法。fetchPoetryData
方法使用 Axios 发送 GET 请求,从 data.json
文件中获取宋词数据,并将数据存储在 poetryList
中。v-model
指令将输入的值绑定到 keyword
数据属性上。@input
事件,调用 filterPoetry
方法。filterPoetry
方法根据 keyword
过滤 poetryList
中的数据,将词牌名、词句、词人中包含关键词的宋词数据存储在 filteredPoetry
中。keyword
为空,则将 filteredPoetry
清空。v-for
指令循环渲染 filteredPoetry
数组中的元素,将每一首符合条件的宋词显示在 <ul>
元素中。highlightKeyword
方法对词句和词牌名 - 词人信息进行高亮处理,将匹配到的关键词用 <span class="highlight"></span>
包裹。