uniapp actual imitation of Netease cloud music (2) - encapsulation of promise interface request and realization of homepage function, component encapsulation, configuration pull-down refresh

foreword

This article continues to complete the part of the previous article, mainly to realize the encapsulation of the proromise interface and the realization of the main entrance of the home page

encapsulation of promise request interface

In the previous article, we requested that we write like this:

methods: {
    
    
	getBanner() {
    
    
		uni.request({
    
    
			url: 'http://localhost:3000/banner',
			method: 'GET',
			success:(res)=>{
    
    
				this.swiper = res.data.banners;
			}
		})
	}
}

But in actual development, there are many interfaces, which is inconvenient to manage, so we usually encapsulate the interfaces.
First, create a new request.js file in the util folder, and encapsulate the promise in the file:
insert image description here

The status code in the package is written according to the actual situation. I wrote a few simple ones here.

/**
 * 请求组件封装
 * @param {Object} url 请求地址 /banner
 * @param {Object} data 请求参数
 * @param {Object} method 请求的方法
 * @param {Object} contentType 请求内容类型 1=json  2=form
 */
function request({
    
    url, data, method="GET", contentType=1}) {
    
    
	let header = {
    
    
		'content-type': contentType === 1 ? 'application/json' : 'application/x-www-form-urlencoded'
	}
	let baseUrl = "http://localhost:3000";
	
	return new Promise((resolve, reject)=>{
    
    
		uni.request({
    
    
			url: baseUrl + url,
			data,
			method,
			header,
			success: (res) => {
    
    
				if (res.statusCode === 200) {
    
    
					//请求成功
					resolve(res.data);
				} else if (res.statusCode === 401) {
    
    
					uni.showToast({
    
    
						icon: 'none',
						title: "未登录或登录状态已超时",
						duration: 1500
					});
				} else if (res.statusCode === 405) {
    
    
					uni.showToast({
    
    
						icon: 'none',
						title: "请求方法错误",
						duration: 1500
					});
				} else {
    
    
					uni.showToast({
    
    
						icon: 'none',
						title: "请求错误:" + res.statusCode,
						duration: 1500
					});
				}
			},
			fail: (err) => {
    
    
				console.log("err:", err)
				uni.showToast({
    
    
					icon: 'none',
					title: err.errMsg,
					duration: 1500
				});
				reject(err);
			}
		})
	})
}
export default {
    
    request}

Then we can create a new api folder and create a new index.js file to encapsulate the api in it
insert image description here

import request from "@/utils/request.js"

//轮播请求接口
export function apiGetBanner(data) {
    
    
	return request.request({
    
    
		url: '/banner',
		method: 'GET',
		data
	})
}

After encapsulation, the page we need can be directly introduced into the API for use, for example:

<script>
	import {
    
    apiGetBanner} from '@/apis/index.js',
	data() {
    
    
			return {
    
    
				swiper: [],                    //轮播
			}
		},
	methods: {
    
    
			getBanner() {
    
    
				apiGetBanner().then(res => {
    
    
					this.swiper = res.banners;
				})
			},
	}
</script>

Implementation of the main entry function:

Let’s implement the content of this part. The main entrance part of the home page
insert image description here
will basically not change the content of this part, so it is written directly in the image style.
This is mainly to render the local image. It is very simple to use the flex layout for the css part.

<view class="main-bar flex-box">
	<view class="flex-item" v-for="(item,index) in contentBar" :key="index">
		<image :src="'../../static/image/index/t_'+(index+1)+'.png'" class="img"></image>
		<view>
			{
   
   {item.name}}
		</view>
	</view>
</view>

Recommended song list module

The recommended song list is directly extracted into a component for writing
insert image description here
. Create a new file under the components folder to write the component of the song list

insert image description here
I won’t post the css style, the main thing is to write the component well, and then define props to accept the value passed from the parent component

<template>
	<view class="song-list-comp">
		<view class="tit-bar">
			{
    
    {
    
    title}}
			<navigator :url="link" class="more fr">
				歌单广场
			</navigator>
		</view>
		<scroll-view class="scroll-view" scroll-x>
			<view class="item" v-for="(item,index) in list" :key="index">
				<image class="img" :src="item.picUrl" mode=""></image>
				<view class="desc ellipsis">
					{
    
    {
    
    item.name}}
				</view>
				<view class="count">
					{
    
    {
    
    item.playCount}}
				</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	export default {
    
    
		props: {
    
    
			title: {
    
    
				type: String,
				default: ''
			},
			link: {
    
    
				type: String,
				default: ''
			},
			list: {
    
    
				type: Array,
				default: []
			}
		}
	}
