preface

Some time ago, my partner has introduced the music playing function of netease Cloud music mini program in detail. As a front-end white person, I have learned for a period of time, and recently I have been busy, so I didn’t write the real-time search content in time to share with you (in fact, the code and function have been written almost before). So today I will tell you about some details and optimization of individuals in it.

Search function is very common, a lot of places can be used, I hope to share with you useful things, at the same time, there are insufficient places, also hope you big guy pointed out, give some modification of the opinion, small white here thank you!

Real-time search capabilities, we also need to use the API interface inside from the input box to enter a value to search Suggestions, and then to search results, finally to jump the songs, is no longer so simple, the value is the key, at the same time of different container box under the different function to hide and display, there are also some search in detail and optimized. Let’s take a look!

Interface to preview

Interface analysis

In the head search bar: return arrow on the left, input box in the middle, jump to the singer list page on the right; The clear button is hidden and only appears after the input value is entered.

As you go down the history, like the value of each search, you have a little bit of an equidistant distribution of the value of each search, and that little bit is as big as the value of the search, and I’m using display: flex; flex-wrap: wrap; If you are interested in this interface style, you can take a look at the entire code later.

Next is the hot search list, here there is no too much attention, is to initiate the interface request data, data buried in the display on the line.

Search suggestions will appear only after the input is complete, and will cover the entire page in a solid block. Use box-shadow: 1px, 1px, 5px #888888 for a solid block, and z-index for an overlay effect.

Search results will appear when you click on one of the search suggestions or click on the search history or hot search. At the same time, all the other containers on the interface will be hidden soon. In fact, this is a small detail of the container box hiding and appearing, which will be discussed in detail in the function. Let’s talk about how components (containers) can be hidden and displayed so that they don’t get obscured in the following functions

The heads of several containers are shown

<! <image class="{{showClean? 'header_view_hide' : 'clean-pic'}}" src=".. /.. /image/search_delete.png" bindtap="clearInput" />Copy the code
<! <view class="{{showSongResult? 'search_suggest' : 'header_view_hide'}}">Copy the code
<! <view class="{{showSearchResult? 'header_view_hide' : 'search_result_songs'}}">Copy the code
<! <view class="{{showView? 'option':'header_view_hide'}}">Copy the code
<! <view class="{{showView? 'option':'header_view_hide'}}">Copy the code

Resolution: I only put the contents of the heads of these containers, In data in the data source to put showClean respectively, showSongResult, showSearchResult, showView, is true is that a few containers by default: (colon) in front of the style, to false by default: (colon) at the back of the style; Header_view_hide style set to display: None; , that is, hide not show; So when in a certain way can go to change showClean showSongResult, showSearchResult, showView to true or false can make this a few container respectively to show or hide.

Interface encapsulation

Interface encapsulation in the last article has been very clear to my friend, we do not need to explain more here, also now used function is not only optical modulation interface request data is so simple, we need to pass the value to the interface, let the interface after receiving the value to return the corresponding data to us; In the search interface, we use the interface of search suggestions and search results. We only use the basic wx.request to get data directly for the time being

api.js

