小程序项目学习--第五章:项目实战一

第五章:项目实战一、

01_(了解)音乐小程序的项目介绍

坑关于Vant Weapp中组件引入未找到的解决方案

[ pages/main-music/main-music.json 文件内容错误] pages/main-music/main-music.json: [“usingComponents”][“van-search”]: “@vant/weapp/search/index” 未找到

小程序构建npm问题:https://blog.csdn.net/weixin_46587302/article/details/118681069

关于Vant Weapp中组件引入未找到的解决方案
npm install

npm i @vant/weapp -S --production

构建npm

 "setting": {
     ...
	"packNpmManually": true,
    "packNpmRelationList": [
      {
        "packageJsonPath": "./package.json",
        "miniprogramNpmDistDir": "./"
      }
    ],
    ...
 }
    

02_(掌握)项目结构搭建和TabBar的页面配置

1.初始化项目结构

image-20230121171151812

2.创建对应文件夹-components–services-assets

image-20230121171409705

3.创建底部tabBar页面–main-muisic 和main-video

image-20230121172317127

3.1自定义页面标题

image-20230124102809321

03_(掌握)视频页面-请求MV列表数据和基本展示

1.做视频页面,需要数据获取列表,数据就需要发送网络请求–封装网络请求–展示页面

之前做过网络封装,这里直接复用之前使用个的网络请求封装,这里使用类封装的请求方法

// 封装成类 -> 实例
import { baseURL } from "./config"

class HYRequest {
  constructor(baseURL) {
    this.baseURL = baseURL
  }
  request(options) {
    const { url } = options
    return new Promise((resolve, reject) => {
      wx.request({
        ...options,
        url: this.baseURL + url,
        success: (res) => {
          resolve(res.data)
        },
        fail: (err) => {
          console.log("err:", err);
        }
      })
    })
  }
  get(options) {
    return this.request({ ...options, method: "get" })
  }
  post(options) {
    return this.request({ ...options, method: "post" })
  }
}

export const hyRequest = new HYRequest("http://codercba.com:9002")

2.发送对应的网络请求

  1. 首先需要存储数据的空数组用来保存数据,显示到页面上
data: {
    // 1.首先需要存储数据的空数组用来保存数据             
    videoList: [],
  }
  1. 引入封装的实例请求方法
// pages/main-video/main-video.js
import { hyRequest } from "../../services/index"
  1. 需要在对应的生命周期中调用实例(onLoad())发送网络请求,使用promise获取请求,将数据放入到data里面
onLoad(){
    // .需要在对应的生命周期中调用实例(onLoad())发送网络请求,使用promise获取请求,将数据放入到data里面
    hyRequest.get({
      url:"/top/mv",
      data:{
        limit:20,
        offset:0
      }
    }).then(res=>{
      // console.log(res);
      this.setData({videoList:res.data})
    })
  }

​ 3.1可以通过调试器中的AppData检验

image-20230124110808691

  1. 对数据遍历(wx:for)进行展示,key需要根据不同的情况进行思考,如果是深层次的key,可以写mustache语法{{}}–
<!--pages/main-video/main-video.wxml-->
<view class="video-list">
  <block wx:for="{{videoList}}" wx:key="id">
      <view>
          <image src="{{item.cover}}"/>
          <view>{{item.name}}</view>
      </view>
  </block>
</view>


  1. 对展示的数据进行布局
2.1,调整每次进入的页面

方式一,通过app.js配置

方式二:更改页面的编译模式–更改启动页面

2.2网络请求时–点击->详情->本地设置->不校验合法域名

04_(掌握)视频页面-网络请求代码的重构和封装

0.对数据发给网络请求,获取数据,对数据进行展示,

1.对应网络请求的数据非常多,每个页面都来管理自己页面的url和参数,如果当前对应的url发生改变,如果写到的书对应页面里面,是不好寻找的,

所以我们会在services文件夹进行模块划分,对请求进行抽取,对网络请求的url地址和参数进行封装,对于页面来说我们只需要发送什么样的请求就行,

里面会对地址和参数进行拼接好,在外部只需要调用对应的方法就行

2.网络分层架构