</script>

In parent component:

<song-list title="推荐歌单" link="" :list="recommendSongs"></song-list>

Make a data request, here you need to format the playback volume in the requested data

//推荐歌单
getRecommendSongs(){
    
    
	const params = {
    
    
		limit: 6
	}
	apiGetRecommendSongs(params).then(res => {
    
    
		//格式化播放量数据
		const formatCount = data=>{
    
    
			let tmp = data;
			if (data > 10000) {
    
    
				tmp = (parseInt(data/10000) + '万');
			}
			return tmp
		}
		this.recommendSongs = res.result;
		//格式化
		this.recommendSongs.forEach(item => {
    
    
			item.playCount = formatCount(item.playCount);
		})
	})
},

New disc new song module

This piece needs to achieve an effect that can be clicked and switched:
insert image description here

<!-- 新碟新歌 -->
<view class="song-list">
	<view class="switch-line flex-box">
			<view class="flex-box">
				<view class="switch-item" :class="{on : newType==1}" @click="switchTab(1)">
					新碟
				</view>
				<view class="switch-item" :class="{on : newType==2}" @click="switchTab(2)">
					新歌
				</view>
			</view>
			<template v-if="newType==1">
				<view class="more">
					更多新碟
				</view>
			</template>
			<template v-if="newType==2">
				<view class="more">
					更多新歌
				</view>
			</template>
	</view>
	<scroll-view class="scroll-view" scroll-x>
		<view class="item" v-for="(item,index) in latestAlbum" :key="index">
			<image class="img" :src="item.picUrl"></image>
			<view class="desc ellipsis">
				{
   
   {item.name}}
			</view>
			<view class="desc ellipsis c9">
				{
   
   {item.artist.name}}
			</view>
		</view>
	</scroll-view>
</view>

Here is to judge whether it is a new song or a new disc by clicking to switch, and then request data

// 切换新碟新歌
switchTab(type) {
    
    
	this.newType = type;
	// 设定开始start和结束end的位置
	let temp = {
    
    
		s: type == 1 ? 0 : 3,                  
		e: type == 1 ? 3 : 6
	}
	this.latestAlbum = this.latestTempAlbum.slice(temp.s, temp.e);
},
//新碟新歌  把前3首歌--新碟  后3首--新歌
getLatestAlbum() {
    
    
	apiGetTopAlbum().then(res=>{
    
    
		//将所有的数据暂存在临时变量中
		this.latestTempAlbum = res.albums;
		//取前3个作为第一类的数据展示
		this.latestAlbum = res.albums.slice(0, 3);
	})
},

Featured Video Module

This video has temporarily made a cover, without the video playback function, and directly renders the cover:
insert image description here

<!-- 精选视频 -->
<view class="video-list song-list">
	<view class="tit-bar">
		精选视频
		<view class="more fr">
			更多
		</view>
	</view>
	<view class="video-item" v-for="(item, index) in relatedVideo" :key="index">
		<image :src="item.coverUrl" mode="" class="img"></image>
		<view class="desc ellipsis">
			{
   
   {item.title}}
		</view>
	</view>
</view>
//精选视频
			getRelatedVideo() {
    
    
				const params = {
    
    
					id: 32154      //根据资源id查询
				}
				apiGetRelatedVideo(params).then(res=>{
    
    
					// console.log(res)
					this.relatedVideo = res.data;
				})
			}

Pull-to-refresh configuration

To implement pull-down refresh, you only need to configure the enablePullDownRefresh property in page.json:

insert image description here
Then configure the refresh in the life cycle of the home page:

// 刷新后等待1s后关闭
onPullDownRefresh() {
    
    
	console.log("page refresh.");
	setTimeout(function () {
    
    
	    uni.stopPullDownRefresh();
	}, 1000);
},

Effect:
insert image description here

at last

At this point, the home page is basically realized,
insert image description here
and other pages will continue to be completed and updated continuously. If you are interested, you can subscribe to this column

insert image description here

Guess you like

Origin blog.csdn.net/weixin_45745641/article/details/128287030