学习:入门uniapp Vue3组合式API版本(10)

发布于:2025-07-31 ⋅ 阅读:(24) ⋅ 点赞:(0)

一.萌宠案例

随机猫咪API接口:https://api.thecatapi.com/v1/images/search?limit=1

咸虾米API接口:https://api.qingnian8.com/

1.页面布局

CSS3 box-shadow 属性 | 菜鸟教程 

CSS3 border-radius 属性 | 菜鸟教程 

 

<script setup>

</script>
<template>
	<view class="container">
		<view class="layout">
			<view class="box" v-for="item in 10" :key="index">
				<view class="pic">
					<image src="/static/image/logo.png" mode="widthFix"></image>
				</view>
				<view class="text">
					abc

				</view>
			</view>
		</view>
	</view>
</template>
<style lang="scss" scoped>
	.container {
		.layout {
			padding: 50rpx;

			.box {
				margin-bottom: 60rpx;
				box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
				border-radius: 15rpx;
				overflow: hidden;//圆角

				.pic {
					image {
						width: 100%;
					}
				}

				.text {
					padding: 30rpx;
				}

			}
		}
	}
</style>

 

2.调用接口 

 随机猫咪API接口:https://api.thecatapi.com/v1/images/search?limit=1 

<script setup>
	import {
		ref
	} from 'vue';
	const pets = ref([])
	function network() {
		uni.request({
			url: "https://api.thecatapi.com/v1/images/search",
			data: {
				limit: 10
			}
		}).then(res => {
			console.log(res.data);
			pets.value=res.data
		})
	}
network() ;
</script>
<template>
	<view class="container">
		<view class="layout">
			<view class="box" v-for="item in pets" :key="item.id">
				<view class="pic">
					<image :src="item.url" mode="widthFix"></image>
				</view>
				<view class="text">
					{{item.id}}
				</view>
			</view>
		</view>
	</view>
</template>
<style lang="scss" scoped>
	.container {
		.layout {
			padding: 50rpx;

			.box {
				margin-bottom: 60rpx;
				box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
				border-radius: 15rpx;
				overflow: hidden; //圆角

				.pic {
					image {
						width: 100%;
					}
				}

				.text {
					padding: 30rpx;
				}

			}
		}
	}
</style>

 

  咸虾米API接口:https://api.qingnian8.com/

<script setup>
	import {
		ref
	} from 'vue';
	const pets = ref([]);

	function network() {
		uni.request({
			url: "https://tea.qingnian8.com/tools/petShow",
			data: {
				size: 10
			},
			// header:{
			// 	key:''
			// }
		}).then(res => {
			console.log(res.data.data)
			pets.value = res.data.data
		})
	}
network() ;
</script>
<template>
	<view class="container">
		<view class="layout">
			<view class="box" v-for="item in pets" :key="item._id">
				<view class="pic">
					<image :src="item.url" mode="widthFix"></image>
				</view>
				<view class="text">
					{{item.content}}
				</view>
				<view class="author">-{{item.author}}</view>
			</view>
		</view>
	</view>
</template>
<style lang="scss" scoped>
	.container {
		.layout {
			padding: 50rpx;

			.box {
				margin-bottom: 60rpx;
				box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
				border-radius: 15rpx;
				overflow: hidden; //圆角

				.pic {
					image {
						width: 100%;
					}
				}

				.text {
					padding: 30rpx;
				}

				.author {
					padding: 0 30rpx 30rpx;
					text-align: right;
					color: #888;
					font-size: 28rpx;
				}
			}
		}
	}
</style>

 

 

3.使用API接口通过传输头传递access-key

	uni.request({
		url: "",
		header:{
			"access-key":''
		}
	})

4.previewImage图片预览和lazy-load懒加载 

 uni.previewImage(OBJECT)|uni-app官网

预览图片。

