一.萌宠案例
随机猫咪API接口:https://api.thecatapi.com/v1/images/search?limit=1
咸虾米API接口:https://api.qingnian8.com/
1.页面布局
<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. 完成下拉刷新和触底加载更多
触底加载更多
<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 插件市场
安装完成之后
<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官网
<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>