学习uni-app心得

系列文章目录


前言

随着开发工具的不断发展,小程序开发框架,App跨平台框架,H5开发框架 uni-app的优势越来越明显。

一、uni-app是什么?

        uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序、快应用等多个平台。

        uni-app在手,做啥都不愁。即使不跨端,uni-app也是更好的小程序开发框架(详见)、更好的App跨平台框架、更方便的H5开发框架。不管领导安排什么样的项目,你都可以快速交付,不需要转换开发思维、不需要更改开发习惯。

二、uni-app的优点

1. 跨平台开发:

        使用uni-app可以一次开发,多端部署,支持编译到H5、小程序、App和桌面应用等多个平台,减少了开发成本和工作量。

2. 良好的性能:

        uni-app采用原生渲染方式,性能优越,用户体验好。

3. 组件丰富:

uni-app内置了丰富的组件和模板,可以快速开发出高质量的应用。

4. 易于学习和使用:

        uni-app采用Vue.js框架,对于熟悉Vue.js的开发者来说,很容易上手。

5. 多人协作便捷:

        基于Git的版本控制系统可以使多人协作变得更加便捷。

6. 生态系统完善:

        uni-app有丰富的社区和生态系统,可以轻松解决开发过程中的问题。

7. 适用范围广泛:

        uni-app适用于开发各种类型的应用,包括商城、社交、新闻、游戏等。

三、实际项目经验

1. 提高开发效率和代码复用性:

        由于 uni-app 支持多个平台的开发,因此可以大大减少开发人员的工作量,提高开发效率。

2. 优化性能和用户体验:

        uni-app 应用可以兼容在多个平台上,可以通过混合原生应用和 Web 应用来提高应用的性能和用户体验。

3. 统一UI风格和设计语言:

        由于uni-app开发可以同时适用于多个平台,因此对于 UI 风格和设计语言也有一定程度的统一性。

4. 快速迭代和发布:

        由于 uni-app 可以同时适用于多个平台,因此可以快速迭代,提高应用的更新速度,同时也可以快速发布,在各个平台上进行推广。

四、近期开发的uni-app项目

1. UAMusic音乐项目

1.apk的封装

export const baseUrl ="https://flask-web-frak-shishn-kvmjsphrif.cn-shenzhen.fcapp.run";
export function topList() {
	return new Promise(function(resolve,reject){
		uni.request({
			url: `${baseUrl}/toplist/detail`,
			method: 'GET',
			data: {},
			success: res => {
				let result = res.data.list;
				resolve(result.splice(0,4));
			},
			fail: (err) => {
				console.log(err);
			},
			complete: () => {}
		});
	});
}

export function list(listId) {
	return uni.request({
		url: `${baseUrl}/playlist/detail?id=${listId}`,
		method: 'GET'
	})
}

export function songDetail(id) {  //获取歌曲详情,包括歌名、艺人、图片等
	return uni.request({
		url: `${baseUrl}/song/detail?ids=${id}`,
		method: 'GET'
	})
}

export function songUrl(id) {  //获取歌曲音频的url
	return uni.request({
		url: `${baseUrl}/song/url?id=${id}`,
		method: 'GET'
	})
}

export function songLyric(id) {  //获取歌词内容
	return uni.request({
		url: `${baseUrl}/lyric?id=${id}`,
		method: 'GET'
	})
}

export function searchHot() {  
	return uni.request({
		url: `${baseUrl}/search/hot/detail`,
		method: 'GET'
	})
}


export function searchWord(word) {  
	return uni.request({
		url: `${baseUrl}/search?keywords=${word}`,
		method: 'GET'
	})
}


export function searchSuggest(word) {  
	return uni.request({
		url: `${baseUrl}/search/suggest?keywords=${word}&type=mobile`,
		method: 'GET'
	})
}

2.首页

 