对应请求视频相关的所有页面我们在services中新建video.js,对应经常变化的参数,让页面传递进来

services->video.js

import { hyRequest } from "./index"

export function getTopMV(offset = 0, limit = 20) {
  return hyRequest.get({
    url: "/top/mv",
    data: {
      limit,
      offset
    }
  })
}

main-video.js

// pages/main-video/main-video.js
// 2.引入封装的实例请求方法
import { getTopMV } from "../../services/video"

Page({
  data: {
    // 1.首先需要存储数据的空数组用来保存数据             
    videoList: [],
  },
  onLoad(){
    // 3.需要在对应的生命周期中调用实例(onLoad())发送网络请求,使用promise获取请求,将数据放入到data里面
   getTopMV().then(res=>{
      // console.log(res);
      this.setData({videoList:res.data})
    })
  }
})

3.我们发送网络请求的代码写在onLoad里面,但是我们不希望我们的代码是promise情况,我们希望是async 和await,但是如果是async 和await是同步,会阻塞直到前面代码执行,才会继续执行,会操成后续代码不会执行,如果我们对代码进行封装,也会方便后续对代码的复用

使用我们并不会将完全请求的代码放到onLoad里面,而是封装一个函数,然后再onLoad中调用封装的方法

// pages/main-video/main-video.js
// 2.引入封装的实例请求方法
import { getTopMV } from "../../services/video"

Page({
  data: {
    // 1.首先需要存储数据的空数组用来保存数据             
    videoList: [],
  },
  onLoad(){
    // 发送网络请求
    this.fetchTopMV()
  },
  async fetchTopMV(){
    // 老方法promise
    // getTopMV().then(res=>{
    // this.setData({videoList:res.data})
    // })
    const res = await getTopMV()
    this.setData({videoList:res.data})
  }
})

05_(掌握)视频页面-VideoItem的具体展示过程

image-20230125110959046

1.VideoItem是独立的组件,对组件进行封装,然后进行wx:for循环,给组件传入数据,以列表的形式展示组件

1.1封装组件VideoItem进行封装,和通过properties接收数据

<view>
  <image src="{{itemData.cover}}"></image>
  <view>{{itemData.name}}</view>
</view>


// components/video-item/video-item.js
Component({
//  组件的属性列表
  properties: {
    itemData:{
      type:Object,
      value:{}
    }
  },
})

1.2向组件传递数据 {{item}}

<view class="video-list">
  <block wx:for="{{videoList}}" wx:key="id">
    <video-item   itemData="{{item}}"></video-item>
  </block>
</view>

1.3使用组件需要进行注册

 "usingComponents": {
    "video-item": "/components/video-item/video-item"
  }

2.对组件进行结构和布局

pages/main-video

/* pages/main-video/main-video.wxss */
.video-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
  padding: 0 10rpx;
}

.video-list .item {
  width: 48%;
}

<!--pages/main-video/main-video.wxml-->
<view class="video-list">
  <block wx:for="{{videoList}}" wx:key="id">
    <video-item 
      class="item" 
      itemData="{{item}}"
      bindtap="onVideoItemTap"
      data-item="{{item}}"
    />
  </block>
</view>

video-item

<!--components/video-item/video-item.wxml-->
<wxs src="/utils/format.wxs" module="fmt"></wxs>
<view class="item" bindtap="onItemTap">
  <view class="album">
    <image class="image" mode="widthFix" src="{{itemData.cover}}"></image>
    <view class="info">
      <view class="count">{{fmt.formatCount(itemData.playCount)}}</view>
      <view class="duration">{{fmt.formatTime(itemData.mv.videos[0].duration)}}</view>
    </view>
  </view>
  <view class="content">{{itemData.name}} - {{itemData.artistName}}</view>
</view>

样式省略... 

3.细节处理–对数字进行格式化(封装–通过utils–》wxs)

format.wxs -->在wxml中使用 wxs

// 对count进行格式化
function formatCount(count) {
  count = Number(count)
  if (count >= 100000000) {
    return (count / 100000000).toFixed(1) + "亿"
  } else if (count >= 10000) {
    return (count / 10000).toFixed(1) + "万"
  } else {
    return count
  }
}

