zoukankan      html  css  js  c++  java
  • 仿网易云音乐-搜索歌曲功能

    思路:
    1.搜索静态页面,展示热门搜索关键词:点击关键词,自动填入搜索框,并实时得到搜索结果。

     小细节:如果搜索框里有内容,则会出现“X”清除搜索内容,并回到默认页面。
    2.手动输入搜索关键词,会给相似推荐的关键词,点击关键词进行搜索相关歌曲

    API接口使用: https://binaryify.github.io/NeteaseCloudMusicApi/#/?id=neteasecloudmusicapi

    视图层:搜索框和热门搜索词列表

     1 <view class="m-input">
     2         <i class="u-svg u-svg-srch">
     3           <image src="/images/s.svg"></image>
     4           </i>
     5         <input class="inputcover" id="input" 
     6         bindinput="bindKeyInput" bindconfirm="getsearchList"
     7         confirm-type="search" 
     8         placeholder="搜索歌曲、歌手、专辑"
     9         value="{{searchValue}}"
    10         />
    11         <i class="close u-svg u-svg-empty {{showClean ? 'header_view_hide' : 'clean-pic'}}" bindtap='clearInput'>
    12           <image src="/images/close.svg"></image>
    13           </i>
    14       </view>
    15 
    16 <view class="m-default  {{showView?'option':'header_view_hide'}}">
    17         <view class="m-hotlist">
    18           <h3 class="title">热门搜索</h3>
    19           <view class="list">
    20           <view class="item f-bd f-bd-full" 
    21           wx:for="{{hotLists}}" 
    22           wx:key="index" 
    23           data-value='{{item.first}}'
    24           bindtap='fill_value'>
    25             {{item.first}}
    26           </view>    
    27           </view>
    28         </view>
    29       </view>

    A. 用到的方法:

    bindinput="bindKeyInput": 输入搜索关键词,实时输出相关搜索词

    bindconfirm="getsearchList":输入完成,enter得到歌曲搜索列表

    bindtap='clearInput':点击“x”清空搜索框里的内容,并清除搜索结果回到默认状态

    B. 所用到的状态控制显示与隐藏

     <i class="close u-svg u-svg-empty {{showClean ? 'header_view_hide' : 'clean-pic'}}" bindtap='clearInput'>

     <view class="m-default {{showView?'option':'header_view_hide'}}">

     showClean默认为ture,当前的class为'header_view_hide':display:none

     showView: true,显示当前模块 getSearchSuggest()方法设置showView为false,

    showSongResult: true,显示当前模块,showView为false,热门搜索隐藏

    <view class="m-recom {{showSongResult ? 'search_suggest' : 'header_view_hide'}}">
            <h3 class="title f-bd f-bd-btm f-thide">搜索“{{searchValue}}”</h3>
            <ul>
              <li class="recomitem" 
              wx:for="{{searchSuggest}}" 
              wx:key="index"
              data-value='{{item.keyword}}'
              bindtap='fill_value'
              >
              <i class="u-svg u-svg-search">
              <image src="/images/s.svg"></image>
              </i>
              <span class="f-bd f-bd-btm f-thide">{{item.keyword}}</span>
              </li>
            </ul>
          </view>
    data-value='{{item.keyword}}':设定当前点击的值,并传值给fill_value方法
    bindtap='fill_value':fill_value方法,获取当前的data-value的值e.currentTarget.dataset.value

    最重要的就是获取搜索列表:用到的方法:getSearchList(),getSearchList()

          <view class="m-searchresult {{showSearchResult ? 'search_result_songs':'header_view_hide'}}">
            <view class="m-matchlist">
              <h3 class="title">最佳匹配</h3>
                <ul>
                  <li class="matchitem artist">
                    <navigator url="/artist?id={{searchResult[0].id}}">
                      <div class="linkcover f-bd f-bd-btm">
                        <figure class="piccover">
                          <image class="pic" src="{{searchResult[0].al.picUrl}}"></image>
                        </figure>
                        <article class="describe">
                          <h4 class="maindes f-thide">
                            歌手: <p class="hcover">{{searchResult[0].ar[0].name}}</p>
                          </h4>
                        </article>
                        <i class="u-svg u-svg-arr">
                          <image src="/images/arrow.svg"></image>
                        </i>
                      </div>
                    </navigator>
                  </li>
                  <li class="matchitem album">
                    <navigator url="/album?id={{searchAlbum.id}}">
                      <div class="linkcover f-bd f-bd-btm">
                        <figure class="piccover">
                          <image class="pic" src="{{searchAlbum.picUrl}}"></image>
                        </figure>
                        <article class="describe">
                          <h4 class="maindes f-thide">
                          专辑: 
                          <p class="hcover">
                            <span>
                              <span class="highlight">{{searchAlbum.name}}</span>
                            </span>
                            <span>
                              <span class="normal">
                                {{searchAlbum.alias}}
                              </span>
                            </span>
                          </p>
                          </h4>
                          <p class="hcover addtional f-thide"> {{searchAlbum.artist.name}}</p>
                        </article>
                        <i class="u-svg u-svg-arr">
                          <image src="/images/arrow.svg"></image>
                        </i>
                      </div>
                    </navigator>
                  </li>
                </ul>
            </view>
            <view class="m-songlist">
              <view class="m-sglst">
              <block wx:for="{{searchResult}}" wx:key="index">
                <navigator 
                class="m-sgitem" 
                url="../musicplay/musicplay?id={{item.id}}&title={{item.name}}">
                    <view class="sgfr f-bd f-bd-btm">
                      <view class="sgchfl">
                        <view class="f-thide sgtl">
                            <p class="hcover">
                                <span>
                                    <span class="highlight">{{item.name}}</span>
                                </span>
                                <span>
                                </span>
                            </p>
                        </view>
                        <view class="f-thide sginfo">
                            <i class="u-hmsprt sghot"></i>
                            <p class="hcover">{{item.ar[0].name}}</p> - <p class="hcover">{{item.al.name}}</p>
                        </view>
                    </view>
                    <view class="sgchfr">
                      <span class="u-hmsprt sgchply">
                      </span>
                    </view>
                  </view>
              </navigator> 
              </block>
              </view>
            </view>
          </view>
    获取搜索音乐列表

    完整的代码:
    WXML:

    <view class="page-section">
          <view class="m-input">
            <i class="u-svg u-svg-srch">
              <image src="/images/s.svg"></image>
              </i>
            <input class="inputcover" id="input" 
            bindinput="bindKeyInput" bindconfirm="fill_value"
            confirm-type="search" 
            placeholder="搜索歌曲、歌手、专辑"
            value="{{searchValue}}"
            />
            <i class="close u-svg u-svg-empty {{showClean ? 'header_view_hide' : 'clean-pic'}}" bindtap='clearInput'>
              <image src="/images/close.svg"></image>
              </i>
          </view>
          <view class="m-recom {{showSongResult ? 'search_suggest' : 'header_view_hide'}}">
            <h3 class="title f-bd f-bd-btm f-thide">搜索“{{searchValue}}”</h3>
            <ul>
              <li class="recomitem" 
              wx:for="{{searchSuggest}}" 
              wx:key="index"
              data-value='{{item.keyword}}'
              bindtap='fill_value'
              >
              <i class="u-svg u-svg-search">
              <image src="/images/s.svg"></image>
              </i>
              <span class="f-bd f-bd-btm f-thide">{{item.keyword}}</span>
              </li>
            </ul>
          </view>
          <view class="m-searchresult {{showSearchResult ? 'search_result_songs':'header_view_hide'}}">
            <view class="m-matchlist" >
              <h3 class="title">最佳匹配</h3>
                <ul>
                  <li class="matchitem artist">
                    <navigator url="/artist?id={{searchResult[0].id}}">
                      <div class="linkcover f-bd f-bd-btm">
                        <figure class="piccover">
                          <image class="pic" src="{{searchResult[0].al.picUrl}}"></image>
                        </figure>
                        <article class="describe">
                          <h4 class="maindes f-thide">
                            歌手: <p class="hcover">{{searchResult[0].ar[0].name}}</p>
                          </h4>
                        </article>
                        <i class="u-svg u-svg-arr">
                          <image src="/images/arrow.svg"></image>
                        </i>
                      </div>
                    </navigator>
                  </li>
                  <li class="matchitem album">
                    <navigator url="/album?id={{searchAlbum.id}}">
                      <div class="linkcover f-bd f-bd-btm">
                        <figure class="piccover">
                          <image class="pic" src="{{searchAlbum.picUrl}}"></image>
                        </figure>
                        <article class="describe">
                          <h4 class="maindes f-thide">
                          专辑: 
                          <p class="hcover">
                            <span>
                              <span class="highlight">{{searchAlbum.name}}</span>
                            </span>
                            <span>
                              <span class="normal">
                                {{searchAlbum.alias}}
                              </span>
                            </span>
                          </p>
                          </h4>
                          <p class="hcover addtional f-thide"> {{searchAlbum.artist.name}}</p>
                        </article>
                        <i class="u-svg u-svg-arr">
                          <image src="/images/arrow.svg"></image>
                        </i>
                      </div>
                    </navigator>
                  </li>
                </ul>
            </view>
            <view class="m-songlist">
              <view class="m-sglst">
              <block wx:for="{{searchResult}}" wx:key="index">
                <navigator 
                class="m-sgitem" 
                url="../musicplay/musicplay?id={{item.id}}&title={{item.name}}">
                    <view class="sgfr f-bd f-bd-btm">
                      <view class="sgchfl">
                        <view class="f-thide sgtl">
                            <p class="hcover">
                                <span>
                                    <span class="highlight">{{item.name}}</span>
                                </span>
                                <span>
                                </span>
                            </p>
                        </view>
                        <view class="f-thide sginfo">
                            <i class="u-hmsprt sghot"></i>
                            <p class="hcover">{{item.ar[0].name}}</p> - <p class="hcover">{{item.al.name}}</p>
                        </view>
                    </view>
                    <view class="sgchfr">
                      <span class="u-hmsprt sgchply">
                      </span>
                    </view>
                  </view>
              </navigator> 
              </block>
              </view>
            </view>
          </view>
          <view class="m-default  {{showView?'option':'header_view_hide'}}">
            <view class="m-hotlist">
              <h3 class="title">热门搜索</h3>
              <view class="list">
              <view class="item f-bd f-bd-full" 
              wx:for="{{hotLists}}" 
              wx:key="index" 
              data-value='{{item.first}}'
              bindtap='fill_value'>
                {{item.first}}
              </view>    
              </view>
            </view>
          </view>
    </view>
    search.wxml
    // pages/search/search.js
    import {get} from "../../utils/request.js"
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        searchValue: '',
        cursor:0,
        hotLists:null,
        searchSuggest:null,
        searchResult:[],
        showView: true,
        showSearchResult:true,
        showSongResult: false,
        showSearchResult: false,
        showClean: true,
        offset:1
      },
      gethotList: async function(){
        const url =`/search/hot`
        const res = await get(url)
        // console.log(res.data.result.hots)
        this.setData({
          hotLists: res.data.result.hots
        })
      },
      getSearchSuggest:async function(searchWords){
        const url =`/search/suggest?keywords=${searchWords}&type=mobile`
        const res = await get(url)
        // console.log(res.data)
        this.setData({
          searchSuggest: res.data.result.allMatch,
          showView: false,
          showSearchResult: false
        })
      },
      // splitData: function (list) {
      //   var res = [];
      //   for (var i = 0, len = songCount; i < len; i += 10) {
      //     list.push(res.data.list[i]);
      //   }
      //   return res;
      // },
      getsearchList: async function(searchWords){
        var that= this;
        const offset = this.data.offset;
        const url =`/cloudsearch?keywords=${searchWords}&limit=6&offset=${offset}`
        // const url_album =`/cloudsearch?keywords=${searchWords}&limit=1&type=10`
        const res = await get(url)
        // const res_album = await get(url_album)
        const arr1 = this.data.searchResult;
        const arr2= res.data.result.songs;
        const musicLists = arr1.concat(arr2);
        console.log(res.data.result)
        // console.log(res_album.data.result)
        this.setData({
          count:res.data.result.songCount,
          searchResult: musicLists,
          // searchAlbum:res_album.data.result.albums[0],
          showSearchResult: true,
          showView: false,
          showSongResult:false
    
        })
      },
      getsearchAlbum: async function(searchWords){
        const url_album =`/cloudsearch?keywords=${searchWords}&limit=1&type=10`
        const res_album = await get(url_album)
        // console.log(res_album.data.result)
        this.setData({
          searchAlbum:res_album.data.result.albums[0],
        })
      },
      bindKeyInput: function (e) {
        console.log(e.detail.value);
        var that = this;
        if(e.detail.cursor != this.data.cursor) {
          this.setData({
            showSongResult: true,
            // cursor: e.detail.cursor,
            searchValue: e.detail.value
          })
          // 假设现在需要检测到用户输入的值,用户 500 毫秒内没有继续输入就将该值打印出来
          that.throttle(that.getSearchSuggest, null, 1000, this.data.searchValue);
        } 
        if (e.detail.value) { // 当input框有值时,才显示清除按钮'x'
          this.setData({
            showClean: false  
          })
        }
        
        if(e.detail.cursor===0){
          this.setData({
            showSongResult: false,
            showClean: true
          })
          return
        }
      },
      // 节流
      throttle: function (fn, context, delay, text) {
        clearTimeout(fn.timeoutId);
        fn.timeoutId = setTimeout(function () {
          fn.call(context, text);
        }, delay);
      },
      //热门歌曲点击
      fill_value: function (e) {
        var that=this;
        console.log(e.currentTarget.dataset.value)
        this.setData({
          searchValue: e.currentTarget.dataset.value||e.detail.value,
          showSongResult: false,
          showClean: false
        })
        that.getsearchList(that.data.searchValue)
        that.getsearchAlbum(that.data.searchValue)
      },
      clearInput: function(e) {
        console.log(e)
        this.setData({
          searchValue: '',
          showSongResult: false,
          showSearchResult: false,
          showView:true,
          showClean: true // 隐藏清除按钮
    
        })
      },
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        this.gethotList()
      },
    
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      onReady: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面显示
       */
      onShow: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面隐藏
       */
      onHide: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面卸载
       */
      onUnload: function () {
    
      },
    
      /**
       * 页面相关事件处理函数--监听用户下拉动作
       */
      onPullDownRefresh: function () {
        wx.showNavigationBarLoading();
        wx.stopPullDownRefresh;
      },
    
      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom: function () {
        var that=this;
        var total = Math.ceil(this.data.count/6);
        console.log(total);
        var offset = that.data.offset + 1; //获取当前页数并+1
        that.setData({
          offset: offset, //更新当前页数
        })
        this.getsearchList(this.data.searchValue)
      },
    
      /**
       * 用户点击右上角分享
       */
      onShareAppMessage: function () {
    
      }
    })
    search.js
    .m-input {
      padding: 15px 10px;
    }
    .m-input .inputcover {
      position: relative;
      width: 100%;
      height: 30px;
      padding: 0 30px;
      box-sizing: border-box;
      background: #ebecec;
      border-radius: 30px;
      font-size: 14px;
    }
    .m-hotlist {
      padding: 15px 10px 0;
    }
    .m-hotlist .title {
      font-size: 12px;
      line-height: 12px;
      color: #666;
    }
    .m-hotlist .list {
      margin: 10px 0 7px;
      display: flex;
      flex-wrap: wrap;
    }
    .m-hotlist .item{
      min-height: unset;
      height: 32px;
      margin-right: 8px;
      margin-bottom: 8px;
      padding: 0 14px;
      font-size: 14px;
      line-height: 32px;
      color: #333;
      border:1px solid #d3d4da;
      border-radius: 32px;
      display: inline-flex;
      align-items: center;
    }
    .header_view_hide{
      display: none;
    }
    .m-recom .title {
      height: 50px;
      margin-left: 10px;
      padding-right: 10px;
      font-size: 15px;
      line-height: 50px;
      color: #507daf;
    }
    .m-recom .recomitem {
      display: -webkit-box;
      display: -webkit-flex;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-align: center;
      -webkit-align-items: center;
      -ms-flex-align: center;
      align-items: center;
      height: 45px;
      padding-left: 10px;
    }
    .m-recom i {
      -webkit-box-flex: 0;
      -webkit-flex: 0 0 auto;
      -ms-flex: 0 0 auto;
      flex: 0 0 auto;
      margin-right: 7px;
    }
    .u-svg-search {
      width: 15px;
      height: 15px;
    }
    .m-input{
      position: relative;
    }
    .m-input .u-svg-srch {
      position: absolute;
      left: 15px;
      top: 20px;
      margin: 0 8px;
      vertical-align: middle;
      z-index: 10;
    }
    .m-input .close {
      position: absolute;
      right: 20px;
      top: 16px;
      line-height: 28px;
      text-align: center;
    }
    .u-svg-srch image{
      width: 13px;
      height: 13px;
    }
    .u-svg-empty image{
      width: 14px;
      height: 14px;
    }
    .u-svg-search image{
      width: 15px;
      height: 15px;
    }
    .m-matchlist .title {
      margin-left: 10px;
      font-size: 12px;
      line-height: 16px;
      color: #666;
    }
    .m-matchlist .linkcover {
      display: -webkit-box;
      display: -webkit-flex;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-align: center;
      -webkit-align-items: center;
      -ms-flex-align: center;
      align-items: center;
      height: 66px;
      margin-left: 10px;
      padding: 8px 10px 8px 0;
      box-sizing: border-box;
    }
    .m-matchlist .piccover {
      position: relative;
      width: 50px;
      height: 50px;
      margin-right: 15px;
      line-height: 0;
    }
    .m-matchlist .pic {
      display: block;
      width: 100%;
      height: 100%;
    }
    .hcover .highlight {
      color: #507daf;
    }
    .m-matchlist .describe {
      -webkit-box-flex: 1;
      -webkit-flex: 1;
      -ms-flex: 1;
      flex: 1;
      display: inline-block;
      width: 1%;
    }
    .f-thide {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      word-break: normal;
    }
    .m-matchlist .describe .addtional {
      font-size: 12px;
      line-height: 15px;
      color: #999;
      width: 100%;
      display: flex;
    }
    .u-svg-arr image{
      width: 8px;
      height: 13px;
    }
    .m-sgitem .sginfo {
      font-size: 12px;
      color: #888;
    }
    .m-sgitem, .m-sgitem .sgfl {
      display: -webkit-box;
      display: -webkit-flex;
      display: -ms-flexbox;
      display: flex;
    }
    .m-sgitem .sgchfl, .m-sgitem .sgfr {
      -webkit-box-flex: 1;
      -webkit-flex: 1 1 auto;
      -ms-flex: 1 1 auto;
      flex: 1 1 auto;
    }
    .m-sgitem .sgfr {
      display: -webkit-box;
      display: -webkit-flex;
      display: -ms-flexbox;
      display: flex;
      position: relative;
    }
    .m-sgitem {
      padding-left: 10px;
    }
    .m-sgitem .sgchfl {
      padding: 6px 0;
      width: 0;
    }
    .m-sgitem .sgchfr {
      display: -webkit-box;
      display: -webkit-flex;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-align: center;
      -webkit-align-items: center;
      -ms-flex-align: center;
      align-items: center;
      padding: 0 10px;
    }
    .m-sgitem .sghot {
      display: inline-block;
      width: 12px;
      height: 8px;
      margin-right: 4px;
    }
    .m-sgitem .sgchply {
      display: inline-block;
      width: 22px;
      height: 22px;
      background-position: -24px 0;
    }
    .u-hmsprt {
      background: url(//s3.music.126.net/mobile-new/img/index_icon_2x.png?5207a28…=) no-repeat;
      background-size: 166px 97px;
    }
    search.wxss
  • 相关阅读:
    Java 基础练习:控制台画圆,画等腰三角,乘法表
    Java 控制台五子棋游戏
    Java浮点数转化为人民币读法字符串
    Java Arrays类的用法
    Java javadoc使用
    Android 使用Camera2 调用摄像头显示预览与拍照
    SSRS: How to Display Checkbox on Report
    ADFS部署过程中设置network service对证书的读取权限
    Dynamics CRM2013 ScLib::AccessCheckEx failed
    ADFS3.0 Customizing the AD FS Sign-in Pages
  • 原文地址:https://www.cnblogs.com/cheryshi/p/14837659.html
Copyright © 2011-2022 走看看