使用OVH API的Vanilla JavaScript构建一个歌词搜索应用程序
不知道歌曲的歌词是大多数爱唱歌的人遇到的问题。在这篇文章中,我们将创建一个平台,用户可以通过输入艺术家的名字或歌名来搜索歌词。
我们将使用HTML5、CSS3、Vanilla JavaScript、带有*fetch()方法的async-await、OVH API和ECMAScript 2015 (ES6)*箭头函数创建歌词网络应用。
前提条件
要跟上本教程,你需要。
- 一个代码编辑器,如Visual Studio Code。
- HTML5、CSS和JavaScript的基本知识。
- 一台有互联网连接的电脑。
用HTML5构建歌词搜索应用程序
首先,创建一个名为lyrics-app 的文件夹,并在该文件夹中添加三个文件。lyrics.html,lyrics.css, 和lyrics.js 。
我们将使用HTML5来构建歌词搜索应用程序。本节涉及到lyrics.html 。
在HTML文件的head 标签中,你将输入预定义的元标签,这些标签对所有网络应用都是必不可少的。
我们还将把CSS文件链接到HTML文件中,并给网络应用命名为Lyrics Search App 。
接下来,创建一个div ,其类别为container 。这个div ,将包含以后要创建的其他div。
添加另一个div ,其类别为intro-text ,并分别包含其他两个h1 和h2 标签。
h1 标签的内容是Learn your favorite song ,而h2 标签将包含song lyrics 。
在带有类container 的div 内,你将创建一个div 和一个id 的lyrics-search ,在这里我们创建一个包含输入字段的表单,还有另一个div 来显示取来的歌词。
你的HTML代码应该如下所示。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="lyrics.css"/>
<title>Lyrics Search App</title>
</head>
<body>
<div class="container">
<div class="intro-text">
<h1>Learn your favorite</h1>
<h2>song lyrics</h2>
</div>
<div id="lyrics-search">
<form action="" id="searchMe">
<input type="text" id="lyricSearch" placeholder="artist name or song title"/>
</form>
<div id="search-result">
</div>
</div>
</div>
<script src="lyrics.js">
</script>
</body>
</html>
设计歌词搜索应用程序
下一步是用CSS设计网络应用(Lyrics.css)。
div 首先,为整个HTML、正文和container ,该类体现了所有其他divs 。
html {
box-sizing:border-box;
}
/**Use pseudo elements to set some static styles**/
*,
*:before,
*:after {
margin:0;
Padding:0;
}
body {
background:#333333;
}
.container {
margin:0 auto;
}
接下来,对body 标签的内容进行样式化--从定义网络应用对占位符和输入字段的文字开始。
/**This is how placeholders are styled**/
::placeholder {
color:gold;
}
我们现在需要用文本Learn your favorite song lyrics 来样式化页面描述,如下所示。
/**Styling the intro text `div` which has the content of “learn your favorite song” lyrics**/
.intro-text {
font-family: Verdana, Geneva, Tahoma, sans-serif;/**If the device doesn't have any of the first three font-family sans-serif will automatically be used **/
padding:2rem 0;
color:gold;
}
/**Styling the h1 header(learn your favourite):centering the h1 element**/
h1 {
text-align:center;
padding:1rem 0;
}
/**Styling the h1 header(learn your favourite):centering the h1 element**/
h2 {
text-align:center;
padding:1rem 0;
}
/**You can use the comma-separated form of styling tags with the same properties.
将嵌入表单和输入栏的div 容器居中,使用其id (lyrics-search)。
#lyrics-search {
text-align:center;
align-items:center;
margin:20px;
padding:20px;
}
最后,对表单和输入字段进行样式设计,如下图所示。
form {
margin:0 auto;
padding-left:10rem;
}
/**style the input field using its id(lyricSearch)**/
#lyricSearch {
background-color: transparent;
color:#eeeeee;
outline:none;
height:30px;
width:64%;
margin:0 auto;
padding-right:2rem;
font-size:16px;
font-family:cursive;
outline-style:none;
border-top:none;
border-left:none;
border-right:none;
border-bottom:1px solid #eeeeee;
}
现在我们已经通过添加颜色、字体大小、字体家族、填充和边距成功地设计了网页。
下面是你的网页应该是什么样子的。