// 2 -> 02
// 24 -> 24
function padLeft(time) {
  time = time + ""
  return ("00" + time).slice(time.length)
}

// 对time进行格式化
// 100 -> 01:40
function formatTime(time) {
  // 0.将毫秒转成秒
  time = time / 1000

  // 1.获取时间
  var minute = Math.floor(time / 60)
  var second = Math.floor(time) % 60

  // 2.拼接字符串
  return padLeft(minute) + ":" + padLeft(second)
}

// 必须导出后, 才能被其他地方调用: 必须使用CommonJS导出
module.exports = {
  formatCount: formatCount,
  formatTime: formatTime
}

06_(掌握)视频页面-上拉加载更多的功能实现

目前的局限->展示数据只能展示20条数据,我们需要实现上拉加载更多

逻辑分析: 我们需要记录之前的数据偏移了多少,在请求偏移的最新的20条数据

我们通过在data中offset记录偏移,再次发送网络请求的时候对offset进行修改,并且将新的数据追加到原来数据的后面

但是我们的数据可能请求完,我们可以通过hasMore变量来记录是否还有更多数据

// pages/main-video/main-video.js
// 2.引入封装的实例请求方法
import { getTopMV } from "../../services/video"

Page({
  data: {
    videoList: [],
    offset: 0,
    hasMore: true
  },

  onLoad() {
    // 发送网络请求 
    this.fetchTopMV()
  },

  // =================  发送网络请求的方法 =================  
  async fetchTopMV() {
    // getTopMV().then(res => {
    //   this.setData({ videoList: res.data })
    // })
    // 1.获取数据
    const res = await getTopMV(this.data.offset)

    // 2.将新的数据追加到原来数据的后面
    const newVideoList = [...this.data.videoList, ...res.data]

    // 3.设置全新的数据
    this.setData({ videoList: newVideoList })
    this.data.offset = this.data.videoList.length
    this.data.hasMore = res.hasMore
  },

  // =================  监听上拉和下拉功能  =================  
  onReachBottom() {
    // 1.判断是否有更多的数据
    if (!this.data.hasMore) return

    // 2.如果有更多的数据, 再请求新的数据
    this.fetchTopMV()
  },
  
})

07_(掌握)视频页面-下拉刷新数据的功能实现

1.开启下拉刷新–默认页面没有开启下拉刷新功能 看不见需要在app.json中改变样式

  "enablePullDownRefresh": true,
      
  "window": {
      ...
    "backgroundTextStyle": "dark",
  }

2.监听 清空之前数据 ,重新请求新的数据,停止下拉刷新

方式一:promise方式

在fetchTopMV重新请求到数据的时候通过promise停止下拉刷新

image-20230125125051301

方式二:async/await方式

image-20230125125119596

  async onPullDownRefresh() {
    // 1.清空之前的数据
    this.setData({ videoList: [] })
    this.data.offset = 0
    this.data.hasMore = true

    // 2.重新请求新的数据
    await this.fetchTopMV()

    // 3.停止下拉刷新
    wx.stopPullDownRefresh()
  },

08_(掌握)视频页面-点击Item跳转到详情的方式–detail-video

1.首先创建detail-video页面 ,我们可以通过onLoad中options参数通过 options.id 获取id options就是通过模板字符串中穿过来的值

<text>{{id}}</text>


// pages/detail-video/detail-video.js
Page({
  data: {
    id: 0
  },
  onLoad(options) {
    const id = options.id
    console.log(options);
    this.setData({
      id
    })
  }

})

2.跳转到详情的

方式一:组件的监听点击

通过在组件上 bindtap监听整个组件点击和给组件添加自定义属性用来判断用户点击的是哪个组件

 <video-item 
      class="item" 
      itemData="{{item}}"
      bindtap="onVideoItemTap"
      data-item="{{item}}"
    />
          
  // =================  界面事件监听的方法 =================  
  onVideoItemTap(event) {
    // const item = event.currentTarget.dataset.item
    // wx.navigateTo({
    //   url: `/pages/detail-video/detail-video?id=${item.id}`,
    // })
  }          

方式二:组件内部的监听