<template>

	<view class="content">

		<uamhead :title="title"></uamhead>
		<!-- <image class="logo" src="/static/logo2.png"></image> -->
		<view class="text-area">
		</view>
		<view>
			 <input  class="ss" @tap="search()" type="button" value="搜索音乐">
		</view>
		<view class="index-list">

			<view class="index-list-ite" v-for="(item,index) in playlist" :key="index" @tap="handleToList(item.id)">
				<view>
					<image :src="item.coverImgUrl" mode=""></image>
					<text class="listtext">{{item.updateFrequency}}</text>
				</view>
				<view class="listlist">
					<text v-for="(i,index) in item.tracks">{{index+1}}.{{i.first}}-{{i.second}}</text>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import {
		topList
	} from "../../common/api.js"
	// const topListData = require('@/static/data/toplist.json')
	import mForSkeleton from "@/components/m-for-skeleton/m-for-skeleton";
	import uamhead from "../../components/uamhead/uamhead.vue";
	
	export default {
		components: {
			mForSkeleton
		},
		data() {
			return {
				// playlist: topListData,
				playlist: [],
				title: 'UAMusic-lyh',
				loading: true
			}
		},
		onLoad() {
			topList().then((res) => {
				if (res.length) {
					setTimeout(() => {
						this.playlist = res;
						this.logding = false
					}, 100);
					// console.log(res);
				}
			});
		},
		methods: {
			handleToList(id) {
				uni.navigateTo({
					url: '/pages/list/list?id=' + id
				});
			},
			search(){
				uni.navigateTo({
					url: '/pages/search/search?' 
				});
			},
			hide() {
				this.loading = false;
			}


		}
	}
</script>

 

 

3. 歌单

<template>

	<view>
		<!-- <uamhead :title="title"></uamhead> -->



		<view class="toubu">
			<view class="gdtext">歌单</view>
			<view class="gd">
				<view class="bd">
					<text>{{playlist.playCount}}</text>
					<img :src="playlist.coverImgUrl" alt="">
				</view>
				<view class="bd2">
					<text>{{title}}</text>
					<view>{{playlist.description}}</view>
				</view>
			</view>
		</view>

		<view class="zb">
			<view class="zb1">
				<img class="bfq" src="../../static/image/播放 (2).jpg" alt="">播放全部(共{{playlist.trackCount}}首)
			</view>

			<view class="gq" @tap="navList(item.id)" v-for="(item,index) in playlist.tracks" :key="index">
				<text class="gqxh">{{index+1}}</text>
				<view>{{item.name}}
					<view class="ym">
						<img class="sq" src="../../static/image/sq.png" alt="">
						<text v-for="(i,index) in item.ar" :key="index">{{i.name}}/</text>
					</view>
				</view>
				
				<view class="gqtp"  @tap="navList(item.id)" ><img class="bfq" src="../../static/image/播放 (1).png" alt=""></view>
			</view>

		</view>
	</view>
</template>

<script>
	import {
		list
	} from "../../common/api.js"
	export default {
		data() {
			return {
				// id:"",
				title: "榜单列表",
				playlist: [],
				privileges: [],
				isShow: [],
				title: [],
				gm: []
			}
		},
		onLoad(options) {

			let listId = options.id;

			console.log(listId);
			list(listId).then((res) => {
				this.playlist = res.data.playlist;
				this.title = res.data.playlist.name;
				console.log(res.data.playlist.tracks[0].id);

				this.gm = res.data.playlist.tracks;
				// this.privileges = res.data.playlist.tracks[0].ar[0].name;
				// console.log(res.data.playlist.tracks);


			});
		},
		methods: {
			navList(listId){
				uni.navigateTo({
					url:'/pages/player/player?id='+listId
					});
			}
		}
	}
</script>

 

 3.播放器

<template>
	<view>
	
		<view class="content">
			<view class="player">
				<image :class="{ 'run': isplayrotate }" :src="song.picUrl" mode=""></image>
				<svg v-if="!isplayrotate" @tap="playing" t="1680513087859" class="icon" viewBox="0 0 1024 1024"
					version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7556" width="50" height="50">
					<path
						d="M512 37.888C251.2384 37.888 37.888 251.2896 37.888 512s213.3504 474.112 474.112 474.112 474.112-213.3504 474.112-474.112S772.7104 37.888 512 37.888z m0 908.6976c-239.0016 0-434.5856-195.584-434.5856-434.5856 0-239.0016 195.584-434.5856 434.5856-434.5856 239.0016 0 434.5856 195.584 434.5856 434.5856 0 239.0016-195.584 434.5856-434.5856 434.5856z"
						p-id="7557" fill="#ffffff"></path>
					<path
						d="M660.736 444.416L499.2 338.944c-54.528-35.84-100.9664-11.9296-100.9664 53.7088v238.592c0 65.6384 44.3904 89.4976 100.9664 53.7088l161.536-105.3696c54.528-39.7824 54.528-99.4304 0-135.2704z"
						p-id="7558" fill="#ffffff"></path>
				</svg>
				<svg v-else @tap="paused" t="1680509815568" class="icon" viewBox="0 0 1024 1024" version="1.1"
					xmlns="http://www.w3.org/2000/svg" p-id="6297" width="50" height="50">
					<path
						d="M512 1024C228.266667 1024 0 795.733333 0 512S228.266667 0 512 0s512 228.266667 512 512-228.266667 512-512 512z m0-42.666667c260.266667 0 469.333333-209.066667 469.333333-469.333333S772.266667 42.666667 512 42.666667 42.666667 251.733333 42.666667 512s209.066667 469.333333 469.333333 469.333333z m-106.666667-682.666666c12.8 0 21.333333 8.533333 21.333334 21.333333v384c0 12.8-8.533333 21.333333-21.333334 21.333333s-21.333333-8.533333-21.333333-21.333333V320c0-12.8 8.533333-21.333333 21.333333-21.333333z m213.333334 0c12.8 0 21.333333 8.533333 21.333333 21.333333v384c0 12.8-8.533333 21.333333-21.333333 21.333333s-21.333333-8.533333-21.333334-21.333333V320c0-12.8 8.533333-21.333333 21.333334-21.333333z"
						fill="#ffffff" fill-opacity=".9" p-id="6298"></path>
				</svg>
				<view></view>
			</view>
			<scroll-view class="lyric" scroll-y="true">

				<view class="wrap" :style="{ transform: 'translateY(' + - (lyricIndex - 1) * 82 + 'rpx)' }">
					<view class="item" :class="{ active: lyricIndex == index }" v-for="(item, index) in song.lyric"
						:key="index">
						{{ item.lyric }}
					</view>
				</view>
			</scroll-view>
			<view class="songtitle">{{ song.author }} : {{ song.name }}</view>
		</view>
	</view>
</template>

<script>
	//
	
	import {
		songDetail,
		songUrl,
		songLyric
	} from "../../common/api.js";
	const innerAudioContext = uni.createInnerAudioContext();
	export default {
		data() {
			return {
				title: '黑胶唱片',
				song: {
					id: '',
					author: '',
					name: '',
					picUrl: '',
					url: '',
					lyric: ''
				},
				isplayrotate: false,
				lyricIndex: 0,
				innerAudioContext: null,
			}
		},
		onLoad(options) {
			let sId = options.id;
			console.log(sId);
			songDetail(sId).then((res) => { //获取歌曲详情
				let s = res.data.songs[0]
				this.song.name = s.name;
				this.song.id = s.id;
				this.song.picUrl = s.al.picUrl;
				this.song.author = s.ar[0].name;
				// console.log(res);
				console.log(s);
				// console.log(this.song);
			})
			songUrl(sId).then((res) => { //获取歌曲音频的url
				this.song.songUrl = res.data.data[0].url;
				// console.log(res);
			})
			songLyric(sId).then((res) => { //获取歌词内容
				// this.song.lyric = res.data.lrc.lyric;
				let lyric = res.data.lrc.lyric;
				let result = [];
				let re = /\[([^\]]+)\]([^[]+)/g;
				lyric.replace(re, ($0, $1, $2) => {
						result.push({
							time: this.formatTimeToSec($1),
							lyric: $2
						})
					}),
					this.song.lyric = result;
				// console.log(this.song.lyric);
			})
			
		},
		methods: {
			playing() {
				innerAudioContext.autoplay = true;
				innerAudioContext.src = this.song.songUrl;
				innerAudioContext.onPlay(() => {
					this.isplayrotate = true;
					this.listenLyricIndex();
				});
				innerAudioContext.onError((res) => {
					console.log(res.errMsg);
					console.log(res.errCode);
				});
				this.innerAudioContext = innerAudioContext
			},
			paused() {
				innerAudioContext.pause();
				this.isplayrotate = false;
				console.log("停止播放");
				innerAudioContext.onPause(() => {  //暂停
					innerAudioContext.startTime = innerAudioContext.currentTime;
				});
			},
			formatTimeToSec(time) {
				var arr = time.split(':');
				return (parseFloat(arr[0]) * 60 + parseFloat(arr[1])).toFixed(2);
			},
			listenLyricIndex() {
				clearInterval(this.timer);
				this.timer = setInterval(() => {
					for (var i = 0; i < this.song.lyric.length; i++) {
						if (this.song.lyric[this.song.lyric.length - 1].time < this.innerAudioContext
							.currentTime) {
							this.lyricIndex = this.song.lyric.length - 1;
							break;
						}
						if (this.song.lyric[i].time < this.innerAudioContext.currentTime && this.song.lyric[i + 1]
							.time > this.innerAudioContext.currentTime) {
							this.lyricIndex = i;
						}
					}
				})
			}
		}
	}
</script>

 4.搜索页

 

