如何使用OVH API的Vanilla JavaScript构建一个歌词搜索应用程序

312 阅读6分钟

使用OVH API的Vanilla JavaScript构建一个歌词搜索应用程序

不知道歌曲的歌词是大多数爱唱歌的人遇到的问题。在这篇文章中,我们将创建一个平台,用户可以通过输入艺术家的名字或歌名来搜索歌词。

我们将使用HTML5、CSS3、Vanilla JavaScript、带有*fetch()方法的async-await、OVH APIECMAScript 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 ,并分别包含其他两个h1h2 标签。

h1 标签的内容是Learn your favorite song ,而h2 标签将包含song lyrics

在带有类containerdiv 内,你将创建一个div 和一个idlyrics-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;
}

现在我们已经通过添加颜色、字体大小、字体家族、填充和边距成功地设计了网页。

下面是你的网页应该是什么样子的。

Screenshot for design

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开发工具中的控制台)。

你的屏幕应该像下面的屏幕截图一样。

Screenshot for consoled data

在上面的截图中,我搜索了一首标题为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-artistgetLyrics() 函数将这两个变量作为参数。

注意,参数是当函数被调用时传递给它的实际值,而参数是当函数被定义时传递的值。

GetLyrics() - 异步函数

这是最重要的函数,因为它允许我们显示歌曲的歌词。

该函数接收了两个参数,分别是artistsongTitle 。回顾一下,你可以通过输入艺术家的名字或歌曲标题来搜索歌词。

下面是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功能构建一个歌词搜索应用。

因此,你可以利用这些知识来制作其他高质量和有成效的应用程序。