在item组件内部根元素,通过bindtap绑定点击事件,在这里跳转不用传参数,可以通过this.properties.itemData

<view class="item" bindtap="onIt emTap">
    
    
  methods: {
    onItemTap() {
      const item = this.properties.itemData
      wx.navigateTo({
        url: `/pages/detail-video/detail-video?id=${item.id}`,
      })
    }
  }

09_(掌握)视频页面-请求视频地址和视频播放

1.请求视频地址和视频播放网络–方法封装

export function getMVUrl(id) {
  return hyRequest.get({
    url: "/mv/url",
 //id 就是options中的id
    data: {
      id
    }
  })
}


2.引入方法和调用请求视频地址数据

// pages/detail-video/detail-video.js
import { getMVUrl } from "../../services/video"

Page({
  data: {
    id: 0,
    mvUrl: "",
  },
  onLoad(options) {
     // 1.获取id
    const id = options.id
    this.setData({id})
     // 2.请求数据
    this.fetchMVUrl()
  },
  async fetchMVUrl() {
    const res = await getMVUrl(this.data.id)
    this.setData({ mvUrl: res.data.url })
  },

})

3.展示数据和设置样式

<!--pages/detail-video/detail-video.wxml-->
<video 
  class="video" 
  src="{{mvUrl}}" 
  danmu-list="{{danmuList}}"
  autoplay />
           

4.弹幕

data: {
  danmuList: [
      { text: "哈哈哈, 真好听", color: "#ff0000", time: 3 },
      { text: "呵呵呵, 不错哦", color: "#ffff00", time: 10 },
      { text: "嘿嘿嘿, 好喜欢", color: "#0000ff", time: 15 },
    ]
}  

10_(掌握)视频页面-请求视频详情和视频推荐的数据

1.请求新数据就需要封装新接口

export function getMVInfo(mvid) {
  return hyRequest.get({
    url: "/mv/detail",
    data: {
      mvid
    }
  })
}

export function getMVRelated(id) {
  return hyRequest.get({
    url: "/related/allvideo",
    data: {
      id
    }
  })
}

2.引入方法和调用请求

import { getMVInfo, getMVRelated } from "../../services/video"
 data: {
	mvInfo: {},
    relatedVideo: [],
 }

  onLoad(options) {
    // 1.获取id
    const id = options.id
    this.setData({ id })

    // 2.请求数据
    this.fetchMVInfo()
    this.fetchMVRelated()
  },
      
async fetchMVInfo() {
    const res = await getMVInfo(this.data.id)
    this.setData({ mvInfo: res.data })
  },
  async fetchMVRelated() {
    const res = await getMVRelated(this.data.id)
    this.setData({ relatedVideo: res.data })
  }
      

3.展示数据和设置样式

<scroll-view class="content" scroll-y>
  <view class="info">
    <view>{{ mvInfo.artistName }}</view>
  </view>

  <view class="related-video">
    <block wx:for="{{relatedVideo}}" wx:key="vid">
      <view class="item">
        <image src="{{item.coverUrl}}" mode="widthFix"></image>
        <view>{{item.title}}</view>
      </view>
    </block>
  </view>
</scroll-view>

/* pages/detail-video/detail-video.wxss */
page {
  height: 100vh;
}

.video {
  width: 100%;
  /* position: fixed;
  top: 0;
  left: 0; */
}

.content {
  /* margin-top: 225px; */
  /* height: 300px; */
  height: calc(100% - 225px);
}

11_(掌握)视频页面-内容的滚动方案实现和对比

方案一:通过样式调整

/* pages/detail-video/detail-video.wxss */

.video {
  width: 100%;
  /* 会脱离标准流,跑到上面去 */
  /* position: fixed;
  top: 0;
  left: 0; */
}

.content {
  /* margin-top: 225px; */
  /* height: 300px; */
  height: calc(100% - 225px);
}

方案二:使用组件scroll-view

<scroll-view class="content" scroll-y>
  <view class="info">
    <view>{{ mvInfo.artistName }}</view>
  </view>

  <view class="related-video">
    <block wx:for="{{relatedVideo}}" wx:key="vid">
      <view class="item">
        <image src="{{item.coverUrl}}" mode="widthFix"></image>
        <view>{{item.title}}</view>
      </view>
    </block>
  </view>