参数名 类型 必填 说明 平台差异说明
current String/Number 详见下方说明 详见下方说明
showmenu Boolean 是否显示长按菜单,默认值为 true 微信小程序2.13.0
urls Array<String> 需要预览的图片链接列表
indicator String 图片指示器样式,可取值:"default" - 底部圆点指示器; "number" - 顶部数字指示器; "none" - 不显示指示器。 App
loop Boolean 是否可循环预览,默认值为 false App
longPressActions Object 长按图片显示操作菜单,如不填默认为保存相册 App 1.9.5+

current 参数说明

current 为当前显示图片的链接/索引值,不填或填写的值无效则为 urls 的第一张。App平台在 1.9.5至1.9.8之间,current为必填。不填会报错

 

Array.prototype.map() - JavaScript | MDN 

<script setup>
	import {
		ref
	} from 'vue';
	const pets = ref([]);
	const onPreview = function(index) {
		let urls = pets.value.map(item => item.url);
		uni.previewImage({
			current: index,
			urls
		})
	}

	//发送网络请求
	function network() {
		uni.request({
			url: "https://tea.qingnian8.com/tools/petShow",
			data: {
				size: 10
			},
			// header:{
			// 	"access-key":''
			// }
		}).then(res => {
			console.log(res.data.data)
			pets.value = res.data.data
		})
	}
	network();
</script>
<template>
	<view class="container">
		<view class="layout">
			<view class="box" v-for="(item,index) in pets" :key="item._id">
				<view class="pic">
					<image :src="item.url" mode="widthFix" @click="onPreview(index)"></image>
				</view>
				<view class="text">
					{{item.content}}
				</view>
				<view class="author">-{{item.author}}</view>
			</view>
		</view>
	</view>
</template>
<style lang="scss" scoped>
	.container {
		.layout {
			padding: 50rpx;

			.box {
				margin-bottom: 60rpx;
				box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
				border-radius: 15rpx;
				overflow: hidden; //圆角

				.pic {
					image {
						width: 100%;
					}
				}

				.text {
					padding: 30rpx;
				}

				.author {
					padding: 0 30rpx 30rpx;
					text-align: right;
					color: #888;
					font-size: 28rpx;
				}
			}
		}
	}
</style>

展示:

 layz-load

lazy-load Boolean false 图片懒加载。只针对page与scroll-view下的image有效 微信小程序、百度小程序、抖音小程序、飞书小程序

 

<image lazy-load :src="item.url" mode="widthFix" @click="onPreview(index)"></image>

 

5. 对回调结果严格处理then_catch_finally用法

<script setup>
	import {
		ref
	} from 'vue';
	const pets = ref([]);
	const onPreview = function(index) {
		let urls = pets.value.map(item => item.url);
		uni.previewImage({
			current: index,
			urls
		})
	}

	//发送网络请求
	function network() {
		uni.showNavigationBarLoading()
		uni.request({
			url: "https://tea.qingnian8.com/tools/petShow",
			data: {
				size: 10
			},
			header:{
				"access-key":''
			}
		}).then(res => {
			if(res.data.errCode==0){//errCode为0则
				pets.value = res.data.data
			}else if(res.data.errCode===400){
				uni.showToast({
					title:res.data.errMsg,
					icon:"none",
					duration:2000,
				})
			}
		}).catch(err=>{
			uni.showToast({
				title:"请求有误,请重新刷新",
				icon:"none"
			})
		}).finally(()=>{
			uni.hideNavigationBarLoading()
		})
	}
	network();
</script>
<template>
	<view class="container">
		<view class="layout">
			<view class="box" v-for="(item,index) in pets" :key="item._id">
				<view class="pic">
					<image lazy-load :src="item.url" mode="widthFix" @click="onPreview(index)"></image>
				</view>
				<view class="text">
					{{item.content}}
				</view>
				<view class="author">-{{item.author}}</view>
			</view>
		</view>
	</view>
</template>
<style lang="scss" scoped>
	.container {
		.layout {
			padding: 50rpx;

			.box {
				margin-bottom: 60rpx;
				box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
				border-radius: 15rpx;
				overflow: hidden; //圆角

				.pic {
					image {
						width: 100%;
					}
				}

				.text {
					padding: 30rpx;
				}

				.author {
					padding: 0 30rpx 30rpx;
					text-align: right;
					color: #888;
					font-size: 28rpx;
				}
			}
		}
	}
</style>
 "access-key"错误

 

 url错误

正常: 

 

6. 完成下拉刷新和触底加载更多

 触底加载更多

展开语法(...) - JavaScript | MDN

<script setup>
	import {
		ref
	} from 'vue';
	import {
		onReachButton
	} from "@dcloudio/uni-app"
	const pets = ref([]);
	const onPreview = function(index) {
		let urls = pets.value.map(item => item.url);
		uni.previewImage({
			current: index,
			urls
		})
	}

	//发送网络请求
	function network() {
		uni.showNavigationBarLoading()
		uni.request({
			url: "https://tea.qingnian8.com/tools/petShow",
			data: {
				size: 5
			},
			// header:{
			// 	"access-key":'00'
			// }
		}).then(res => {
			if (res.data.errCode == 0) { //errCode为0则
				pets.value = [...pets.value, ...res.data.data]
			} else if (res.data.errCode === 400) {
				uni.showToast({
					title: res.data.errMsg,
					icon: "none",
					duration: 2000,
				})
			}
		}).catch(err => {
			uni.showToast({
				title: "请求有误,请重新刷新",
				icon: "none"
			})
		}).finally(() => {
			uni.hideNavigationBarLoading()
		})
	}
	//触底加载更多
	onReachButton(() => {
		network();
	})
	network();
</script>
<template>
	<view class="container">
		<view class="layout">
			<view class="box" v-for="(item,index) in pets" :key="item._id">
				<view class="pic">
					<image lazy-load :src="item.url" mode="widthFix" @click="onPreview(index)"></image>
				</view>
				<view class="text">
					{{item.content}}
				</view>
				<view class="author">-{{item.author}}</view>
			</view>
		</view>
	</view>
</template>
<style lang="scss" scoped>
	.container {
		.layout {
			padding: 50rpx;

			.box {
				margin-bottom: 60rpx;
				box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
				border-radius: 15rpx;
				overflow: hidden; //圆角

				.pic {
					image {
						width: 100%;
					}
				}

				.text {
					padding: 30rpx;
				}

				.author {
					padding: 0 30rpx 30rpx;
					text-align: right;
					color: #888;
					font-size: 28rpx;
				}
			}
		}
	}
</style>

展示:

下拉刷新 

在pages.json配置 "enablePullDownRefresh": true

{
	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		{
			"path": "pages/requestDemo/requestDemo",
			"style": {
				"navigationBarTitleText": "requestDemo",
				"enablePullDownRefresh": true
			}
		}
	],
	"globalStyle": {
		"navigationBarTextStyle": "white",
		"navigationBarTitleText": "Nanshu",
		"navigationBarBackgroundColor": "#99FF99",
		"backgroundColor": "#99FFFF",
		"backgroundTextStyle": "light",
		"enablePullDownRefresh": true,
		"onReachBottomDistance": 100
	},
	"tabBar": {
		"color": "#999",
		"selectedColor": "#0004ff ",
		"backgroundColor": "#b8ff99",
		"borderStyle": "white", //默认黑白
		// "position": "top",//默认在下方,只有小程序支持
		"list": [{
				"pagePath": "pages/index/index",
				"text": "首页",
				"iconPath": "/static/image/tabBar/home.png",
				"selectedIconPath": "/static/image/tabBar/home-h.png"
			},
			{
				"pagePath": "pages/classify/classify",
				"text": "分类",
				"iconPath": "/static/image/tabBar/classify.png",
				"selectedIconPath": "/static/image/tabBar/classify-h.png"
			},
			{
				"pagePath": "pages/user/user",
				"text": "用户",
				"iconPath": "/static/image/tabBar/user.png",
				"selectedIconPath": "/static/image/tabBar/user-h.png"
			}
		]
	},
	"uniIdRouter": {}
}

 展示:

7.uni.pageScrollTo(OBJECT)滚动到顶部和刷新

OBJECT参数说明

参数名 类型 必填 说明
scrollTop Number 滚动到页面的目标位置(单位px)
selector String 元素选择器,用于指定要滚动到的元素位置,App、H5、抖音小程序2.62.0+、微信小程序2.7.3+ 、支付宝小程序1.20.0+支持
duration Number 滚动动画的时长,默认300,单位 ms

 

<script setup>
	import {
		ref
	} from 'vue';
	import {
		onReachBottom,
		onPullDownRefresh
	} from "@dcloudio/uni-app"
	const pets = ref([]);

	//发送网络请求
	function network() {
		uni.showNavigationBarLoading()
		uni.request({
			url: "https://tea.qingnian8.com/tools/petShow",
			data: {
				size: 5
			},
			header: {
				"access-key": 'ccc#bbb'
			}
		}).then(res => {
			if (res.data.errCode == 0) { //errCode为0则
				pets.value = [...pets.value, ...res.data.data]
			} else if (res.data.errCode === 400) {
				uni.showToast({
					title: res.data.errMsg,
					icon: "none",
					duration: 2000,
				})
			}
		}).catch(err => {
			uni.showToast({
				title: "请求有误,请重新刷新",
				icon: "none"
			})
		}).finally(() => {
			uni.stopPullDownRefresh();
			uni.hideNavigationBarLoading()
		})
	}

	// 点击刷新
	function onRefresh() {
		uni.startPullDownRefresh();
	}
	//返回顶部   
	function onTop() {
uni.pageScrollTo({
	scrollTop:0,
	duration:100,
})
	}
	network();
</script>
<template>
	<view class="container">
		<view class="float">
			<view class="item" @click="onRefresh">刷新</view>
			<view class="item" @click="onTop">回到顶部</view>
			<view class="box"></view>
		</view>
	</view>
</template>
<style lang="scss" scoped>
	.container {
		.float {
			position: fixed;
			right: 30rpx;
			bottom: 80rpx;
			padding-bottom: env(safe-area-inset-bottom);

			.item {
				width: 90rpx;
				height: 90rpx;
				background: rgba(255, 255, 255, 0.6);
				border-radius: 50%;
				margin-bottom: 20rpx;
				display: flex;
				align-items: center;
				justify-content: center;
				border: 1rpx solid #ccc;
				box-shadow: 0 5rpx 1rpx #d7d7d7;
			}
		}

	}
</style>

 展示:

8.使用uni-ui扩展组件

下载安装使用uni-icons 图标 - DCloud 插件市场 

 

安装完成之后 

uni-icons 图标 | uni-app官网

 

<template>
		<view class="float">
			<view class="item" @click="onRefresh">
				<uni-icons type="refreshempty" size="30"></uni-icons>
			</view>
			<view class="item" @click="onTop">
				<uni-icons type="arrow-up" size="30"></uni-icons>
			</view>
		</view>
	</view>
</template>

 下载安装使用uni-load-more 加载更多 - DCloud 插件市场

 

uni-load-more 加载更多 | uni-app官网

CSS calc() 函数 | 菜鸟教程

 


<template>
		<view class="loadMore">
			<uni-load-more status="loading"></uni-load-more>
		</view>
	</view>
</template>
<style lang="scss" scoped>
		.loadMore {
			padding-bottom: calc(env(safe-area-inset-bottom) + 50rpx);
		}
	}
</style>

 

下载安装使用 uni-segmented-control 分段器 - DCloud 插件市场

 

 uni-segmented-control 分段器|uni-app官网

 

<script setup>
	import {
		computed,
		ref
	} from 'vue';
	import {
		onReachBottom,
		onPullDownRefresh
	} from "@dcloudio/uni-app"
	const pets = ref([]);
	const current = ref(0); //默认选择all

	//点击预览 
	const onPreview = function(index) {
		let urls = pets.value.map(item => item.url);
		uni.previewImage({
			current: index,
			urls
		})
	}

	//发送网络请求
	function network() {
		uni.showNavigationBarLoading()
		uni.request({
			url: "https://tea.qingnian8.com/tools/petShow",
			data: {
				size: 5,
				type: classify[current.value].key
			},
			header: {
				"access-key": 'ccc#bbb'
			}
		}).then(res => {
			if (res.data.errCode == 0) { //errCode为0则
				pets.value = [...pets.value, ...res.data.data]
			} else if (res.data.errCode === 400) {
				uni.showToast({
					title: res.data.errMsg,
					icon: "none",
					duration: 2000,
				})
			}
		}).catch(err => {
			uni.showToast({
				title: "请求有误,请重新刷新",
				icon: "none"
			})
		}).finally(() => {
			uni.stopPullDownRefresh();
			uni.hideNavigationBarLoading()
		})
	}
	//触底加载更多
	onReachBottom(() => {
		network();
	})
	//下拉刷新
	onPullDownRefresh(() => {
		pets.value = [];
		current.value = 0
		network();
	})

	// 点击刷新
	function onRefresh() {
		uni.startPullDownRefresh();
	}
	//返回顶部   
	function onTop() {
		uni.pageScrollTo({
			scrollTop: 0,
			duration: 100,
		})
	}
	//总的选项数组
	const classify = [{
		key: "all",
		value: "全部"
	}, {
		key: "dog",
		value: "狗"
	}, {
		key: "cat",
		value: "猫"
	}]
	// 计算选项数组
	const values = computed(() => classify.map(item => item.value))
	//点击菜单
	function onClickItem(e) {
		// 更新当前选中的tab索引值
		current.value = e.currentIndex
		//清空数组
		pets.value = []
		//再获取
		network();
	}
	network();
</script>
<template>
	<view class="container">
		<view class="menu">
			<uni-segmented-control :current="current" :values="values" @clickItem="onClickItem" styleType="button"
				activeColor="#99FF99">
			</uni-segmented-control>
		</view>
		<view class="layout">
			<view class="box" v-for="(item,index) in pets" :key="item._id">
				<view class="pic">
					<image lazy-load :src="item.url" mode="widthFix" @click="onPreview(index)"></image>
				</view>
				<view class="text">
					{{item.content}}
				</view>
				<view class="author">-{{item.author}}</view>
			</view>
		</view>


		<view class="float">
			<view class="item" @click="onRefresh">
				<uni-icons type="refreshempty" size="30"></uni-icons>
			</view>
			<view class="item" @click="onTop">
				<uni-icons type="arrow-up" size="30"></uni-icons>
			</view>
		</view>


		<view class="loadMore">
			<uni-load-more status="loading"></uni-load-more>
		</view>
	</view>
</template>
<style lang="scss" scoped>
	.container {
		.menu {
			padding: 50rpx 50rpx 0;
		}

		.float {
			position: fixed;
			right: 30rpx;
			bottom: 80rpx;
			padding-bottom: env(safe-area-inset-bottom);

			.item {
				width: 90rpx;
				height: 90rpx;
				background: rgba(255, 255, 255, 0.6);
				border-radius: 50%;
				margin-bottom: 20rpx;
				display: flex;
				align-items: center;
				justify-content: center;
				border: 1rpx solid #ccc;
				box-shadow: 0 5rpx 1rpx #d7d7d7;
			}
		}

		.layout {
			padding: 50rpx;

			.box {
				margin-bottom: 60rpx;
				box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
				border-radius: 15rpx;
				overflow: hidden; //圆角

				.pic {
					image {
						width: 100%;
					}
				}

				.text {
					padding: 30rpx;
				}

				.author {
					padding: 0 30rpx 30rpx;
					text-align: right;
					color: #888;
					font-size: 28rpx;
				}

			}
		}

		.loadMore {
			padding-bottom: calc(env(safe-area-inset-bottom) + 50rpx);
		}
	}
</style>

9.结束


网站公告

今日签到

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