这里写目录标题
一、自定义组件
1. 制作自定义组件
上面这个部分将在项目中重复使用,所有将其作为一个组件。
首先将index页面文件夹里面的 wxml和wxss里面关于header的代码片段和样式复制到新建的conponent组件相应的文件里。
2. 使用自定义组件
- 在page里面需要注册(在index.json文件的usingComponents添加注册)
由于前面设置的滚动条太高了,所有需要设置一下这个容器的高度!
/* 推荐歌曲样式设置 */
.commmendContainer{
padding: 20rpx;
height: 400rpx;
}
完成组件的复用:
3. 组件动态数据
需要根据不同的需要改变组件的显示内容
参考官方文档!
Navheader.wxml
<!-- 头部 -->
<view class="header">
<text class="title">{{title}}</text>
<view>
<text>{{nav}}</text>
<text class="more">查看更多</text>
</view>
</view>
NavHeader.js
properties: {
title:{
type:String,
value:"title的默认值"
},
nav:{
type:String,
value:"nav的默认值"
}
},
index.wxml 里面的使用
<!-- 头部 -->
<NavHeader title="推荐歌曲" nav="为你精心推荐"></NavHeader>
<!-- 头部区域-->
<NavHeader title="排行榜" nav="热歌风向标"></NavHeader>
二、排行榜的制作
1. 静态搭建
<!-- 排行榜区域-->
<view class="topList">
<!-- 头部区域-->
<NavHeader title="排行榜" nav="热歌风向标"></NavHeader>
<!-- 内容区域 采用轮播图的形式 -->
<swiper class="topListSwiper" next-margin="50rpx" previous-margin="50rpx">
<swiper-item>
<view class="swiperItem">
<view class="title">云音乐热歌榜</view>
<view class="musicItem">
<image src="/static/images/nvsheng.jpg"></image>
<text class="count">1</text>
<text class="musicName">光辉岁月</text>
</view>
<view class="musicItem">
<image src="/static/images/nvsheng.jpg"></image>
<text class="count">2</text>
<text class="musicName">海阔天空</text>
</view>
<view class="musicItem">
<image src="/static/images/nvsheng.jpg"></image>
<text class="count">3</text>
<text class="musicName">真的爱你</text>
</view>
</view>
</swiper-item>
<swiper-item>
<view class="swiperItem">
<view class="title">云音乐热歌榜</view>
<view class="musicItem">
<image src="/static/images/nvsheng.jpg"></image>
<text class="count">1</text>
<text class="musicName">光辉岁月</text>
</view>
<view class="musicItem">
<image src="/static/images/nvsheng.jpg"></image>
<text class="count">2</text>
<text class="musicName">海阔天空</text>
</view>
<view class="musicItem">
<image src="/static/images/nvsheng.jpg"></image>
<text class="count">3</text>
<text class="musicName">真的爱你</text>
</view>
</view>
</swiper-item>
</swiper>
</view>
/* 排行榜的 样式*/
.topList{
padding: 20rpx;
}
.topListSwiper{
height: 400rpx;
}
.swiperItem{
width: 96%;
background: #FBFBFB;
}
.swiperItem .title{
font-size: 30rpx;
line-height: 80rpx;
}
.musicItem{
/* 当一个元素设置为flex,其子元素会自动成为block元素 */
display: flex;
padding-bottom: 20rpx;
}
.musicItem image{
width: 100rpx;
height: 100rpx;
border-radius: 6rpx;
}
.musicItem .count{
width: 100rpx;
height: 100rpx;
text-align: center;
line-height: 100rpx;
}
.musicItem .musicName{
height: 100rpx;
line-height: 100rpx;
/* 歌曲名过长 时隐藏 */
max-width: 400rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
2. 获取排行榜动态数据
直接for循环
<!-- 排行榜区域-->
<view class="topList">
<!-- 头部区域-->
<NavHeader title="排行榜" nav="热歌风向标"></NavHeader>
<!-- 内容区域 采用轮播图的形式 -->
<swiper class="topListSwiper" next-margin="50rpx" previous-margin="50rpx">
<swiper-item wx:for="{{topListData}}" wx:key="name" >
<view class="swiperItem">
<view class="title">{{item.name}}</view>
<view class="musicItem" wx:for="{{item.tracks}}" wx:key="id" wx:for-item="musicItem">
<image src="{{musicItem.al.picUrl}}"></image>
<text class="count">{{index+1}}</text>
<text class="musicName">{{musicItem.name}}</text>
</view>
</view>
</swiper-item>
</swiper>
</view>
// 3. 获取排行榜的数据
/* 需求分析
1. 需要根据idx的值获取对应的数据
2. idx的取值范围是 0-20 ,我们只需要 0-4
3. 所以需要发送5次请求来获取数据
* */
// 3.1 组装数据
let index = 0;// 标识idx
let resultArr=[];
while (index<5){
let topListData = await request("/top/list",{idx:index++});
// 数组的截取:splice(会修改原数组) slice(不会修改原数组)
let topListItem={name:topListData.playlist.name,tracks:topListData.playlist.tracks.slice(0,3)};
resultArr.push(topListItem);
// 3.2 更新数据
this.setData({
topListData:resultArr
});
}
三、内网穿透(真机体验)
使用工具 https://u.tools/
由于服务器在自己的本机上,我们的手机localhost是访问不到的,所以我们需要借助工具 uTool
.
下载:
下载插件:内网穿透
将生成的域名链接替换原来的 localhost
最后进行真机调试:
四、tabBar(底部栏) 的使用
使用:
在app.json里面添加tabBar,list最少需要两个
"tabBar": {
"color":"#333",
"selectedColor": "#d43c33",
"backgroundColor": "#FFF",
"list": [
{
"pagePath": "pages/index/index",
"text": "主页",
"iconPath": "/static/images/tabs/tab-home.png",
"selectedIconPath": "static/images/tabs/tab-home-current.png"
},
{
"pagePath": "pages/video/video",
"text": "视频",
"iconPath": "/static/images/tabs/select.png",
"selectedIconPath": "static/images/tabs/selected.png"
},
{
"pagePath": "pages/personal/personal",
"text": "个人中心",
"iconPath": "/static/images/tabs/tab-my.png",
"selectedIconPath": "static/images/tabs/tab-my-current.png"
}
]
}
可设置为顶部位置:
五、个人中心页面
关键点介绍:
<view
class="cover-container"
bindtouchstart="handleTouchStart"
bindtouchmove="handleTouchMove"
bindtouchend="handleTouchEnd"
style="transform: {{coverTransform}}; transition:{{coverTransition}}"
>
// pages/personal/personal.js
let startY=0; // 手指开始的坐标
let moveY=0; // 手指移动的坐标
let moveDistance=0; // 手指移动的距离
Page({
data: {
coverTransform:"translateY(0rpx)", // 移动距离数据
coverTransition:"" // 缓动效果
},
// 1. 开始
handleTouchStart(event){
// 获取起始坐标
startY=event.touches[0].clientY; // touches[0]取第一次点击,因为屏幕可能有多个位置被点击
},
// 2.移动
handleTouchMove(event){
// 获取手指移动的坐标
moveY = event.touches[0].clientY;
moveDistance=moveY-startY; // 手指往下移动为正,往下为负数
// 更新移动的距离
if(moveDistance <=0){
return;
}
if(moveDistance >= 80){
moveDistance = 80;
}
this.setData({
coverTransform:`translateY(${moveDistance}rpx)`,
coverTransition:""
})
},
// 3.结束
handleTouchEnd(event){
this.setData({
coverTransform:`translateY(0rpx)`,
coverTransition:"transform 1s linear"
})
},
})
界面和样式下载 https://download.csdn.net/download/qq_45021180/14921902
界面的搭建代码如下:
<view class="personalContainer">
<view class="user-section">
<image class="bg" src="/static/images/personal/bgImg2.jpg"></image>
<view class="user-info-box">
<view class="portrait-box">
<image class="portrait" src='/static/images/personal/missing-face.png'></image>
</view>
<view class="info-box">
<text class="username">游客</text>
</view>
</view>
<view class="vip-card-box">
<image class="card-bg" src="/static/images/personal/vip-card-bg.png" mode=""></image>
<view class="b-btn">
立即开通
</view>
<view class="tit">
<!-- 会员图标-->
<text class="iconfont icon-huiyuan-"></text>
硅谷会员
</view>
<text class="e-m">atguigu Union</text>
<text class="e-b">开通会员听歌, 撸代码</text>
</view>
</view>
<view
class="cover-container"
bindtouchstart="handleTouchStart"
bindtouchmove="handleTouchMove"
bindtouchend="handleTouchEnd"
style="transform: {{coverTransform}}; transition:{{coverTransition}}"
>
<image class="arc" src="/static/images/personal/arc.png"></image>
<!-- 个人中心导航 -->
<view class="nav-section">
<view class="nav-item" hover-class="common-hover" hover-stay-time="50">
<text class="iconfont icon-xiaoxi"></text>
<text>我的消息</text>
</view>
<view class="nav-item" hover-class="common-hover" hover-stay-time="50">
<text class="iconfont icon-myRecommender"></text>
<text>我的好友</text>
</view>
<view class="nav-item" hover-class="common-hover" hover-stay-time="50">
<text class="iconfont icon-gerenzhuye"></text>
<text>个人主页</text>
</view>
<view class="nav-item" hover-class="common-hover" hover-stay-time="50">
<text class="iconfont icon-gexingzhuangban"></text>
<text>个性装扮</text>
</view>
</view>
<!-- 个人中心列表 -->
<view class="personalContent">
<view class="recentPlayContainer">
<text class="title">最近播放</text>
<!-- 最近播放记录 -->
</view>
<view class="cardList">
<view class="card-item">
<text class="title">我的音乐</text>
<text class="more"> > </text>
</view>
<view class="card-item">
<text class="title">我的收藏</text>
<text class="more"> > </text>
</view>
<view class="card-item">
<text class="title">我的电台</text>
<text class="more"> > </text>
</view>
</view>
</view>
</view>
</view>
样式:
/* pages/personal/personal.wxss */
.personalContainer {
width: 100%;
height: 100%;
}
.personalContainer .user-section {
height: 520rpx;
position: relative;
padding: 100rpx 30rpx 0;
}
.user-section .bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0.7;
filter: blur(1px);
}
.user-info-box{
height: 180rpx;
display:flex;
align-items:center;
position:relative;
z-index: 1;
}
.user-info-box .portrait{
width: 130rpx;
height: 130rpx;
border:5rpx solid #fff;
border-radius: 50%;
}
.user-info-box .username{
font-size: 24;
color: #303133;
margin-left: 20rpx;
}
/* vip-box */
.vip-card-box {
position: relative;
display: flex;
flex-direction: column;
// background: linear-gradient(left, red, black);
background: rgba(0, 0, 0, .7);
height: 240rpx;
color: #f7d680;
border-radius: 16rpx 16rpx 0 0;
padding: 20rpx 24rpx;
}
.vip-card-box .card-bg{
position:absolute;
top: 20rpx;
right: 0;
width: 380rpx;
height: 260rpx;
}
.vip-card-box .b-btn{
position: absolute;
right: 20rpx;
top: 16rpx;
width: 132rpx;
height: 40rpx;
text-align: center;
line-height: 40rpx;
font-size: 22rpx;
color: #36343c;
border-radius: 20px;
background: #f9e6af;
z-index: 1;
}
.vip-card-box .b-btn{
position: absolute;
right: 20rpx;
top: 16rpx;
width: 132rpx;
height: 40rpx;
text-align: center;
line-height: 40rpx;
font-size: 22rpx;
color: #36343c;
border-radius: 20px;
/*background: linear-gradient(left, #f9e6af, #ffd465);*/ /*渐变不生效*/
background: #f9e6af;
z-index: 1;
}
.vip-card-box .tit {
font-size: 22rpx;
color: #f7d680;
margin-bottom: 28rpx;
}
.vip-card-box .tit .iconfont{
color: #f6e5a3;
margin-right: 16rpx;
}
.vip-card-box .e-m{
font-size: 34rpx;
margin-top: 10rpx;
}
.vip-card-box .e-b{
font-size: 24rpx;
color: #d8cba9;
margin-top: 10rpx;
}
.cover-container{
margin-top: -150rpx;
padding: 0 30rpx;
position:relative;
background: #f5f5f5;
padding-bottom: 20rpx;
}
.cover-container .arc{
position:absolute;
left: 0;
top: -34rpx;
width: 100%;
height: 36rpx;
}
/* 导航部分 */
.cover-container .nav-section {
display: flex;
background: #fff;
padding: 20rpx 0;
border-radius: 15rpx;
}
.nav-section .nav-item {
width: 25%;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
}
.nav-section .nav-item .iconfont {
font-size: 50rpx;
color: #d43c33;
line-height: 70rpx;
}
.nav-section .nav-item text:last-child {
font-size: 22rpx;
}
/* 个人中心列表 */
.personalContent {
background: #fff;
margin-top: 20rpx;
}
/* 最近播放 */
.personalContent .scrollView {
display: flex;
height: 160rpx;
}
.personalContent .recentPlay {
display: flex;
}
.recentPlayContainer .title {
padding-left: 20rpx;
font-size: 26rpx;
color: #333;
line-height: 80rpx;
}
.personalContent .recentPlay image {
width: 160rpx;
height: 160rpx;
margin-left: 20rpx;
border-radius: 20rpx;
}
.cardList {
margin-top: 20rpx;
}
.cardList .card-item{
border-top: 1rpx solid #eee;
height: 80rpx;
line-height: 80rpx;
padding: 10rpx;
font-size: 26rpx;
color: #333;
}
.cardList .card-item .more {
float: right;
}