</scroll-view>  
/* pages/detail-video/detail-video.wxss */
page {
  height: 100vh;
}

.video {
  width: 100%;
  /* 会脱离标准流,跑到上面去 */
  /* position: fixed;
  top: 0;
  left: 0; */
}

.content {
  /* margin-top: 225px; */
  /* height: 300px; */
  height: calc(100% - 225px);
}

第五章:音乐界面

12_(掌握)音乐页面-Vant库的安装和使用过程

音乐页面从上到下-

搜索框–第三方组件–vant https://vant-contrib.gitee.io/vant-weapp/#/home

1.安装

小程序新建终端

npm i @vant/weapp

会自动生成package-lock.json 和package.json文件 node_modules

如果没有生成,我们通过命令npm init -y之后在重新安装 npm i @vant/weapp

npm init -y

安装完还是不可以直接使用,因为不是node环境也不是webpack环境,而是小程序自己的环境

我们选择使用npm环境-》工具-》构建npm(每次通过npm下载,都需要重新构建一下)

本质是将安装在node_modules里面的东西构建在miniprogram_npm下面,因为你下载的node_modules里面的东西默认不会从中寻找,而是从miniprogram_npm下面寻找

image-20230126104023995

2.注册

在使用的页面中的json文件中

 "usingComponents": {
    "van-search": "@vant/weapp/search/index",
 }

3.使用

在使用的页面wxml中使用

<van-search
  value="{{ searchValue }}"
  shape="round"
  background="#fafafa"
  placeholder="请输入搜索关键词"
  bind:click-input="onSearchClick"
/>

image-20230126105046902

13_(掌握)音乐页面-搜索框搭建和点击搜索框的跳转

1.

1.引入组件

  "usingComponents": {
    "van-search": "@vant/weapp/search/index",
  }

2.设置样式

"navigationBarBackgroundColor": "#fafafa",

<van-search
  value="{{ searchValue }}"
  shape="round" 
  background="#fafafa"
  placeholder="请输入搜索关键词"
  bind:click-input="onSearchClick"
/>    
    
page {
  --search-background-color: #fff;
  --search-padding: 10px 0;

  box-sizing: border-box;
  padding: 0 24rpx;
  background-color: #fafafa;
}

2.

覆盖元素背景样式的方法

image-20230126160031083

方式一 获取class,重写

/* .van-search__content {
  background-color: #fff !important;
} */

方式二:修改变量

--search-background-color: #fff;

3.

vant 2.18.1之后出现的警告,不是错误

image-20230126160223341

解决

方式一:修改源码

方式二: 使用低版本的基础库(但是新功能使用不了,但是适配能力越强)

使用2.18.0在 project.config.json 修改

 "libVersion": "2.18.0",

4.点击搜索框进入搜索页面

创建页面detail-search

<!--pages/detail-search/detail-search.wxml-->
<text>pages/detail-search/detail-search.wxml</text>

绑定点击事件

<!--pages/main-music/main-music.wxml-->
<van-search
  value="{{ searchValue }}"
  shape="round" 
  background="#fafafa"
  placeholder="请输入搜索关键词"
  bind:click-input="onSearchClick"
/>    

书写方法

// pages/main-music/main-music.js
Page({
  data: {
    searchValue: "",
  },
  
  // 界面的事件监听方法
  onSearchClick() {
    wx.navigateTo({url: '/pages/detail-search/detail-search'})
  },
})

14_(掌握)音乐页面-请求轮播图数据和效果展示

轮播图的实现步骤

从服务器中获取数据 -》将数据放到data里面-》通过for循环进行展示

1.请求对应数据->创建对应文件-》封装请求方法

music.js

import { hyRequest } from "./index"


export function getMusicBanner(type = 0) {
  return hyRequest.get({
    url: "/banner",
    data: {
      type
    }
  })
}

2.对应请求逻辑

import { getMusicBanner } from "../../services/music"

