掌握Video详情页-获取网络数据
编写播放页面
/pages/service/api_video.js中编写请求mv的播放地址、请求MV的详情、请求关于MV的相关视频
import hyRequest from './index'
export function getTopMV(offset,limit = 10){
return hyRequest.get("/top/mv",{
offset,
limit
})
}
/**
* 请求MV的播放地址
* @param {number} id MV的id
*/
export function getMVURL(id) {
return hyRequest.get("/mv/url",{
id
})
}
/**
* 请求MV的详情
* @param {nmber} mvid MV的id
*/
export function getMVDetail(mvid) {
return hyRequest.get("/mv/detail",{
mvid
})
}
export function getRelatedVideo(id) {
return hyRequest.get("/related/allvideo",{
id
})
}
在// pages/detail-video/index.js使用await如下获取数据,但不推荐,原因是await需要从上到下依次执行代码,而1.2.3.这三块获取数据互不相干,可以同时请求,优化性能。
onLoad:async function (options) {
const id = options.id
// 1.请求播放地址
const res1 = await getMVURL(id)
console.log(res1)
// 2.请求视频信息
const res2 = await getMVDetail(id)
console.log(res2)
// 3.请求相关视频
const res3 = await getRelatedVideo(id)
console.log(res3)
},
优化后
onLoad:async function (options) {
const id = options.id
// 1.请求播放地址
getMVURL(id).then(res =>{
})
// 2.请求视频信息
getMVDetail(id).then(res =>{
})
// 3.请求相关视频
getRelatedVideo(id).then(res =>{
})
},
获取数据
// pages/detail-video/index.js
import {getMVURL,getMVDetail,getRelatedVideo} from '../../service/api_video'
Page({
/**
* 页面的初始数据
*/
data: {
mvURLInfo:{},
mvDetail:{},
relatedVideos:[]
},
/**
* 生命周期函数--监听页面加载
*/
onLoad:async function (options) {
const id = options.id
// 1.请求播放地址
getMVURL(id).then(res =>{
this.setData({mvURLInfo:res.data})
})
// 2.请求视频信息
getMVDetail(id).then(res =>{
this.setData({mvDetail:res.data})
})
// 3.请求相关视频
getRelatedVideo(id).then(res =>{
this.setData({relatedVideos:res.data})
})
},
})
成功获取到的数据在界面→调试器→AppData中查看
优化代码可读性,把获取数据抽离成一个函数。
// pages/detail-video/index.js
import {getMVURL,getMVDetail,getRelatedVideo} from '../../service/api_video'
Page({
/**
* 页面的初始数据
*/
data: {
mvURLInfo:{},
mvDetail:{},
relatedVideos:[]
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// 1.获取传入的id
const id = options.id
// 2.获取页面的数据
this.getPageData(id)
// 3.其他逻辑
},
getPageData:function(id){
// 1.请求播放地址
getMVURL(id).then(res =>{
this.setData({mvURLInfo:res.data})
})
// 2.请求视频信息
getMVDetail(id).then(res =>{
this.setData({mvDetail:res.data})
})
// 3.请求相关视频
getRelatedVideo(id).then(res =>{
this.setData({relatedVideos:res.data})
})
}
})
最终完成效果图
接下来完善视频播放下面的样式编写
关于小程序播放,在微信官方文档→开发→组件→媒体组件→video
<!--pages/detail-video/index.wxml-->
<video class="video"
src="{{mvURLInfo.url}}"
danmu-list="{{danmuList}}"
autoplay
loop>
</video>
<block wx:for="{{100}}" wx:key="*this">
<view>列表数据{{item}}</view>
</block>
添加position:fixed;使video固定在顶部不被滑动
page {
padding-top: 225px;
} video默认的高度为225px,padding-top: 225px;使顶部空出video对应高度的位置,同时.video添加top:0,这样前十条数据就不会被视频播放器遮盖,实现滑动区。
/* pages/detail-video/index.wxss */
page {
padding-top: 225px;
}
.video {
position:fixed;
width: 100%;
top:0;
}
(掌握)小程序npm使用第三方包
在界面→调试器→终端 输入npm init -y 创建package.json
项目管理文件,记录着当前依赖着那些包以及项目的其他信息
GitHub - vant-ui/vant-weapp: 轻量、可靠的小程序 UI 组件库
GitHub - vant-ui/vant-weapp: 轻量、可靠的小程序 UI 组件库轻量、可靠的小程序 UI 组件库. Contribute to vant-ui/vant-weapp development by creating an account on GitHub.https://github.com/vant-ui/vant-weapp使用说明文档:Vant Weapp - 轻量、可靠的小程序 UI 组件库轻量、可靠的小程序 UI 组件库
https://vant-ui.github.io/vant-weapp/#/home
在界面→调试器→终端 输入npm install @vant/weapp 创建node_modules文件夹
(掌握)music页面搜索框
然后在工具→构建npm 后出现 miniprogram_npm文件夹,就可以引用组件库,写搜索框。
去Vant Weapp - 轻量、可靠的小程序 UI 组件库查看Search搜索的组件如何引用
在//pages/home-music/index.json中
{
"usingComponents": {
"van-search": "@vant/weapp/search/index"
}
}
<!--pages/home-music/index.wxml-->
<van-search/>
效果图:
如果Search的图标不加载显示,可以清楚缓存,从新编译,亦或者退出编辑器重新进入。这是因为小程序编辑工具本身有一定的bug,在确定代码本身没有问题的情况下,这样操作一番即可。
在使用vant-weapp组件库时微信小程序报错-Failed to load font
错误信息是加载vant-weapp组件库中的字体出问题,然后重新装了一次,还是报错。走投无路时打开了vant官方文档,然后发现有这个错误解释:
然后打开微信小程序的文档:
参考原文:https://www.jianshu.com/p/e42627993ce2
页面的颜色其实大多数是一个浅灰色#fafafa,在app.wxss中设置全局,所有的页面颜色都是#fafafa
/**app.wxss**/
page {
background-color: #fafafa;
}
在去app.json设置window属性 "navigationBarBackgroundColor": "#fafafa",
<!--pages/home-music/index.wxml-->
<van-search
background="#000000"
shape="round"
placeholder="搜索您喜欢的歌曲"
/>
最终效果需要将background="000000"(黑色)改成#fafafa
/* pages/home-music/index.wxss */
.van-search__content {
background-color: rgb(180, 57, 57) !important;
}
当原组件中有对样式css的修改方案时我们优先使用官网的方式;
若没有,原组件库的css样式我们需要自行修改,找到原样式的class为van-search__content
修改属性: background-color: rgb(180, 57, 57) !important;(红色),
最终效果图需要修改成:background-color: #fafafa !important;
background-color: rgb(180, 57, 57) !important;
效果图:(暂时)使用红黑配色为了呈现Search搜索框其实有内外颜色,最后效果图要将这两个颜色都改成#fafafa.
<!--pages/home-music/index.wxml-->
<van-search
background="#fafafa"
shape="round"
placeholder="搜索您喜欢的歌曲"
/>
/* pages/home-music/index.wxss */
.van-search__content {
background-color: #fafafa !important;
}
最终效果:
vant-weapp使用文档→Search搜索→API→Props参数中
disabled | 是否禁用输入框 |
vant-weapp使用文档→Search搜索→API→Events中
bind:click-input | 点击搜索区域时触发 |
使用这两个属性的原因,当我们在Search框中点击搜索时,页面会跳转到另一个页面中做搜索,在/pages/home-music/index.wxml这个页面中的Search禁止输入搜索,但又要监听这个搜索框,因此使用点击搜索区域时触发。
<!--pages/home-music/index.wxml-->
<van-search
disabled
background="#fafafa"
shape="round"
placeholder="搜索您喜欢的歌曲"
bind:click-input="handleSearchClick"
/>
// pages/home-music/index.js
Page({
data: {
},
onLoad: function (options) {
},
handleSearchClick:function () {
// console.log("dinaji")
wx.navigateTo({
url: '/pages/detail-search/index',
})
},
onUnload: function () {
}
})
注意:当调试器中报出诸多警告时,原因是小程序的调试基础库在不断更新,更新到一定版本后,对vant-weapp组件库有严格的验证,因此会报出警告。忽略即可
当遇到不懂的警告也可以在github中查
轮播图
需求:轮播图的高度和图片的高度是一致。
问题:图片的高度如何获取。*width→widthFix→height
<!--pages/home-music/index.wxml-->
<!-- 搜索框 -->
<van-search
disabled
background="#fafafa"
shape="round"
placeholder="搜索您喜欢的歌曲"
bind:click-input="handleSearchClick"
/>
<!-- 轮播图 -->
<swiper class="swiper"
indicator-dots
indicator-active-color="#A52A2A"
autoplay >
<block wx:for="{{banners}}" wx:key="bannerId">
<swiper-item class="swiper-item">
<image class="image" src="{{item.pic}}" mode="widthFix"></image>
</swiper-item>
</block>
</swiper>
图片的高度是通过mode="widthFix"的属性根据原图片的宽高比计算得到的。这个时候图片与轮播图的高度是有一点点不一致的
// pages/home-music/index.js
import { getBanners } from '../../service/api_music'
Page({
data: {
banners:[]
},
onLoad: function (options) {
// 获取页面数据
this.getPageData()
},
// 网络请求
getPageData:function() {
getBanners().then(res => {
this.setData({banners:res.banners})
})
},
handleSearchClick:function () {
// console.log("dinaji")
wx.navigateTo({
url: '/pages/detail-search/index',
})
},
onUnload: function () {
}
})
/* pages/home-music/index.wxss */
.van-search__content {
background-color: #fafafa !important;
}
/* 轮播图 */
.swiper {
}
.swiper-item {
display: flex;
}
.swiper-item .image {
width: 100%;
}
说明:轮播图与图片的高度不一致,一般图片底部会超出轮播图3个像素,使用display:flex;使图片尽可能的和轮播图大小合适,但仔细看还是会有点差值,轮播图有固定的高度150px,所以当切换成不同型号的手机(iPhone x 切换 iPhone 5),图片的高度则达不到150px,轮播图的样式会发生改变,这是因为无论手机型号如何改变,轮播图高度固定150px,这时候图和指示点会分家。所以我们要动态设置图片高度,希望轮播图的高度要与图片的高度保持一致,适应各个型号机型。
1.如何获取图片的高度
2.如何将这个高度设置到swiper
如何去获取一张网络图片的高度
1.请求轮播图的数据
2.image src="url字符串"
3.图片加载完成
微信开放文档→组件→媒体组件→image→属性说明
bindload | eventhandle | 否 | 当图片载入完毕时触发,event.detail = {height, width} | 1.0.0 |
说明:event.detail = {height, width}是原图片的大小,而我们在使用它的时候是放在一个容器或者说组件里面,使用css样式来设置原图片适配容器的大小。也就是说在获取图片的高度时也就等同于获取一个容器的高度。
微信开放文档→API→WXML→wx.createSelectorQuery
返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用 this.createSelectorQuery()
来代替。
返回值
SelectorQuery
<!--pages/home-music/index.wxml-->
<!-- 搜索框 -->
<van-search
disabled
background="#fafafa"
shape="round"
placeholder="搜索您喜欢的歌曲"
bind:click-input="handleSearchClick"
/>
<!-- 轮播图 -->
<swiper class="swiper"
indicator-dots
indicator-active-color="#A52A2A"
autoplay
style="height: {{swiperHeight}}px;" >
<block wx:for="{{banners}}" wx:key="bannerId">
<swiper-item class="swiper-item">
<image class="swiper-image"
src="{{item.pic}}"
mode="widthFix"
bindload="handleSwiperImageLoaded">
</image>
</swiper-item>
</block>
</swiper>
// pages/home-music/index.js
import { getBanners } from '../../service/api_music'
Page({
data: {
swiperHeight:0,
banners:[]
},
onLoad: function (options) {
// 获取页面数据
this.getPageData()
},
// 网络请求
getPageData:function() {
getBanners().then(res => {
this.setData({banners:res.banners})
})
},
// 事件处理
handleSearchClick:function () {
// console.log("dinaji")
wx.navigateTo({
url: '/pages/detail-search/index',
})
},
handleSwiperImageLoaded:function(){
// 获取图片的高度(如何去获取某一个组件的高度)
const query = wx.createSelectorQuery()
query.select('.swiper-image').boundingClientRect()
query.exec((res)=> {
const rect = res[0]
this.setData({swiperHeight:rect.height})
})
},
onUnload: function () {
}
})
(掌握)Music页面-查询抽取和节流处理
在utils下创建query-rect.js用来封装一个函数
export default function (selector){
return new Promise((resolve) =>{
const query = wx.createSelectorQuery()
query.select(selector).boundingClientRect()
// query.exec(resolve)
query.exec((res)=> {
resolve(res)
})
})
}
// pages/home-music/index.js
import { getBanners } from '../../service/api_music'
import queryRect from '../../utils/query-rect'
Page({
data: {
swiperHeight:0,
banners:[]
},
onLoad: function (options) {
// 获取页面数据
this.getPageData()
},
// 网络请求
getPageData:function() {
getBanners().then(res => {
this.setData({banners:res.banners})
})
},
// 事件处理
handleSearchClick:function () {
// console.log("dinaji")
wx.navigateTo({
url: '/pages/detail-search/index',
})
},
handleSwiperImageLoaded:function(){
// 获取图片的高度(如何去获取某一个组件的高度)
queryRect(".swiper-image").then (res =>{
const rect = res[0]
this.setData({swiperHeight:rect.height})
})
},
onUnload: function () {
}
})
因为每一张轮播图加载完都会触发加载queryRect函数,那么就会浪费掉很多性能,需要使用js高级里面的节流或者抖动。
在utils文件夹下新建throttle.js
//节流函数
export default function throttle(fn, interval = 1000, options = { leading: true, trailing: false }) {
// 1.记录上一次的开始时间
const { leading, trailing, resultCallback } = options
let lastTime = 0
let timer = null
// 2.事件触发时, 真正执行的函数
const _throttle = function(...args) {
return new Promise((resolve, reject) => {
// 2.1.获取当前事件触发时的时间
const nowTime = new Date().getTime()
if (!lastTime && !leading) lastTime = nowTime
// 2.2.使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数
const remainTime = interval - (nowTime - lastTime)
if (remainTime <= 0) {
if (timer) {
clearTimeout(timer)
timer = null
}
// 2.3.真正触发函数
const result = fn.apply(this, args)
if (resultCallback) resultCallback(result)
resolve(result)
// 2.4.保留上次触发的时间
lastTime = nowTime
return
}
if (trailing && !timer) {
timer = setTimeout(() => {
timer = null
lastTime = !leading ? 0: new Date().getTime()
const result = fn.apply(this, args)
if (resultCallback) resultCallback(result)
resolve(result)
}, remainTime)
}
})
}
_throttle.cancel = function() {
if(timer) clearTimeout(timer)
timer = null
lastTime = 0
}
return _throttle
}
// pages/home-music/index.js
import { getBanners } from '../../service/api_music'
import queryRect from '../../utils/query-rect'
import throttle from '../../utils/throttle'
const throttleQueryRect = throttle(queryRect,1000)
Page({
data: {
swiperHeight:0,
banners:[]
},
onLoad: function (options) {
// 获取页面数据
this.getPageData()
},
// 网络请求
getPageData:function() {
getBanners().then(res => {
this.setData({banners:res.banners})
})
},
// 事件处理
handleSearchClick:function () {
// console.log("dinaji")
wx.navigateTo({
url: '/pages/detail-search/index',
})
},
handleSwiperImageLoaded:function(){
// 获取图片的高度(如何去获取某一个组件的高度)
throttleQueryRect(".swiper-image").then (res =>{
console.log("查询到了结果")
const rect = res[0]
this.setData({swiperHeight:rect.height})
})
},
onUnload: function () {
}
})