3-HYMusic状态管理方案.mp4

发布于:2023-01-23 ⋅ 阅读:(459) ⋅ 点赞:(0)

掌握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 () {

    }
})

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到