OVH API的简单介绍
OVH API是一个简单的API,帮助我们检索歌曲的歌词。我们使用两个参数来获取数据(歌词)。这两个参数是。
- 艺术家的名字。
- 歌曲的标题。
当请求被提出时,数据以JSON格式返回。我们还得到两个状态代码。
- 状态代码200表示API调用成功。
- 状态代码404表示API调用失败。
一个正在运行的URL的例子看起来像这样:https://api.lyrics.ovh/v1/Drake/Toosie Slide 。
在上面的例子中,Drake 代表艺术家的名字,而Toosie Slide 是歌曲的标题。
用JavaScript添加功能
在你的lyrics.js 文件中,声明变量并使用DOM选择器与lyrics.html 文件中的元素连接,使用下面的代码片断。
//defining variables
const form = document.getElementById("searchMe"); //target the form tag in the html file
const search = document.getElementById("lyricSearch"); //target the input field
const output = document.getElementById("search-result"); //target the output `div`
为这个网络应用程序检索数据(歌词)所需的API是OVH API。
使用下面的代码声明API的URL。
const api = "https://api.lyrics.ovh";
下一个阶段是提交表单。你将定义如果输入字段有一个值或为空会发生什么。
要做到这一点,使用DOM事件创建一个事件监听器来监听一个提交事件。注意,我们不能使用点击事件,因为我们没有一个按钮。
下面是这个功能的代码片断。
// Get Search Value
form.addEventListener("submit", e => {
e.preventDefault();
searchValue = search.value.trim();
if (!searchValue) {
alert("Nothing to search");
} else {
startSearch(searchValue);
}
})
在上面的代码中。
-
你监听了一个提交事件,之后你声明了一个变量
searchValue,等于search.value.trim()。trim()方法只是删除了空白。 -
如果
searchValue等于一个空字符串,应用程序就会显示一个警告信息,否则,它就会调用startSearch()函数,并将searchValue作为参数。
现在,我们可以使用async-await和fetch方法来从OVH歌词API中检索数据。
下面是获取数据的代码片段。
async function startSearch(searchValue) {
const searchResult = await fetch(`${api}/suggest/${searchValue}`);
const data = await searchResult.json();
console.log(data);
showData(data);
}
测试网络应用程序的当前状态
我们需要测试当你在搜索字段中输入歌曲的标题或艺术家的名字时,网络应用是否从OVH API返回数据。
首先,注释掉上面代码段中的showData 函数(记住以后要取消注释showData 函数)。
使用直播服务器vscode扩展启动网络应用。
在搜索栏中输入一首歌曲(注意有些建议的歌词在这个API上是不可用的)。
控制台记录结果(要访问控制台,在网页内点击右键,点击检查选项,然后导航到chrome开发工具中的控制台)。
你的屏幕应该像下面的屏幕截图一样。