data:{  
  banners: [],
}onLoad() {
    this.fetchMusicBanner()
}   
// 网络请求的方法封装
async fetchMusicBanner() {
    const res = await getMusicBanner()
    this.setData({ banners: res.banners })
 },  

3.轮播图的展示

<!-- 2.轮播图的展示 -->
<swiper 
  class="banner"
  circular
  indicator-dots
  style="height: {{bannerHeight}}px;"
  wx:if="{{banners.length}}"
>
  <block wx:for="{{banners}}" wx:key="targetId">
    <swiper-item class="item">
      <image 
        class="banner-image" 
        src="{{item.imageUrl}}" 
        mode="widthFix"
        bindload="onBannerImageLoad"
      />
    </swiper-item>
  </block>
</swiper>

15_(掌握)音乐页面-页面内边距和轮播图的基本样式

给整个页面设置内边距=》针对于不需要设置内边距的地方,我们撑开就行

/* pages/main-music/main-music.wxss */
page {
  --search-background-color: #fff;
  --search-padding: 10px 0;

  box-sizing: border-box;
  padding: 0 24rpx;
  background-color: #fafafa;
}

/* .van-search__content {
  background-color: #fff !important;
} */

/* 轮播图的样式 */
.banner {
  border-radius: 12rpx;
  overflow: hidden;
  /* height: 260rpx; */
}

.banner-image {
  width: 100%;
}

16_(掌握)音乐页面-轮播图的高度计算和节流函数

轮播图默认高度(150px)有问题,我们的目标是轮播图的高度和图片的高度保持一致,

所以我们需要监听图片什么时候加载完毕,加载完获取组件高度,把image组件的高度设置为swiper高度

获取image组件高度需要一个新的api,我们需要进行封装到工具里面,通过promise进行回调,获取结果

但是发现执行的太频繁,所以我们使用节流函数进行优化

1.动态设置高度

mode=“widthFix” 会导致图标在下面,设置固定高度,其他机型又会出现问题,其他模式也有各种问题

如何设置动态高度呢,通过插值语法,根据图片的高度动态设置

<swiper 
  class="banner"
  circular
  indicator-dots
  style="height: {{bannerHeight}}px;"
  wx:if="{{banners.length}}"
>
  <block wx:for="{{banners}}" wx:key="targetId">
    <swiper-item class="item">
      <image 
        class="banner-image" 
        src="{{item.imageUrl}}" 
        mode="widthFix"
        bindload="onBannerImageLoad"
      />
    </swiper-item>
  </block>
</swiper>


import querySelect from "../../utils/query-select"
            
 bannerHeight: 0,
     
  onBannerImageLoad(event) {
    querySelect(".banner-image").then(res => {
      this.setData({ bannerHeight: res[0].height })
    })
  },     

image里面有bindload事件,图片加载完成会执行该事件,在事件中获取Image组件的高度(对这个方法进行封装)

export default function querySelect(selector) {
  return new Promise(resolve => {
    const query = wx.createSelectorQuery()
    query.select(selector).boundingClientRect()
    query.exec((res) => {
      resolve(res)
    })
  })
}

2.节流

但是会调用八次,这里我们使用节流来进行优化

0.封装

export default function hythrottle(fn, interval = 200, { leading = true, trailing = false } = {}) {
  let startTime = 0
  let timer = null

  const _throttle = function(...args) {
    return new Promise((resolve, reject) => {
      try {
         // 1.获取当前时间
        const nowTime = new Date().getTime()

        // 对立即执行进行控制
        if (!leading && startTime === 0) {
          startTime = nowTime
        }

        // 2.计算需要等待的时间执行函数
        const waitTime = interval - (nowTime - startTime)
        if (waitTime <= 0) {
          // console.log("执行操作fn")
          if (timer) clearTimeout(timer)
          const res = fn.apply(this, args)
          resolve(res)
          startTime = nowTime
          timer = null
          return
        } 

        // 3.判断是否需要执行尾部
        if (trailing && !timer) {
          timer = setTimeout(() => {
            // console.log("执行timer")
            const res = fn.apply(this, args)
            resolve(res)
            startTime = new Date().getTime()
            timer = null
          }, waitTime);
        }
      } catch (error) {
        reject(error)
      }
    })
  }

  _throttle.cancel = function() {
    if (timer) clearTimeout(timer)
    startTime = 0
    timer = null
  }

  return _throttle
}

1.引入

import throttle  from '../../utils/throttle'

2.使用

const querySelectThrottle = throttle(querySelect, 100)

 // 图片加载完毕调用函数,设置高度
  onBannerImageLoad(event) {
    querySelectThrottle(".banner-image").then(res => {
      this.setData({ bannerHeight: res[0].height })
    })
  },  

17_(掌握)音乐页面-underscore库中节流函数使用

1.安装

npm install underscore

2.构建

工具-》构建npm

3.使用

import {throttle}  from 'underscore'

const querySelectThrottle = throttle(querySelect, 100)

18_(掌握)音乐页面-区域头部area-header的封装

自定义area-header头部组件

1.创建组件页面

2.注册、使用

 "usingComponents": { 
"area-header": "/components/area-header/area-header",
 }

<!-- 3.推荐歌曲的展示 -->
<view class="recommend">
  <area-header title="推荐歌曲" bind:moreclick="onRecommendMoreClick"/>
</view>


接收子组件传过来的点击事件进行处理
onRecommendMoreClick() {
   console.log(111)
  },

3.组件封装

// components/area-header/area-header.js
Component({
  properties: {
    title: {
      type: String,
      value: "默认标题"
    },
    hasMore: {
      type: Boolean,
      value: true
    }
  },
  methods: {
    onMoreTap() {
      // 将更多的点击事件传递出去
      this.triggerEvent("moreclick")
    }
  }
})

{
  "component": true,
  "usingComponents": {
    "van-icon": "@vant/weapp/icon/index"
  }
}

<!--components/area-header/area-header.wxml-->
<view class="header">
  <view class="title">{{title}}</view>
  <view class="more" wx:if="{{hasMore}}" bindtap="onMoreTap">
    <text class="text">更多</text>
    <van-icon name="arrow" />
  </view>
</view>

/* components/area-header/area-header.wxss */
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 32rpx 0;
}

.header .title {
  font-size: 36rpx;
  font-weight: 700;
  color: #000;
}

.header .more {
  display: flex;
  align-items: center;
  font-size: 36rpx;
  color: #888;
}

.header .more .text {
  font-size: 28rpx;
}

19_(理解)内容回顾和作业布置

第五章:内容回顾

一. 项目的搭建

1.1. 创建一个新项目

1.2. 创建项目目录结构

1.3. 搭建tabBar页面

二. 视频页面

2.1. 请求基本数据和展示

  • 网络请求进行分层结构
  • Promise -> await/async

2.2. 上拉加载更多功能

  • 监听滚到到底部
  • 加载更多的数据
    • offset
    • […this.data.videoList, …res.data]
    • hasMore

2.3. 下拉刷新的功能

  • 开启下拉刷新
  • 监听下拉刷新
  • 重置变量
    • offset = 0
    • videoList = []
    • hasMore = true
  • 请求结束后, 结束下拉刷新

三. 视频详情

3.1. 点击Item跳转到详情

  • video-item组件的监听点击
    • data-
  • video-item组件的内部监听
    • this.properties.itemData

3.2. 获取播放地址Video

  • 获取播放地址
  • 使用video组件播放

3.3. 获取详情的其他数据

  • MV详情
  • MV关联推荐视频

3.4. 滚动的页面展示

  • page滚动
  • scroll-view滚动

四. 音乐页面

4.1. 搜索框的展示

  • 安装vant

    • npm install @vant/weapp
    • 构建npm
  • 演练vant的使用

  • 搭建搜索框

    • 设置属性
    • 监听点击, 跳转搜索页面
  • 重要: 覆盖vant样式

    • CSS属性
    • CSS变量

4.2. 轮播图的展示

4.2.1. 请求轮播数据和基本展示
4.2.2. 轮播图的基本样式调整
  • 页面的内边距
  • 轮播图的圆角

DFS

4.2.3. 轮播图的动态计算
  • 根据加载出来的图片, 计算轮播图的高度
  • querySelect
  • 对方法调用进行节流操作

4.3. area-header的封装

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值