10.4.3 检索页 (上)

首页的最后一部分为检索页,也就是让用户通过关键字搜索歌曲或专辑。

说到搜索页,比不可少的就是关键字的输入框。

图10-4 搜索框样图

参照这个样式,布局文件应该为:

<view class="search-bar">
    <view class="search-input-warp">
      <form bindsubmit="searchSubmit">
        <label class="search-input-icon"></label>
        <input type="text" class="search-input" bindfocus="bindFocus" name="search" value="{{searchKey}}" bindinput="bindKeyInput" placeholder="搜索歌曲、歌单、专辑" placeholder-class="search-input-placeholder"/>
        <view class="search-cancel" bindtap="searchOk">确定</view>
      </form>
    </view>
  </view>

格式文件为:

.search-bar {
    background:#f7f7f7;
    padding:20rpx;
}
.search-input-warp {
    position:relative;
    padding:16rpx 24rpx 16rpx 70rpx;
    background:#fff;
}
.search-input-icon {
    content:" ";
    position:absolute;
    top:18rpx;
    left:20rpx;
    display:inline-block;
    vertical-align:middle;
    width:40rpx;
    height:40rpx;
    background-image:url("../../resources/images/search.png");
    background-repeat:no-repeat;
    background-size:40rpx;
}
.search-input {
    font-size:28rpx;
    line-height:40rpx;
}
.search-input-placeholder {
    color:#ddd;
    font-size:28rpx;
    line-height:40rpx;
}
.search-cancel {
    position:absolute;
    right:0;
    top:0;
    display:inline-block;
    font-size:32rpx;
    height:90rpx;
    width:140rpx;
    text-align:center;
    line-height: 90rpx;
    z-index:50;
    background:#f7f7f7;
}

因为要提交关键字,所以使用表单组件,内部由表示搜索的放大镜图标,代表输入完成的“确定”按钮以及输入框组成。

除了输入框以外,此页还需要显示的内容应该是搜索的结果列表,搜索的历史记录以及热门关键字。这些内容应该显示在输入框下方,并按一定逻辑切换。他们之间的逻辑关系为:

  1. 用户进入检索页,显示的内容应该是输入框与热门关键字。
  2. 开始输入后(即输入框获得焦点),应该显示历史记录。
  3. 点击确定,显示结果列表。
  4. 清空输入框内容后,返回关键字显示。

可以看出,对输入框的操作决定了当前页面显示的内容,所以我们需要监听输入框的获取焦点事件(bindfocus),确定点击事件(bindtap)以及输入事件(bindinput),还需要记录输入的关键字searchKey。

输入框完成后我们先写热门关键字,这些关键字也是来源于网络,所以还需要请求网络。在services/music里添加方法:

function getHotSearchKey(callback){
    var data = {
            g_tk: 5381,
            uin: 0,
            format: 'json',
            inCharset: 'utf-8',
            outCharset: 'utf-8',
            notice: 0,
            platform: 'h5',
            needNewCode: 1,
            _: Date.now()
        };
        wx.request({
            url: 'http://c.y.qq.com/splcloud/fcgi-bin/gethotkey.fcg',
            data: data,
            header: {
                'Content-Type': 'application/json'
            },
            success: function (res) {
                if (res.statusCode == 200) {
                    callback(res.data)
                } else {

                }
            }
        });
}
...
module.exports = {
  ...
  getHotSearchKey:getHotSearchKey
}

返回JSON格式结果为

{
    "code": 0,
    "data": {
        "hotkey": [
            {
                "k": "三生三世十里桃花 ",
                "n": 90558
            },
            {
                "k": "DJ ",
                "n": 67590
            },
            {
                "k": "薛之谦 ",
                "n": 60425
            },
            {
                "k": "凉凉 ",
                "n": 37056
            },
            {
                "k": "那片星空那片海 ",
                "n": 29170
            },
            {
                "k": "理想 ",
                "n": 28695
            },
            ...
        ],
        "special_key": "歌手",
        "special_url": "http://y.qq.com/m/act/singer/index.html?ADTAG=search"
    },
    "subcode": 0
}

这里返回的hotkey就是我们需要的关键字啦,除此之外,我们还看到下面有“special_key”这一部分,这相当于广告部分,为服务器推荐的搜索关键字。所以我们以标签的形式显示关键字,对于广告那部分关键字,我们以红色字体,并且放在最前方,最后达成的样式应该为图10-5所示:

图10-5 热门搜索标签样图

实现这一布局的代码为:

<view class="quick-search" wx:if="{{showSearchPanel == 1}}">
    <view class="quick-search-title">
      <text>热门搜索</text>
    </view>
    <view class="quick-search-bd">
      <text class="quick-search-item-red" data-url="{{special.url}}" data-key="{{special.key}}" bindtap="hotKeysTap" wx:if="{{showSpecial}}">{{special.key}}</text>
      <text class="quick-search-item" wx:for="{{hotkeys}}" wx:key="unique" data-n="{{item.n}}" bindtap="hotKeysTap" data-key="{{item.k}}">{{item.k}}</text>
    </view>
  </view>

这里面showSearchPanel的值为我们控制这一页面切换的依据,当其为1的时候,显示热门关键字。

绑定的数据有两个,special和hotkey。对于special部分,为了防止服务器缺失“special_key”这一部分从而导致没有数据显示,我们定义一个数据showSpecial来决定是否显示这一部分。

将这三个数据以及输入框用到的searchKey添加到data里吧。

修改index.js文件:

//引用网络请求文件
var MusicService = require('../../services/music');

//获取应用实例
var app = getApp()
Page({
    data: {
        indicatorDots: true,
        autoplay: true,
        interval: 5000,
        duration: 1000,
        radioList: [],
        slider: [],
        mainView: 1,
        topList:[],
        hotkeys: [],
        showSpecial: false,
        special: { key: '', url: '' },
        searchKey: '',
    },
    onLoad: function () {
        var that = this;
        MusicService.getRecommendMusic(that.initPageData);
        MusicService.getTopMusic(that.initTopList);
        MusicService.getHotSearchKeys(that.initSearchHotKeys);    
    },

    ...
    initSearchHotKeys: function (data) {
        var self = this;
        if (data.code == 0) {
            var special = { key: data.data.special_key, url: data.data.special_url };
            var hotkeys = [];
            if (data.data.hotkey && data.data.hotkey.length) {  //当返回数据不为空且长度不为0
                for (var i = 0; (i < data.data.hotkey.length && i < 6); i++) {   //如果长度大于6只保留前6个
                    var item = data.data.hotkey[i];                              
                    hotkeys.push(item);
                }
            }
            if (special != undefined) {     //当返回项有special部分时,showSpecial为true
                self.setData({
                    showSpecial: true
                })
            } else {                        //没有special部分,showSpecial为false
                self.setData({
                    showSpecial:false
                })
            }
            self.setData({
                special: special,
                hotkeys: hotkeys
            })
        }
    },
    ...
})

数据加载完成后,我们为每个热门关键字view添加点击事件。

hotKeysTap: function (e) {
         //TODO
    },

在这个点击事件里,我们需要做的事情有:

  1. 将点击的关键词加入历史记录。
  2. 将页面切换到搜索结果列表。 在完成搜索结果列表页后我们再来完善这一部分吧。

最后附上这一部分的格式文件。

.quick-search {
    padding:20rpx;
    box-sizing:border-box;
}
.quick-search-title {
    font-size:28rpx;
}
.quick-search-bd {
    position:relative;
    margin-top:20rpx;
}
.quick-search-item {
    font-size:28rpx;
    float:left;
    margin:0 20rpx 20rpx 0;
    line-height:40rpx;
    padding:10rpx 20rpx;
    border-radius:30rpx;
    color:#000;
    border:2rpx solid rgba(0,0,0,.6);
}
.quick-search-item-red {
    font-size:28rpx;
    float:left;
    margin:0 20rpx 20rpx 0;
    line-height:40rpx;
    padding:10rpx 20rpx;
    border-radius:30rpx;
    color:#fc4524;
    border:2rpx solid #fc4524;
}

results matching ""

    No results matching ""