在上面的截图中,我搜索了一首标题为cast 的歌曲。
我们需要创建一个函数showData() ,在控制台中显示数据。showData() 方法是由startSearch() 函数调用的。
下面是showData() 函数的代码。
// Display Search Result
function showData(data) {
output.innerHTML = `
<ul class="lyrics">
${data.data
.map(song=> `<li>
<div>
<strong>${song.artist.name}</strong> -${song.title}
</div>
<span class="btn" data-artist="${song.artist.name}" data-songtitle="${song.title}">Get Lyrics</span>
</li>`
)
.join('')}
</ul>
`;
}
上述函数将在lyrics.html 文件中的一个空的div 内显示歌词。
内部--HTML
这是DOM属性,可以设置或检索一个HTML元素的内容。
我们将设置lyrics.html 文件中的空div 的内容,以列表形式显示歌词的建议。
来自API的数据有一些具有我们想在网页上显示的属性的对象集。
我们关心的是如何在网页上显示歌名和歌手的名字。
map() 是最常用的方法之一。它根据现有数组的值返回一个新的数组。
例如,我们有一个numbers 数组,我们想把每个值乘以3,然后把它们加入一个新的数组。
const numbers = [2 , 4, 6, 8];
const tripleNo = numbers.map(tripleNum);
function tripleNum(number) {
return number * 3;
}
console.log(tripleNo);//logs [6,12,18,24]
通常情况下,为了访问歌曲标题和艺术家的名字,你会调用data.data.title 来获取歌曲标题,调用data.data.artist.name 来获取艺术家的名字。如果你还记得,参数--歌曲代表了结果数据。
由于我们已经对数据进行了映射,你可以使用song.title 来访问歌名,也可以使用song.artist.name 来访问艺术家的名字。
下面的代码帮助我们在输出的InnerHTML内监听一个点击事件。
//event listener in get lyrics button
output.addEventListener('click', e=>{
const clickedElement = e.target;
//checking clicked element is button or not
if (clickedElement.tagName === 'SPAN'){
const artist = clickedElement.getAttribute('data-artist');
const songTitle = clickedElement.getAttribute('data-songtitle');
getLyrics(artist, songTitle);
}
})
上面的代码有助于知道被点击的元素是否是span标签(即如果变量clickedElement 包含span 作为tagName )。如果是这样,if 块中的语句就会被执行。
你将在变量songTitle 中存储属性data-song.title ,以及在变量artist 中存储属性data-artist ,getLyrics() 函数将这两个变量作为参数。
注意,参数是当函数被调用时传递给它的实际值,而参数是当函数被定义时传递的值。
GetLyrics() - 异步函数
这是最重要的函数,因为它允许我们显示歌曲的歌词。
该函数接收了两个参数,分别是artist 和songTitle 。回顾一下,你可以通过输入艺术家的名字或歌曲标题来搜索歌词。
下面是getLyrics() 函数的代码。
async function getLyrics(artist, songTitle) {
const response = await fetch(`${api}/v1/${artist}/${songTitle}`);
const data = await response.json();
const lyrics = data.lyrics;
if (lyrics === undefined){
alert('lyrics doesnt exist in this api');
console.log('lyrics doesnt exist in this api');
}
output.innerHTML = `<h2><strong>${artist}</strong> - ${songTitle}</h2>
<p id="lyrics-display">${lyrics}</p>`;
}
注意,OVH API在其免费版本下并不能访问所有的歌词。如果你想获得所有的歌词,我建议你买一个付费版本。
undefined 如果某个特定的歌词不可用,它将在div 。它还提醒你该歌词在API上不可用。
接下来,你可以决定在变量歌词中使用replace 的方法实现正则表达式(REGEX)语法,在歌词变量中加入.replace(/(\r\n|\r|\n)/g ,'<br>'); 。
const lyrics = data.lyrics.replace(/(\r\n|\r|\n)/g ,'<br>');
这将返回排列整齐的歌词,可以在网页上显示。
REGEX的使用有助于在我们的数据(歌词)中寻找。
- 单独返回的回车。
- 与新行一起返回的回车。
如果发现上面定义的任何一个实例,replace() 方法将其替换为<br> (断行)。
/g 是一个正则表达式标志,它意味着全局。整个数据(歌词)应该被搜索一遍(为所有匹配)。
当span标签被点击时,歌词将显示在段落标签中。
歌词的样式和居中
导航到你的CSS文件,并添加下面的代码,使歌词的样式和居中。
.lyrics {
width: 70%;
list-style: none;
margin: 0 auto;
padding: 2rem 0;
}
.lyrics li {
font-size: 1.4rem;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
padding: 5px 0;
border-bottom: 1px solid gold;
}
.lyrics li span {
font-size: 1.4rem;
padding: 5px;
margin: 5px;
cursor: pointer;
}
.lyrics li span:hover {
background-color: lightyellow;
}
/*styling the button to get the lyrics*/
.btn {
padding: 4px;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
outline: none;
border-radius: 3px;
text-decoration: none;
font-size: 1.2rem;
cursor: pointer;
background-color: gold;
color: white;
}
你可以在这里找到完整的JavaScript代码。
//defining the variables
const form = document.getElementById("searchMe");//target the form tag in the html file
const search = document.getElementById("lyricSearch");//target th input field
const output = document.getElementById("search-result");
const api = "https://api.lyrics.ovh";
//structuring how the result will be displayed using the suggestion mode the API supports
function showData(data) {
output.innerHTML = `
<ul class="lyrics">
${data.data
.map(song=> `<li>
<`div`>
<strong>${song.artist.name}</strong> -${song.title}
</`div`>
<span class="btn" data-artist="${song.artist.name}" data-songtitle="${song.title}">Get Lyrics</span>
</li>`
)
.join('')}
</ul>
`;
}
//declaring async function to fetch data from api
async function startSearch(searchValue) {
const searchResult = await fetch(`${api}/suggest/${searchValue}`);
const data = await searchResult.json();
showData(data);
}
//calling the function that gets and displays the lyrics
async function getLyrics(artist, songTitle) {
const response = await fetch(`${api}/v1/${artist}/${songTitle}`);
const data = await response.json();
const lyrics = data.lyrics;
if (lyrics === undefined){
alert('lyrics doesnt exist in this api');
console.log('lyrics does not exist in this api');
}
output.innerHTML = `<h2><strong>${artist}</strong> - ${songTitle}</h2>
<p id="lyrics-display">${lyrics}</p>`;
}
//listening if the clicked event is on the span tag, so lyrics can be called and displayed
output.addEventListener('click', e=>{
const clickedElement = e.target;
//checking clicked element is button or not
if (clickedElement.tagName === 'SPAN'){
const artist = clickedElement.getAttribute('data-artist');
const songTitle = clickedElement.getAttribute('data-songtitle');
getLyrics(artist, songTitle)
}
})
//listening for a submit event
form.addEventListener("submit", e => {
e.preventDefault();
searchValue = search.value.trim();
if (!searchValue) {
alert("Nothing to search");
} else {
startSearch(searchValue);
}
})
结语
在本教程中,我们学习了如何使用HTML5、CSS3、Vanilla JavaScript、OVH API以及ES6功能构建一个歌词搜索应用。
因此,你可以利用这些知识来制作其他高质量和有成效的应用程序。