文章目录
页面布局
<template>
<view class="container">
<view class="layout">
<view class="box" v-for="item in 5">
<view class="pic">
<image src="../../static/logo.png" mode="widthFix"></image>
</view>
<view class="text">@@@@</view>
</view>
</view>
</view>
</template>
<script setup>
</script>
<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{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
}
}
}
}
</style>
效果:
调用萌宠API接口渲染到页面中
代码如下:
<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.width}}*{{item.height}}</view>
</view>
</view>
</view>
</template>
<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>
<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{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
}
}
}
}
</style>
效果如下,每次刷新都会有不同的猫咪图片出现:
换个接口试一下:
<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>
<script setup>
import { ref } from 'vue';
const pets = ref([]);
function network(){
uni.request({
url:"https://tea.qingnian8.com/tools/petShow",
data:{
size:10
}
}).then(res=>{
console.log(res.data.data);
pets.value = res.data.data
})
}
network();
</script>
<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{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
color:#333;
font-size:36rpx;
}
.author{
padding:0 30rpx 30rpx;
text-align:right;
color:#888;
font-size:28rpx;
}
}
}
}
</style>
效果:
previewImage图片预览和lazy-load懒加载
增加图片预览和懒加载功能,代码如下:
<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>
<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
}
}).then(res=>{
console.log(res.data.data);
pets.value = res.data.data
})
}
network();
</script>
<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{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
color:#333;
font-size:36rpx;
}
.author{
padding:0 30rpx 30rpx;
text-align:right;
color:#888;
font-size:28rpx;
}
}
}
}
</style>
效果:
对回调结果严格处理then_catch_finally用法
对网络的回调结果做出判断,代码如下:
<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>
<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":"lp9899"
}
}).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:3000,
})
}
}).catch(err=>{
uni.showToast({
title:"请求有误,请重新刷新",
icon:"none",
duration:3000,
})
}).finally(()=>{
uni.hideNavigationBarLoading()
})
}
network();
</script>
<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{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
color:#333;
font-size:36rpx;
}
.author{
padding:0 30rpx 30rpx;
text-align:right;
color:#888;
font-size:28rpx;
}
}
}
}
</style>
.then即使用result做一些事情,.catch是用于处理错误的;.finally即无论是否成功,都会执行。
完成下拉刷新和触底加载更多
下拉刷新的实现,即清空数组,然后重新加载。
触底加载更多的实现,即将新加载内容与旧内容合并起来。
<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>
<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:5
},
header:{
"access-key":"lp9899"
}
}).then(res=>{
if(res.data.errCode === 0){ //errCode = 0 ,才让它赋值
pets.value = [...pets.value,...res.data.data]
console.log(pets.value)
}else if (res.data.errCode === 400){
uni.showToast({
title:res.data.errMsg,
icon:"none",
duration:3000,
})
}
}).catch(err=>{
uni.showToast({
title:"请求有误,请重新刷新",
icon:"none",
duration:3000,
})
}).finally(()=>{
uni.hideNavigationBarLoading()
uni.stopPullDownRefresh()
})
}
//触底加载更多
onReachBottom(()=>{
network();
})
//下拉刷新
onPullDownRefresh(()=>{
pets.value = [];
network();
})
network();
</script>
<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{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
color:#333;
font-size:36rpx;
}
.author{
padding:0 30rpx 30rpx;
text-align:right;
color:#888;
font-size:28rpx;
}
}
}
}
</style>
效果:
pageScrollTo滚动到顶部和刷新
定义“刷新” “顶部” 两个按钮,为其设置CSS;然后定义点击刷新与界面滚动的方法。
<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 class="float">
<view class="item" @click="onRefresh">刷新</view>
<view class="item" @click="onTop">顶部</view>
</view>
</view>
</template>
<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
})
}
//点击刷新
const onRefresh = function(){
uni.startPullDownRefresh();
}
//返回顶部
const onTop = function(){
uni.pageScrollTo({
scrollTop:0,
duration:100,
})
}
//发送网络请求
function network(){
uni.showNavigationBarLoading()
uni.request({
url:"https://tea.qingnian8.com/tools/petShow",
data:{
size:5
},
header:{
"access-key":"lp9899"
}
}).then(res=>{
if(res.data.errCode === 0){ //errCode = 0 ,才让它赋值
pets.value = [...pets.value,...res.data.data]
console.log(pets.value)
}else if (res.data.errCode === 400){
uni.showToast({
title:res.data.errMsg,
icon:"none",
duration:3000,
})
}
}).catch(err=>{
uni.showToast({
title:"请求有误,请重新刷新",
icon:"none",
duration:3000,
})
}).finally(()=>{
uni.hideNavigationBarLoading()
uni.stopPullDownRefresh()
})
}
//触底加载更多
onReachBottom(()=>{
network();
})
//下拉刷新
onPullDownRefresh(()=>{
pets.value = [];
network();
})
network();
</script>
<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{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
color:#333;
font-size:36rpx;
}
.author{
padding:0 30rpx 30rpx;
text-align:right;
color:#888;
font-size:28rpx;
}
}
}
.float{
position: fixed;
right: 30rpx;
bottom: 80rpx;
padding: env(safe-area-inset-bottom);
.item{
width: 90rpx;
height:90rpx;
background: rgba(255, 255, 255, 0.9);
border-radius: 50%;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #eee;
}
}
}
</style>
效果:
使用uni-ui扩展组件
去到官方文档中,选择uni-icons图标,使用前需要点击安装:
然后选择,下载插件并导入:
导入成功后,会出现uni-modules文件夹:
用法:
<uni-icons type="contact" size="30"></uni-icons>
导入uni-load-more 加载更多插件,用法:
<uni-load-more status="more"></uni-load-more>
同时实现图标插件与加载更多插件,代码如下:
<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 class="float">
<view class="item" @click="onRefresh">
<uni-icons type="refresh" size="26" color="#888"></uni-icons>
</view>
<view class="item" @click="onTop">
<uni-icons type="arrow-up" size="26" color="#888"></uni-icons>
</view>
</view>
<view class="loadMore">
<uni-load-more status="loading"></uni-load-more>
</view>
</view>
</template>
<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
})
}
//点击刷新
const onRefresh = function(){
uni.startPullDownRefresh();
}
//返回顶部
const onTop = function(){
uni.pageScrollTo({
scrollTop:0,
duration:100,
})
}
//发送网络请求
function network(){
uni.showNavigationBarLoading()
uni.request({
url:"https://tea.qingnian8.com/tools/petShow",
data:{
size:5,
type:"cat"
},
header:{
"access-key":"lp9899",
}
}).then(res=>{
if(res.data.errCode === 0){ //errCode = 0 ,才让它赋值
pets.value = [...pets.value,...res.data.data]
console.log(pets.value)
}else if (res.data.errCode === 400){
uni.showToast({
title:res.data.errMsg,
icon:"none",
duration:3000,
})
}
}).catch(err=>{
uni.showToast({
title:"请求有误,请重新刷新",
icon:"none",
duration:3000,
})
}).finally(()=>{
uni.hideNavigationBarLoading()
uni.stopPullDownRefresh()
})
}
//触底加载更多
onReachBottom(()=>{
network();
})
//下拉刷新
onPullDownRefresh(()=>{
pets.value = [];
network();
})
network();
</script>
<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{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
color:#333;
font-size:36rpx;
}
.author{
padding:0 30rpx 30rpx;
text-align:right;
color:#888;
font-size:28rpx;
}
}
}
.float{
position: fixed;
right: 30rpx;
bottom: 80rpx;
padding: env(safe-area-inset-bottom);
.item{
width: 90rpx;
height:90rpx;
background: rgba(255, 255, 255, 0.9);
border-radius: 50%;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #eee;
}
}
.loadMore{
padding-bottom: calc(env(safe-area-inset-bottom) + 50rpx);
}
}
</style>
效果:
分段器组件实现点击切换萌宠类型
先实现分段器,代码如下:
<template>
<view class="container">
<view class="menu">
<uni-segmented-control :current="1" :values="[11,22,33]" @clickItem="onClickItem" styleType="button" activeColor="#2B9939"></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="refresh" size="26" color="#888"></uni-icons>
</view>
<view class="item" @click="onTop">
<uni-icons type="arrow-up" size="26" color="#888"></uni-icons>
</view>
</view>
<view class="loadMore">
<uni-load-more status="loading"></uni-load-more>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
const pets = ref([]);
//点击菜单
const onClickItem = function(e){
console.log(e)
}
//点击预览
const onPreview = function (index){
let urls = pets.value.map(item=>item.url)
uni.previewImage({
current:index,
urls
})
}
//点击刷新
const onRefresh = function(){
uni.startPullDownRefresh();
}
//返回顶部
const onTop = function(){
uni.pageScrollTo({
scrollTop:0,
duration:100,
})
}
//发送网络请求
function network(){
uni.showNavigationBarLoading()
uni.request({
url:"https://tea.qingnian8.com/tools/petShow",
data:{
size:5,
type:"cat"
},
header:{
"access-key":"lp9899",
}
}).then(res=>{
if(res.data.errCode === 0){ //errCode = 0 ,才让它赋值
pets.value = [...pets.value,...res.data.data]
console.log(pets.value)
}else if (res.data.errCode === 400){
uni.showToast({
title:res.data.errMsg,
icon:"none",
duration:3000,
})
}
}).catch(err=>{
uni.showToast({
title:"请求有误,请重新刷新",
icon:"none",
duration:3000,
})
}).finally(()=>{
uni.hideNavigationBarLoading()
uni.stopPullDownRefresh()
})
}
//触底加载更多
onReachBottom(()=>{
network();
})
//下拉刷新
onPullDownRefresh(()=>{
pets.value = [];
network();
})
network();
</script>
<style lang="scss" scoped>
.container{
.menu{
padding: 50rpx 50rpx 0;
}
.layout{
padding: 50rpx;
.box{
margin-bottom: 60rpx;
box-shadow: 0 10rpx 40rpx rgba(0,0,0,0.08);
border-radius: 15rpx;
overflow: hidden;
.pic{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
color:#333;
font-size:36rpx;
}
.author{
padding:0 30rpx 30rpx;
text-align:right;
color:#888;
font-size:28rpx;
}
}
}
.float{
position: fixed;
right: 30rpx;
bottom: 80rpx;
padding: env(safe-area-inset-bottom);
.item{
width: 90rpx;
height:90rpx;
background: rgba(255, 255, 255, 0.9);
border-radius: 50%;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #eee;
}
}
.loadMore{
padding-bottom: calc(env(safe-area-inset-bottom) + 50rpx);
}
}
</style>
效果:
现在实现点击逻辑,分为三类:全部、猫猫、狗狗,点击后会显示相应的图片类型,在任意界面下拉刷新时回到全部界面
<template>
<view class="container">
<view class="menu">
<uni-segmented-control :current="current" :values="values" @clickItem="onClickItem" styleType="button" activeColor="#2B9939"></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="refresh" size="26" color="#888"></uni-icons>
</view>
<view class="item" @click="onTop">
<uni-icons type="arrow-up" size="26" color="#888"></uni-icons>
</view>
</view>
<view class="loadMore">
<uni-load-more status="loading"></uni-load-more>
</view>
</view>
</template>
<script setup>
import { computed, ref } from 'vue';
const pets = ref([]);
const current = ref(0);
const classify = [{key:"all",value:"全部"},{key:"dog",value:"狗狗"},{key:"cat",value:"猫猫"}];
const values = computed(()=>classify.map(item=>item.value))
//点击菜单
const onClickItem = function(e){
current.value = e.currentIndex
pets.value = []
console.log()
network()
}
//点击预览
const onPreview = function (index){
let urls = pets.value.map(item=>item.url)
uni.previewImage({
current:index,
urls
})
}
//点击刷新
const onRefresh = function(){
uni.startPullDownRefresh();
}
//返回顶部
const onTop = function(){
uni.pageScrollTo({
scrollTop:0,
duration:100,
})
}
//发送网络请求
function network(){
uni.showNavigationBarLoading()
uni.request({
url:"https://tea.qingnian8.com/tools/petShow",
data:{
size:5,
type:classify[current.value].key
},
header:{
"access-key":"lp9899",
}
}).then(res=>{
if(res.data.errCode === 0){ //errCode = 0 ,才让它赋值
pets.value = [...pets.value,...res.data.data]
console.log(pets.value)
}else if (res.data.errCode === 400){
uni.showToast({
title:res.data.errMsg,
icon:"none",
duration:3000,
})
}
}).catch(err=>{
uni.showToast({
title:"请求有误,请重新刷新",
icon:"none",
duration:3000,
})
}).finally(()=>{
uni.hideNavigationBarLoading()
uni.stopPullDownRefresh()
})
}
//触底加载更多
onReachBottom(()=>{
network();
})
//下拉刷新
onPullDownRefresh(()=>{
pets.value = [];
current.value = 0
network();
})
network();
</script>
<style lang="scss" scoped>
.container{
.menu{
padding: 50rpx 50rpx 0;
}
.layout{
padding: 50rpx;
.box{
margin-bottom: 60rpx;
box-shadow: 0 10rpx 40rpx rgba(0,0,0,0.08);
border-radius: 15rpx;
overflow: hidden;
.pic{
iamge{
width: 100%;
}
}
.text{
padding: 30rpx;
color:#333;
font-size:36rpx;
}
.author{
padding:0 30rpx 30rpx;
text-align:right;
color:#888;
font-size:28rpx;
}
}
}
.float{
position: fixed;
right: 30rpx;
bottom: 80rpx;
padding: env(safe-area-inset-bottom);
.item{
width: 90rpx;
height:90rpx;
background: rgba(255, 255, 255, 0.9);
border-radius: 50%;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #eee;
}
}
.loadMore{
padding-bottom: calc(env(safe-area-inset-bottom) + 50rpx);
}
}
</style>
效果: