微信小程序【网易云音乐实战】(第六篇 歌曲搜索、自定义模板、分包)
作者:互联网
一、歌曲搜索
1. 界面数据获取
<view class="searchContainer">
<!-- 头部搜索区域 -->
<view class="header">
<view class="searchInput">
<text class="iconfont icon-search1 searchIcon"></text>
<input type="text" placeholder="{{placeholderContent}}" placeholder-class="placeholder" />
</view>
<text class="cancel">取消</text>
</view>
<!-- 热搜榜 -->
<view class="hotContainer">
<text class="title">热搜榜</text>
<!-- 热搜列表 -->
<view class="hotList">
<view class="hotItem" wx:for="{{hotList}}" wx:key="searchWord">
<text class="order">{{index + 1}}</text>
<text>{{item.searchWord}}</text>
<image wx:if="{{item.iconUrl}}" src="{{item.iconUrl}}" class="iconImg"></image>
</view>
</view>
</view>
</view>
.searchContainer{
padding: 0 20rpx;
}
.header{
display: flex;
height: 60rpx;
line-height: 60rpx;
padding: 10rpx 0;
}
.searchInput{
flex: 1;
background: rgba(237,237,237,0.5);
border-radius: 30rpx;
}
.cancel{
width: 100rpx;
text-align: center;
}
.searchIcon{
position: absolute;
left: 15rpx;
}
.searchInput input{
margin-left: 50rpx;
height: 60rpx;
}
.placeholder{
/*color: #d43c33;*/
font-size: 28rpx;
}
/* 热搜榜的样式*/
.hotContainer .title{
font-size: 28rpx;
height: 80rpx;
line-height: 80rpx;
border-bottom: 1rpx solid #eeeeee;
}
.hotList{
display: flex;
flex-wrap: wrap;
}
.hotItem{
width: 50%;
height: 80rpx;
line-height: 80rpx;
font-size: 26rpx;
}
.hotItem .order{
margin: 0 10rpx;
}
.hotItem .iconImg{
width: 35rpx;
height: 20rpx;
margin-left: 10rpx;
}
// 获取初始化的数据
async getInitData() {
let placeholderData = await request("/search/default");
let hotListData = await request("/search/hot/detail");
this.setData({
placeholderContent:placeholderData.data.showKeyword,
hotList:hotListData.data
});
},
2. 模糊匹配
数据节流:每0.3 秒发一次请求
let isSend = true; // 函数节流使用
// 表单项数据发生变化时的回调
handleInputChange(event) {
console.log(event)
this.setData({
searchContent: event.detail.value.trim()
});
if(isSend === false){
return;
}
isSend = false;
// 知识点:函数节流
setTimeout(()=>{
// 发请求获取关键字模糊匹配数据
this.getSearchList();
isSend = true;
},300);
},
// 获取搜索数据的功能函数
async getSearchList() {
if(!this.data.searchContent){
this.setData({
searchList:[]
})
return;
}
let searchListData = await request("/search", {keywords: this.data.searchContent, limit: 10});
this.setData({
searchList: searchListData.result.songs
});
},
3. 歌曲搜索
<!-- 搜索内容展示 -->
<block wx:if="{{searchList.length}}">
<view class="showSearchContent">
<view class="searchContent">搜索内容:{{searchContent}}</view>
<view class="searchList">
<view class="searchItem" wx:for="{{searchList}}" wx:key="id">
<text class="iconfont icon-search1"></text>
<text class="content">{{item.name}}</text>
</view>
</view>
</view>
</block>
<!-- 热搜榜 -->
<block wx:else>
<view class="hotContainer">
<text class="title">热搜榜</text>
<!-- 热搜列表 -->
<view class="hotList">
<view class="hotItem" wx:for="{{hotList}}" wx:key="searchWord">
<text class="order">{{index + 1}}</text>
<text>{{item.searchWord}}</text>
<image wx:if="{{item.iconUrl}}" src="{{item.iconUrl}}" class="iconImg"></image>
</view>
</view>
</view>
</block>
/* 热搜榜的样式*/
.hotContainer .title{
font-size: 28rpx;
height: 80rpx;
line-height: 80rpx;
border-bottom: 1rpx solid #eeeeee;
}
.hotList{
display: flex;
flex-wrap: wrap;
}
.hotItem{
width: 50%;
height: 80rpx;
line-height: 80rpx;
font-size: 26rpx;
}
.hotItem .order{
margin: 0 10rpx;
}
.hotItem .iconImg{
width: 35rpx;
height: 20rpx;
margin-left: 10rpx;
}
/* 搜索内容展示 */
.searchContent{
color: #d43c43;
height: 80rpx;
line-height: 80rpx;
font-size: 24rpx;
border-bottom: 1rpx solid #d43c43;
}
.searchItem{
height: 80rpx;
line-height: 80rpx;
display: flex;
}
.searchItem .content{
flex: 1;
margin-left: 20rpx;
border-bottom: 1rpx solid #eee;
font-size: 26rpx;
}
4. 历史纪录
<!-- 搜索的历史纪录 -->
<view class="history" wx:if="{{historyList.length}}">
<view class="title">历史</view>
<view class="historyItem" wx:for="{{historyList}}" wx:key="{{item}}">{{item}}</view>
<!-- 删除区域 -->
<text class="iconfont icon-shanchu delete" bindtap="deleteSearchHistory"></text>
</view>
<!-- 热搜榜 -->
<view class="hotContainer">
<text class="title">热搜榜</text>
<!-- 热搜列表 -->
<view class="hotList">
<view class="hotItem" wx:for="{{hotList}}" wx:key="searchWord">
<text class="order">{{index + 1}}</text>
<text>{{item.searchWord}}</text>
<image wx:if="{{item.iconUrl}}" src="{{item.iconUrl}}" class="iconImg"></image>
</view>
</view>
</view>
/* 搜索历史样式 */
.history{
position: relative;
display: flex;
flex-wrap: wrap;
margin: 20rpx 0;
}
.history .title{
font-size: 28rpx;
height: 50rpx;
line-height: 50rpx;
}
.history .historyItem{
font-size: 26rpx;
height: 50rpx;
line-height: 50rpx;
background: #ededed;
margin-left: 20rpx;
padding: 0 30rpx;
border-radius: 20rpx;
margin-bottom: 20rpx;
}
.history .delete{
position: absolute;
bottom: 10rpx;
right: 15rpx;
font-size: 36rpx;
}
data: {
placeholderContent:"", // placeholder 的内容
hotList:[], // 热搜榜数据
searchContent:"" , // 用户输入的表单项数据
searchList:[], // 关键字迷糊匹配的数据
historyList:[], // 搜索历史纪录
},
onl oad: function (options) {
// 获取初始化数据
this.getInitData();
// 获取历史纪录
this.getSearchHistory();
},
// 获取初始化的数据
async getInitData() {
let placeholderData = await request("/search/default");
let hotListData = await request("/search/hot/detail");
this.setData({
placeholderContent:placeholderData.data.showKeyword,
hotList:hotListData.data
});
},
// 表单项数据发生变化时的回调
handleInputChange(event) {
this.setData({
searchContent: event.detail.value.trim()
});
if(isSend === false){
return;
}
isSend = false;
// 知识点:函数节流
setTimeout( ()=>{
// 发请求获取关键字模糊匹配数据
this.getSearchList();
isSend = true;
},300);
},
// 获取搜索数据的功能函数
async getSearchList() {
if(!this.data.searchContent){
this.setData({
searchList:[]
})
return;
}
let {searchContent,historyList} = this.data;
let searchListData = await request("/search", {keywords: searchContent, limit: 10});
this.setData({
searchList: searchListData.result.songs
});
// 将搜索的关键字添加到搜索纪录中
if(historyList.indexOf(searchContent) !== -1){ // 已存在 删除
historyList.splice(historyList.indexOf(searchContent));
}
historyList.unshift(searchContent); // 添加到前面
this.setData({
historyList:historyList
});
// 存在本地
wx.setStorageSync("searchHistory",historyList);
},
// 获取本地历史纪录的功能函数
getSearchHistory(){
let historyList = wx.getStorageSync("searchHistory");
if(historyList){
this.setData({
historyList:historyList
})
}
},
// 清空搜索内容回调
clearSearchContent(event){
this.setData({
searchContent:"",
searchList:[]
})
},
// 删除搜索的历史纪录回调
deleteSearchHistory(event){
wx.showModal({
content:"确定删除吗?",
success:(res)=>{
if(res.confirm){
// 清空data中的 historyList
this.setData({
historyList:[]
})
// 移除本地的历史数据
wx.removeStorageSync("searchHistory");
}
}
})
},
二、自定义模板使用
实例
模板:
myTemplate.wxml
<!-- 定义 模板 -->
<template name="myTmp">
<view>
<view class="title">这是我自定义的模板</view>
<view>
<view class="userName">用户名:{{username}}</view>
<view class="age">年龄:{{age}}</view>
</view>
</view>
</template>
myTemplate.wxss
.title{
font-size: 80rpx;
color: red;
}
引用:
other.wxml
<import src="/template/myTemplate/myTemplate"/>
<view class="otherContainer">
<!-- 测试使用模板 -->
<view>测试使用模板如下:</view>
<template is="myTmp" data="{{...person}}"/>
</view>
other.wxss
/* 引入模板样式 */
@import "/template/myTemplate/myTemplate.wxss";
other.js
data: {
person:{
username:"nzs",
age:22
}
},
三、获取用户登录凭证(唯一标识 openId)
服务器端:
github上:fly 和 jsonwebtoken库
npm install flyio
npm install jsonwebtoken
const Fly=require("flyio/src/node");
const jwt = require('jsonwebtoken');
const fly=new Fly;
// 注册获取用户唯一标识的接口
app.use('/getOpenId', async (req, res, next) => {
let code = req.query.code;
let appId = 'wx810e8b1fde386fde';
let appSecret = '8bb909649da12002fba7a47f5ac3791b';
let url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appId}&secret=${appSecret}&js_code=${code}&grant_type=authorization_code`
// 发请求给微信服务器获取openId
let result = await fly.get(url);
let openId = JSON.parse(result.data).openid;
console.log('openId', openId);
// 自定义登录态
let person = {
username: 'nzs',
age: 18,
openId
}
// 对用户的数据进行加密,生成token返回给客户端
let token = jwt.sign(person, 'atguigu');
console.log(token);
// 验证身份,反编译token
let result2 = jwt.verify(token, 'atguigu');
console.log(result2);
res.send(token);
});
前端:
// 获取用户唯一标识的回调
handleGetOpenId(event) {
// 1. 获取登录凭证
wx.login({
success: async (res) => {
let code = res.code;
// 2. 将登录的凭证发送给服务器
let result = await request("/getOpenId", {code});
console.log(result)
}
})
},
四、分包
4.1 常规分包
1. 创建文件夹,移动相应的文件
2. 配置 app.json
"subpackages": [
{
"root": "songPackage",
"pages": [
"pages/recommendSong/recommendSong",
"pages/songDetail/songDetail"
]
},
{
"root": "otherPackage",
"pages": [
"pages/other/other"
]
}
]
3. 修改由于分包导致的路径错误
4. 完成
4.2 独立分包
3. 分包预加载
"preloadRule": {
"pages/index/index": {
"packages": ["songPackage","other"]
}
}
加载主包:
五、开发完成
标签:自定义,80rpx,微信,historyList,height,item,let,searchContent,第六篇 来源: https://blog.csdn.net/qq_45021180/article/details/113254731