<template>
	<view>
		<!-- <input type="button" class="ss" value="" v-model="ss"> -->
		<text>搜索内容:{{ss}}</text>
		<!-- <uniSearchBar></uniSearchBar> -->
		<uni-search-bar placeholder="搜索音乐" @focus="gg" v-on:input="dd" @confirm="ff" @cancel="ff" v-model="ss" @blur="ff"
			cancel-text="取消">
			<template v-slot:searchIcon>
				<uni-icons color="#999999" size="18" type="home" />
			</template>
		</uni-search-bar>

<div class="sy">
	搜索历史
<view v-for="(item,index) of key" >{{item}}</view>
</div>

		<!-- 一字 -->
		<div v-if="showChildDialog2">
			<view>搜索</view>
			
			<view>
				<h6 v-for="(item,index) of cc">{{item.keyword}}</h6>
			</view>
		</div>
		<div v-if="showChildDialog">
			<view> <text>热搜榜</text></view>
			<h6 v-for="(item,index) of aa" @tap="hh(item.searchWord)">
				<img :src="item.iconUrl" alt="">

				{{item.searchWord}}--{{item.content}}--{{item.score}}
			</h6>
		</div>

		<view v-if="showChildDialog3">
			<view><text>播放列表</text></view>
			<h6 v-for="(item,index) of bb" :key="index" @tap="navList(item.id)">
				<text>{{index+1}}</text>
				{{item.album.name}}
				<img src="../../static/image/sq.png" alt="">
				<text v-for="(i,index) of item.artists" :key="index">{{i.name}}/</text>
				<img src="../../static/播放.png" alt="">
			</h6>
		</view>
	</view>
</template>

<script>
	import {
		searchHot,
		searchWord,
		searchSuggest
	} from "../../common/api.js";

	import
	unisearchbar
	from "../../uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue";
	import gjcss from "../../components/gjcss/gjcss.vue"
	export default {
		data() {
			return {
				ss: '',
				aa: [],
				bb: [],
				cc: [],
				a: 1,
				key: [],
				showChildDialog: true,
				showChildDialog2: true,
				showChildDialog3: false
			}
		},
		onLoad() {
			searchHot().then((res) => {
				this.aa = res.data.data;
			});
			uni.getStorage({
				key: 'key',
				success: function (res) {
					this.key=res.data;
					console.log(6666)
				}
			});
		},
		methods: {
			gg() {

				if (this.ss != '') {
					this.showChildDialog2 = true;
				}
				console.log(this.showChildDialog3);
				if (this.showChildDialog3 == true) {
				}
			},
			dd() {
				if (this.ss != '') {
					this.showChildDialog = false;
					this.showChildDialog2 = true;
					searchSuggest(this.ss).then((res) => {
						this.cc = res.data.result.allMatch;
					});
				} else {
					this.showChildDialog = true;
					this.showChildDialog2 = false;
				}
			},
			ff() {
				if (this.ss != '') {
					this.showChildDialog2 = false;
					this.showChildDialog3 = true;
					
					searchWord(this.ss).then((res) => {
						this.bb = res.data.result.songs;
					});
					
					this.key.unshift(this.ss);
					this.key=[...new Set(this.key)];
					uni.setStorage({
						key: 'key',
						data: this.key,
						success: function (res) {
							
							// this.key=res.data;
							console.log(this.key)
						}
					});
					
				}
			},
			hh(t) {
				
				this.ss=t;
			},
			navList(listId) {
				uni.navigateTo({
					url: '/pages/player/player?id=' + listId
				});
			}
		},
	}
</script>

 

 

2. 本项目涉及的知识点一览

uni-app项目的创建

h5和安卓app发布

使用git和gitee进行代码的版本控制

使用gimp测量图片大小与距离以编写css

pages.json页面路由的配置

使用阿里云智能logo设计网站设计应用logo

安装与使用微信小程序开发工具

在uni-app中使用静态资源

iconfont的下载与使用

认识uniapp应用生命周期和页面生命周期

uni-app基础组件的使用view、scrollview、text、list

、rich-text等

安装、使用第三方组件-循环骨架m-for-skeleton

自定义组件开发-uamhead及使用向组件props传值

使用apifox调用、测试webapi

使用uni.request发起对api的网络请求并处理响应结果

在模板中声明事件及在代码中定义响应方法

uni-app中进行数据绑定、使用v-属性

使用uni.navigate进行页面间的跳转及传递参数

使用uni.createInnerAudioContext()创建音频对象并控制音频的播放

使用css3的animation实现音乐唱盘的动画效果

使用css的动态绑定技术实现动画启动-停止的控制

使用正则表达式对字符串进行搜索、替换

使用css的tranform配合js的setInterval同步歌曲的播放进度显示相应歌词

安装和使用uni-app的扩展组件uni-ui优化应用开发

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_57494029

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值