Const API = {getSearchSuggest: (data) => Request (GET, '/search/suggest', data), // (data) => request(GET, '/search', data), // search result interface}Copy the code

Real-time search function:

1. Data source analysis

A search function we designed to have a lot of data, can be itemized: inputValue inputValue, at the time of input; Hot search list data HOTS, hot search interface to obtain; The search keyword searchKey, which itself is the value of the input box, is passed to the search suggestion as the search keyword; SearchSuggest, the data returned by the search suggestion interface after retrieving the search term (search suggestions); SearchResult. When you click a search suggestion, the value will be filled into the search box, and the keyword searchKey will be changed to this value, which will be passed to the searchResult interface and return data into the searchResult. Finally, search history, and each time you do a search, place the value of the original input field into the history data source. Other data sources involve component hiding and presentation, that is, under what circumstances the container boxes of each piece are hidden and under what circumstances they are displayed.

Data Source presentation

Data: {inputValue: null,// input box inputValue history: [], // search history store array searchSuggest: [], // search suggestion showView: ShowSongResult: true, searchResult: [],// searchKey: [], showSearchResult: true, showClean: True, hots: [] //Copy the code

2. Get top searches

Here we call the interface directly in the initial data of the page, and get the data directly to use

onLoad: function (options) {
    wx.request({
      url: 'http://neteasecloudmusicapi.zhaoboy.com/search/hot/detail',
      header: { "Content-Type": "application/json" },
      success: (res) => {  // console.log(res)
        this.setData({
          hots: res.data.result.hots })
      }
    })
  },
Copy the code

3. Obtain the input text

As mentioned above, there is no direct way to obtain the interface for searching suggestions and results, which requires us to pass the value, so first we need to obtain the value of the input box

Input box content analysis

<input focus='true' type="text" class=" wei-search-bar__input "placeholder=" placeholder" style="color:#eaeaea" value='{{inputValue}}' bindinput="getSearchKey" bindblur="routeSearchResPage" bindconfirm="searchOver" />Copy the code

Small program about the input box related properties you can go to the details; Placeholder for the input box is empty time placeholder, that is, before input box display content, placeholder style can be set to the placeholder style; Value is the initial content of the input box, that is, the input content in the input box. Here, we directly take the input content value as the content of inputValue in the data source. Bindinput is triggered on keyboard input, meaning that as soon as we type, our custom event getSearchKey is triggered and the corresponding data is returned. Bindblur is triggered when the input box loses focus. To perform the search function, you need to enter a value in the search box, and the focus is always on the input box. When you click outside the input box, the input box loses focus, and the routeSearchResPage event is triggered, and corresponding data is returned, as described in the following functions. Bindconfirm, which is triggered when the Finish button is hit, binds a searchOver to hide the component (container block) and triggers the search function again, as described in the following functions.

Get input text

GetSearchKey: function (e) {// console.log(e.createail) // Prints the values of the input box if (e.createail. Cursor! This. setData({showSongResult: true, searchKey: searchKey); e.detail.value }) this.searchSuggest(); } if (e.daile.value) {// Display the clear button 'x' this.setData({showClean: })} if(e.dail. cursor === 0){this.setData({// If there is no value in the input box, hide the search suggestion interface and return to the original state. false }) return } }Copy the code

bindinputIt will return the data itself, so while the code is running, you can print it out and look at it; e.detail.valueIs the value of the input field and assigns it tosearchKey; Viewing printed Datae:

Resolution:

Confused friends can run the code and print out several data of the above design for analysis

If the value of the input box is the same as the value of the input box returned by bindinput, the value of the input box is assigned to the searchKey, and the search suggestion bar is displayed. You can see details in WXML for the entire interface in the last post); The searchSuggest event (method) takes effect at the same time.

② When the input box has no value, the clear button X will not be displayed, only when the input box has a value, the clear button X will appear

(3) When the input box has no value, hide the search suggestion bar, in fact, when we first enter this page, the input box is no value, the search suggestion bar is not displayed, there is no data for no input; However, when we input content, search suggestions appear, at this time, we click the clear button, the input box content is gone, but the search suggestions remain in the previous state, so we optimize here, make showSongResult false, that is, empty the input box content, hide the search suggestions bar. And why should we return? There is also a bug here. When you clear the contents of the input box, you find that the search function is no longer available, so you need to return to the initial state to re-enter and search. At the same time, when the input field is empty, the search function will also report an error, which is also a bug, so with return, even if the null value search will immediately return to the initial state, which solves the null value search error bug.

4. Other functions of the search box

  • Clear the contents of the input box
ClearInput: function (e) {// console.log(e) this.setData({inputValue: "", // Set the input box to null showSongResult: False, // Hide the search suggestion bar showClean: true // hide the clear button (if this item is not added, the clear button does not disappear after the clear input box)})},Copy the code

Click the clear button to leave the inputValue value empty, that is, the content of the input box is empty to achieve the effect of clearing the text; We also mentioned the clear button when we get the input field text, and we also mentioned that when the input field text is empty, the previous search suggestions bar will remain, so here we set showSongResult to false to hide the search suggestions bar. Clear the text and hide the clear button.

  • Cancel the search and return to the previous page
NavigateBack: function () {wx: wx.navigateBack({wx: wx.navigateBack: function () {wx: wx.navigateBack({wx: wx.navigateBack: function () {wx: wx.navigateBack({wx: wx.navigateBack: function () {wx: wx.navigateBack({wx: wx.navigateBack: function () {wx: wx. }Copy the code

The applet used here has a built-in return page function that returns to the previous page when a delta value of 0 is given. (See documentation for details)

  • Jump singer chart
SingerPage: function () {wx.navigateTo({// keep the current page, jump to a page in the app. But you can't skip to tabbar page URL: '.. /singer/singer '// the interface to jump to})},Copy the code

NavigateTo navigateTo navigateTo navigateTo navigateTo navigateTo navigateTo

5. Search for suggestions

searchSuggest() { $api. getSearchSuggest({ keywords: this.data.searchKey, type: 'mobile'}). Then (res = > {/ / request/success/console log (res); If (res.statusCode === 200){this.setData({searchSuggest: Res.data.result. allMatch // Pass the name of the song in the returned data to the search suggestion})}}). Catch (err => {// failed console.log(' error ')})}Copy the code

In the last article about playback, my friend has talked about interface and encapsulation very carefully. Here we will not talk about this, we will analyze our interface. The searchKey is passed to the interface as a search keyword. In the previous getSearchKey method, we passed the contents of the input box to the searchKey as its value. So we take the searchKey and pass it to the interface. The interface returns the relevant data. Res.data.result. allMatch is the name of all the songs in the search suggestion returned from the search keyword. This will fetch the data in the WXML buried space and display the search suggestions bar.

6. Search results

  • Search suggestions within the song click event
<view wx:for="{{searchSuggest}}" wx:key="index" class='search_result' data-value='{{item.keyword}} 'bindtap='fill_value'> // js: Function (e) {// Click search suggestion, popular search value or search history, Fill in the search box. / / the console log (value) urrentTarget of e.c. with our fabrication:. The dataset. / / print data in a ` e ` - > click on the value of the enclosing setData ({searchKey: E.c. with our fabrication: urrentTarget. Dataset. Value, / / click the value to search inputValue searchKey: E.c. with our fabrication: urrentTarget. Dataset. Value, / / display content in the input box showSongResult: false, / / gave false values, hidden showClean search Suggestions page: False // Show clear button}) this.searchResult(); // execute the search function},Copy the code

The first click of the event carries additional information, such as ID, dataset, touches. Returns the parameterevent.eventThere’s going to be onecurrentTargetProperties; Here’s an explanationdata-value='{{item.keyword}}= >dataisdataset;item.keywordIs assigned to the data returned after the search suggestion is completedsearchSuggestSome data in it; When a click on the search suggestion inside a song name, the song name is at this timeitem.keywordAnd saves the value to the click event parametereventWithin thedataset. You can also print a wave to see the results,currentTarget.dataset.valueThat’s the name of the song we clicked on. So when you click on a song in the search suggestion or a song in the search history or hot list, the click event takes effect and returns the song name and gives the value to the current songsearchKeyandinputValue, the value of the input box will become the value, and the keyword value of the search result will also become the value; At the same timethis.searchResult()Enables the search results function to be executed at this point.showSongResult: falseThe search suggestions bar is also hidden. increaseshowClean: falseIs to solve the click after the input box has a value but does not show the clear buttonbug.Viewing printed Datae:

  • Return search results
SearchResult: function () {// console.log(this.data.searchkey) // Print the search keyword $api.getSearchResult({keywords: this.data.searchKey, type: 1, limit: 100, offset: If (res.statusCode === 200) {// console.log(res) // prints the returned data this.setData({searchResult: ShowSearchResult: false, showView: false, // Hide the search history bar and the hot list bar}); }}. Catch (REE => {// request failed})},Copy the code

Resolution: Clicking on the name of the song above triggers the function of search results at the same time, passing the new keywords after clicking to the interface of search results. After the interface requests, it returns us the data. Res.data.result. songs in the data is the searched song. It is then assigned to the searchResult so that the searchResult bar gets the data, and showSearchResult: false renders the searchResult bar; Here also made a search history bar and hot search bar the hidden function of note: search results and search Suggestions need pass search keywords to interface, don’t know the friend can go to see the interface of document study: https://binaryify.github.io/NeteaseCloudMusicApi/#/

  • Optimization after the search is complete
SearchOver: function () {this.setData({showSongResult: }) this.searchResult(); // execute search result},Copy the code

The searchOver is a BindConfirm event bound to the input box, which is triggered when the Finish button is clicked. When we search is completed, interface and the search bar and search results show that at the moment we click on the input box again, can make clear text, at the same time we also need to add a function, namely, in such a case, we’ll be able to input and return to the search Suggestions, and click search again suggest the songs in again to perform the function of search results.

7. Search for history

  • Input loses focus
routeSearchResPage: Function (e) {/ / console log (this) data) searchKey) / / print search keywords at this time. / / the console log (this) data. SearchKey. Length) of the if (this data. The searchKey. Length > 0) {/ / when the search box has a value of value for the search to history, Avoid empty values in historical records let history = wx. GetStorageSync (" history ") | | []; // synchronize the contents of the specified key from the local cache. The key is history // console.log(history); history = history.filter(item => item ! Unshift (this.data.searchkey) // Sort into wx.setStoragesync ("history", history); }}Copy the code

The routeSearchResPage event is placed in the input box, fired when the input box loses focus, i.e. when input is not performed in the input box, or when something outside the input box is clicked. When the input is complete, the search suggestion will appear and the focus is still in the input box. When we click on a day in the search suggestion, the input box will lose focus and this event will be triggered. The loss of focus function occurs after the search suggestion event, and the search keyword at this time is the search keyword of the search suggestion. As mentioned above, this search keyword is the text content we enter in the input box, so the search keyword at this time is assigned to the search history. Note: * * * * about the search history, we added a judgment here, namely when the search keywords is not null, will get search keywords to search history, otherwise, each input value or to click on the input box, a null value will be passed on to the search history, led to the search history will be free to show, this is also a ` ` bugs have to solve. At the same time, the code is further optimized by using filter to achieve the effect of historical de-retrieval, that is, to judge whether the new search keyword is the same as the search keyword in the existing search history, then filter out the previous one, and use unshift ‘to add this to the beginning of the array as a new history record.

  • History cache

    OnShow: function () {// Fetch the cache every time the display changes, give history, and for out. // console.log('a') this.setData({ history: wx.getStorageSync("history") || [] }) }Copy the code

    The previous step saved the search record to the search history, but it is not displayed to the data source to retrieve the data, there is a history cache operation. OnShow is displayed on the listening page. It is triggered every time when the search result bar appears after clicking the song name after the search suggestion function. At this time, the history obtained in the previous step is cached locally with getStorageSync, so that the search history will not be lost when refreshing or jumping.

  • Delete history

ClearHistory: function () {// Clear the page object data's history array and reset the cache to [] (empty) const that = this; Wx. showModal({content: 'confirm to empty all history ', cancelColor: '#DE655C', confirmColor: '#DE655C', success(res) {if (res.confirm) { []}) wx.setStoragesync ("history", [])} else if (res.cancel) {}})}Copy the code

The showModal() method is used to display a dialog window, which is triggered when the delete button is clicked, and displays a window confirming to clear all history, with two click buttons: Confirm and cancel; When clicking OK, the contents of the history array will be reset to empty, that is, to achieve the function of clearing the data in the search history; You also need to cache the search history that has no data at this point. Click Cancel, the prompt window disappears, and the interface will not change.

8. Jump and play songs

  • Value transfer resets the playing interface
// <view wx:key="index" class='search_result_song_item' Data-id ="{{item.id}}" bindtap='handlePlayAudio'> Function (e) {function (e) {function (e) {function (e) {function (e) {function (e) { CurrentTarget property. / / the console log (e) / / print out the content of the return parameter const musicId = e.c. with our fabrication: urrentTarget. Dataset. Id; NavigateTo ({// Go to the play page with the full URL: '.. /play/play? ${musicId} =${musicId} '// Jump to the interface of the music that has been completed})}Copy the code

Resolution:handlePlayAudioBind to each search result, that is, click the search suggestion to complete the search result function to display the search result bar, click the search result of each day can triggerhandlePlayAudio. We talked about that beforebindtapIs returned with parameters, carrying additional informationdataset.eventThere’s going to be onecurrentTargetProperties,data-id="{{item.id}}"The function of the followingSearch suggestions within the song click eventIt has the same effect,item.idReturns to the interface for executing search resultssearchResultFor each song in the search resultsid. When you click on a song in the search results, click on the songidTo pass toeventIn thedataset, data namedatasetIn theid. Now let’s define onemusicIdThat will beeventThe songs in itidAssigned tomusicIdwith wx.navigateToJump to the play screen, while themusicIdIncoming data as required by the playback request interface.Viewing printed Datae:

9. Search function source code sharing

wxml

<nav-bar></nav-bar> <view class="wrapper"> <! <view class=" wei-search-bar "> <! <view class=" wei-search-bar__cancel-btn "bindtap="back"> <image class="return-pic" SRC =".. /.. /image/search_return.png" bindtap="cancel" /> </view> <! <view class="weui-search-bar__form"> <view class="weui-search-bar__box"> <input focus='true' type="text" Class ="weui-search-bar__input" placeholder=" placeholder-style="color:#eaeaea" value='{{inputValue}}' bindinput="getSearchKey" bindblur="routeSearchResPage" bindconfirm="searchOver" /> </view> <! <view class="clean-bar"> <image class="{{showClean? 'header_view_hide' : 'clean-pic'}}" src=".. /.. /image/search_delete.png" bindtap="clearInput" /> </view> </view> <! <view class="songer"> <image class="songer-pic" SRC =".. /.. /image/search_songner.png" bindtap="singerPage" /> </view> </view> <! <view class="{{showSongResult? 'search_suggest' : 'header_view_hide'}}"> <view wx:for="{{searchSuggest}}" wx:key="index" class='search_result' data-value='{{item.keyword}} ' bindtap='fill_value'> <image class="search-pic" src=".. /.. /image/search_search.png"></image> <view class="search_suggest_name">{{item.keyword}}</view> </view> </view> <! <view class="{{showSearchResult? 'header_view_hide' : 'search_result_songs'}}"> <view class="search-title"> <text class="songTitle"> </text> <view class="openBox"> <image class="openTap" src=".. /.. PNG "/> <text class="openDes"> </text> </view> </view> <view wx:for="{{searchResult}}" wx:key="index" class='search_result_song_item' data-id="{{item.id}}" bindtap='handlePlayAudio'> <view class='search_result_song_song_name'>{{item.name}}</view> <view class='search_result_song_song_art-album'> {{item.artists[0].name}} - {{item.album.name}} </view> <image class="broadcast" src=".. /.. /image/search_nav-open.png" /> <image class="navigation" src=".. /.. /image/mine_lan.png" /> </view> </view> <! <view class="{{showView? 'option':'header_view_hide'}}"> <view class="history"> <view class="history-wrapper"> <text Class ="history-name"> history </text> <image bindtap="clearHistory" class="history-delete" SRC =".. /.. /image/search_del.png" /> </view> <view class="allhistory"> <view class="allhistorybox" wx:for="{{history}}" wx:key="index" data-value='{{item}}' data-index="{{index}}" bindtap="fill_value"> <text class="historyname">{{item}}</text> </view> </view> </view> </view> <! <view class="{{showView? 'option':'header_view_hide'}}"> <view class="ranking"> <text class="ranking-name"> </text> </view> <view class="rankingList"> <view class="rankingList-box" wx:for="{{hots}}" wx:key="index"> <view wx:if="{{index <= 2}}"> <text  class="rankingList-num" style="color:red">{{index+1}}</text> <view class="song"> <text class="rankigList-songname" style="color:black; font-weight:600" data-value="{{item.first}}" bindtap='fill_value'> {{item.first}} </text> <block wx:for="{{detail}}" wx:key="index"> <text class="rankigList-hotsong" style="color:red">{{item.hot}}</text> </block> </view> </view> <view wx:if="{{index > 2}}"> <text class="rankingList-num">{{index+1}}</text> <view class="othersong"> <text class="rankigList-songname" data-value="{{item.first}}" bindtap='fill_value'> {{item.first}} </text> </view> </view> </view> </view> </view> </view>Copy the code

wxss

  /* pages/search/search.wxss */
.weui-search-bar{
    position:relative;
    /* padding:8px; */
    display:flex;
    box-sizing:border-box;
    /* background-color:#EDEDED; */
    -webkit-text-size-adjust:100%;
    align-items:center
}
.weui-icon-search{
    margin-right:8px;font-size:14px;vertical-align:top;margin-top:.64em;
    height:1em;line-height:1em
}
.weui-icon-search_in-box{
    position:absolute;left:12px;top:50%;margin-top:-8px
}
.weui-search-bar__text{
    display:inline-block;font-size:14px;vertical-align:top
}
.weui-search-bar__form{
    position:relative;
    /* flex:auto;
    border-radius:4px;
    background:#FFFFFF */
    border-bottom: 1px solid #000;
    margin-left: 30rpx;
    width: 400rpx;
    padding-right: 80rpx;
}
.weui-search-bar__box{
    position:relative;
    padding-right: 80rpx;
    box-sizing:border-box;
    z-index:1;
}
.weui-search-bar__input{
    height:32px;line-height:32px;font-size:14px;caret-color:#07C160
}
.weui-icon-clear{
    position:absolute;top:0;right:0;bottom:0;padding:0 12px;font-size:0
}
.weui-icon-clear:after{
    content:"";height:100%;vertical-align:middle;display:inline-block;width:0;overflow:hidden
}
.weui-search-bar__label{
    position:absolute;top:0;right:0;bottom:0;left:0;z-index:2;border-radius:4px;
    text-align:center;color:rgba(0,0,0,0.5);background:#FFFFFF;line-height:32px
}
.weui-search-bar__cancel-btn{
    margin-left:8px;line-height:32px;color:#576B95;white-space:nowrap
}
.clean-bar {
    /* width: 20rpx;
    height: 20rpx; */
}
.clean-pic {
    width: 20rpx;
    height: 20rpx;
    float: right;
    position: absolute;
     margin-top: -30rpx; 
     margin-left: 450rpx;
}
.return-pic {
    width: 60rpx;
    height: 60rpx;
    margin-left: 20rpx;
}
.songer-pic{
    width: 60rpx;
    height: 60rpx;
    margin-left: 40rpx;
}
.wrapper {
    width: 100%;
    height: 100%;
    position: relative;
    z-index: 1;
}
.poster {
    width: 670rpx;
    height: 100rpx;
    margin-top: 40rpx;
    margin-left: 40rpx;
}
.postername {
    font-size: 15rpx;
    position: absolute;
    margin-top: 10rpx;
    margin-left: 10rpx;
}
.poster-outside {
    border-radius: 10rpx;
    background-color: slategrey;
}
.poster-pic0 {
    width: 80rpx;
    height: 80rpx;
    margin-top: 10rpx;
}
.test-title {
    position: absolute;
    font-size: 30rpx;
    line-height: 100rpx;
    margin-left: 20rpx;
    color: red;
}
.test-age {
    position: absolute;
    font-size: 30rpx;
    line-height: 100rpx;
    margin-left: 80rpx;
}
.test-red {
    position: absolute;
    font-size: 30rpx;
    line-height: 100rpx;
    margin-left: 270rpx;
    color: red;
}
.test-black {
    position: absolute;
    font-size: 30rpx;
    line-height: 100rpx;
    margin-left: 400rpx;
}
.poster-pic1 {
    width: 80rpx;
    height: 80rpx;
    margin-left: 510rpx;
}
.history {
    margin: 50rpx 0 0 40rpx;
}
.history-name {
    font-size: 28rpx;
    font-weight: 550;
}
.history-delete {
    width: 50rpx;
    height: 50rpx;
    position: absolute;
    margin-left: 510rpx;
}
.allhistory {
    display: flex;
    flex-wrap: wrap;
}
.allhistorybox {
    margin: 30rpx 20rpx 0 0;
    background-color: dimgray;
    border-radius: 10rpx;
}
.historyname {
    font-size: 28rpx;
    margin: 20rpx 20rpx 20rpx 20rpx;
}
.ranking {
    margin-left: 40rpx;
    margin-top: 100rpx;
}
.ranking-name {
    font-size: 28rpx;
    color: black;
    font-weight: 550;
}
.rankingList {
    margin-left: 50rpx;
    margin-top: 30rpx;
}
.rankingList-box {
    width: 100%;
    height: 80rpx;
    margin: 0 0 30rpx 0;
}
.rankingList-num {
    line-height: 80rpx;
    align-content: center;
}
.song {
    margin: -100rpx 0 0 30rpx;
    display: flex;
    flex-wrap: wrap;
}
.othersong {
    margin-top: -100rpx;
    margin-left: 70rpx;
}
.rankigList-songname {
    font-size: 30rpx;
    margin-left: 40rpx;
}
.rankigList-hotsong {
    font-size: 25rpx;
    font-weight: 550;
    margin-top: 45rpx;
    margin-left: 20rpx;
}
.rankigList-hotnum {
    float: right;
    position: absolute;
    line-height: 80rpx;
    margin-left: 600rpx;
    font-size: 20rpx;
    color: darkgrey;
}
.rankingList-songdes {
    font-size: 22rpx;
    color: darkgrey;
    position: absolute;
    margin-left: 60rpx;
    margin-top: -30rpx;
}
.search_suggest{
    width:570rpx;
    margin-left: 40rpx;
    position: absolute;
    z-index: 2;
    background: #fff;
    box-shadow: 1px 1px 5px #888888;
    margin-top: 20rpx;
}
.header_view_hide{
    display: none;
  }
.search-pic {
      width: 50rpx;
      height: 50rpx;
     margin-top: 25rpx;
     margin-left: 20rpx;
}
.search-title {
    color: #000;
    margin-left: 15rpx;
    margin-bottom: 30rpx;
}
.songTitle {
    font-size: 30rpx;
    font-weight: 700;
}
.openBox {
    float: right;
    border-radius: 30rpx;
    margin-right: 30rpx;
    border-radius: 30rpx;
    border-bottom: 1px solid #eaeaea;
}
.openTap {
    width: 30rpx;
    height: 30rpx;
    position: absolute;
    margin: 6rpx 10rpx 0rpx 20rpx;
}
.openDes {
    font-size: 25rpx;
    color: rgba(0,0,0,0.5);
    margin-right: 20rpx;
    margin-left: 58rpx;
}
.broadcast {
    width: 20px;
    height: 20px;
    display: inline-block;
    overflow: hidden;
    float: right;
    margin-top: -70rpx;
    margin-left: -120rpx;
    margin-right: 80rpx;
}
.navigation {
    width: 20px;
    height: 20px;
    display: inline-block;
    overflow: hidden;
    float: right;
    margin-top: -70rpx;
    margin-right: 20rpx;
}
  .search_result{
    /* display: block;
    font-size: 14px;
    color: #000000;
    padding: 15rpx;
    margin: 15rpx; */
    /* border-bottom: 1px solid #eaeaea; */
    /* float: right; */
    /* margin-left: -450rpx; */
    width: 570rpx;    
    height: 100rpx;
    border-bottom: 1px solid #eaeaea;
  }
  .search_suggest_name {
    display: block;
    float: right;
    position: absolute;
    margin-left: 85rpx;
    margin-top: -46rpx;
    font-size: 14px;
    color: darkgrey;
    /* padding: 15rpx;
    margin: 15rpx; */
  }
  .search_result_songs{
    margin-top: 10rpx;
    width: 100%;
    height: 100%;
    margin-left: 15rpx;
  }
  .search_result_song_item{
     display: block;
     margin: 15rpx;
     border-bottom: 1px solid #EDEEF0;
  }
  .search_result_song_song_name{
    font-size: 15px;
    color: #000000;
    margin-bottom: 15rpx;
  }
  .search_result_song_song_art-album{
    font-size: 11px;
    color: #000000;
    font-weight:lighter;
    margin-bottom: 5rpx;
  }
Copy the code

js

// pages/search/search.js // const API = require('.. /.. /utils/req') const $api = require('.. /.. /utils/api.js').API; const app = getApp(); Page({data: {inputValue: null,// input box inputValue history: [], // searchSuggest: [], // search suggestion showView: ShowSongResult: true, searchResult: [],// searchKey: [], showSearchResult: true, showClean: }, onLoad: function (options) {wx.request({url: 'http://neteasecloudmusicapi.zhaoboy.com/search/hot/detail', data: { }, header: { "Content-Type": "application/json" }, success: (res) => { // console.log(res) this.setData({ hots: Function (e) {// console.log(e) this.setData({inputValue: // console.log(e) this.setData({inputValue: ", showSongResult: false, showClean: true})} back: function () {wx: wx.navigateBack({ delta: 0 }); Function () {// console.log('a') wx.navigateTo({url: '.. /singer/singer '})}, // Get input text and real-time search getSearchKey: function (e) { if(e.detail.cursor === 0){ this.setData({ showSongResult: False}) return} // console.log(e.createail) // Prints the values of the input box if (e.createail. Cursor! This. setData({showSongResult: true, searchKey: searchKey); e.detail.value }) this.searchSuggest(); } if (e.daile.value) {// Display the clear button 'x' this.setData({showClean: SearchSuggest() {$api.getSearchSuggest () {keywords: this.data.searchKey, type: 'mobile'}). Then (res = > {/ / request/success/console log (res); if(res.statusCode === 200){ this.setData({ searchSuggest: Res.data.result.allmatch})}}). Catch (err => {// failed console.log(' error ')})}, // searchResult searchResult: function () { // console.log(this.data.searchKey) $api.getSearchResult({ keywords: this.data.searchKey, type: 1, limit: If (res.statusCode === 200) {// console.log(res) this.setData({searchResult: res.data.result.songs, showSearchResult: false, showView: false, }); }}). Catch (REE => {// request failed})}, handlePlayAudio: Function (e) {function (e) {function (e) {function (e) {function (e) {function (e) { CurrentTarget property. / / the console log (e) const musicId = e.c. with our fabrication: urrentTarget. Dataset. Id; NavigateTo ({// Go to the play page with the full URL: '.. /play/play? MusicId =${musicId} '})}, // Input lose focus function routeSearchResPage: function (e) { // console.log(e) // console.log(e.detail.value) // console.log(this.data.searchKey) // The console. The log (enclosing data. SearchKey. Length) if (this. Data. SearchKey. Length > 0) {/ / when the search box has a value of value for the search to history, Avoid empty values in historical records let history = wx. GetStorageSync (" history ") | | []; // console.log(history); history = history.filter(item => item ! Unshift (this.data.searchKey) wx.setStorageSync("history", history); }}, // Clear the page object data's history array to reset the cache to [] (empty) clearHistory: function () {const that = this; Wx. showModal({content: 'confirm to empty all history ', cancelColor: '#DE655C', confirmColor: '#DE655C', success(res) { if (res.confirm) { that.setData({ history: []}) wx.setStoragesync ("history", []) else if (res.cancel) {}})}, SearchOver: function () {this.searchSuggest(); searchOver: function () {this.searchsuggest (); // execute the searchResult this.searchresult ()}, // click on the popular search value or search history, and fill in the search box fill_value: function (e) { console.log(e) // console.log(this.data.history) // console.log(e.currentTarget.dataset.value) Enclosing setData ({searchKey: urrentTarget of e.c. with our fabrication:. The dataset. Value, / / click = give searchKey value, let he go to search inputValue: E.c. with our fabrication: urrentTarget. Dataset. Value, / / display content in the input box showSongResult: false, / / gave false values, hidden showClean search Suggestions page: False // Show clear button}) this.searchResult(); // Perform the search function}, /** * lifecycle function -- listen to the page display */ / every time the display changes to fetch the cache, give history, and for out. onShow: function () { // console.log('a') this.setData({ history: wx.getStorageSync("history") || [] }) }, })Copy the code

api.js

const app = getApp(); // Method (HTTP request method), netease cloud API provides get and POST request const get = 'get '; const POST = 'POST'; / / baseUrl define global constants used to store the prefix const baseUrl = 'http://neteasecloudmusicapi.zhaoboy.com'; function request(method, url, data) { return new Promise(function (resolve, reject) { let header = { 'content-type': 'application/json', 'cookie': app.globalData.login_token }; wx.request({ url: baseURL + url, method: method, data: method === POST ? JSON.stringify(data) : data, header: Header, success(res) {if (res.data.code == 200) {resolve(res); } else {// Other exceptions reject(' runtime error, please try again later '); }, fail(err) {// reject(err)}})})} const API = {getSearchSuggest: (data) => request(GET, '/search/suggest', data), // (data) => request(GET, '/search', data), // search result interface}; module.exports = { API: API }Copy the code

conclusion

In fact, bit by bit clear will find it is not difficult to operate, first of all, the idea should be clear, know what each function is, at the same time in the debugging is the time to find some bugs, and then to optimize the code. Search this function is widely used, I hope this share can give you a little use. Please point out any other optimization suggestions or errors. Thank you for watching. Give me a thumbs up, crab!