补充前面的“图片预览页”中点击“返回图标”的功能:
const goBack=()=>{
//利用uni.navigateBack
uni.navigateBack({
success:()=>{
//成功返回时
delta:1 //返回到上一页
},
fail:()=>{
//返回失败时,强制跳转到“首页”
//由于“首页”属于底部tabBar中的路由页面,所以跳转时利用uni.relaunch({})
uni.reLaunch({
url:"/pages/index/index"
})
}
}
一、完成“公告页面”的结构搭建及样式配置:
pages/notice/notice.vue:
发现该页面由:公告标题 、发布者、发布时间、二维码及文字、阅读数 组成。
<view class="noticeLayout">
//公告标题
<view class="title">
//tag标签
<view class="tag">
//使用uniapp中的uni-tag组件(用法在官网可见)
<uni-tag inverted text="置顶" type="error" />
</view>
//标题
<view class="font">公告标题</view>
</view>
//发布者及发布时间(uni-dateformat组件)
<view class="info">
<view class="item">发布者</view>
<view class="item">
<uni-dateformat :date="Date.now()" format="yyyy-MM-dd hh:mm:ss"></uni-dateformat>
</view>
</view>
//二维码及内容
<view class="content"></view>
//阅读数
<view class="count">
39234
</view>
</view>
样式配置:
<style lang="scss" scoped>
.noticeLayout{
padding:30rpx;
.title{
font-size: 40rpx;
color:#111;
line-height: 1.6em;
padding-bottom:30rpx;
display: flex;
//给tag标签缩小显示
.tag{
transform: scale(0.8);
transform-origin: left center;
flex-shrink: 0;
}
.font{
padding-left:6rpx;
}
}
.info{
display: flex;
align-items: center;
color:#999;
font-size: 28rpx;
.item{
padding-right: 20rpx;
}
}
.content{
padding:50rpx 0;
}
.count{
color:#999;
font-size: 28rpx;
}
}
</style>
二、实现“公告页面”中真实数据的获取:
1、封装接口方法用于获取真实数据
2、在“公告页面”中封装一个函数用于调用接口方法,获取数据
const detail=ref({})
const getNoticeDetail=async()=>{
const res= await apiNoticeDetail({id:noticeId})
detail.value=res.data
}
3、在“首页”公告区域,点击公告内容,实现跳转到其对应的公告页面
跳转时需要携带id值传入:
index/index.vue:
4、在“公告页面”中接收传来的参数id,实现数据获取
let noticeId;
onLoad((e)=>{
noticeId=e.id
//调用封装好的函数,实现发送请求,获取数据
getNoticeDetail()
})
5、将获取到的数据渲染在页面中:
三、实现“公告页面”中二维码及文字的显示:
由于在“公告区域”点击公告,跳转到对应的“公告页面”时,发送请求,获取到的公告数据是:
其中公告内容content部分的数据是一串html结构,因此要将其转化成用户能看懂的形式显示出来。
可以利用uniapp中的rich-text组件。
因此,可以这样写:
//二维码及内容
<view class="content">
<rich-text :node="detail.content"></rich-text>
</view>
四、在“用户页面”中点击“订阅更新”以及“常见问题”,实现跳转到“公告页面”
user/user.vue:
五、完成“搜索页”页面的基本结构及样式搭建:
1、先完成基本结构的搭建
发现“搜索页”是由: 搜索栏、最近搜索盒子、热门搜索盒子 、搜索列表数据组成。
搜索栏可以利用uni-search-bar组件来实现
pages/search/search.vue:
<template>
<view class="searchLayout">
//搜索栏 利用uniapp中的uni-search-bar组件
<view class="search">
<uni-search-bar
//当用户点击搜索/回车后触发@confirm事件
@confirm="onSearch"
//当用户点击“取消”按钮时,触发@cancel事件
@cancel="onClear"
// 当用户点击“清除”按钮时,触发@clear事件
@clear="onClear"
focus
placeholder="搜索"
// 实现搜索栏关键词数据的双向绑定
v-model="queryParams.keyword">
</uni-search-bar>
</view>
//“最近搜索”盒子:
<view v-if="!classList.length || noSearch">
<view class="history" v-if="historySearch.length">
//“标题”
<view class="topTitle">
<view class="text">最近搜索</view>
//“清除”图标 --- uni-icons图标
<view class="icon" @click="removeHistory">
<uni-icons type="trash" size="25"></uni-icons>
</view>
</view>
//“历史数据”
<view class="tabs">
<view class="tab" v-for="tab in historySearch" :key="tab"
@click="clickTab(tab)">{{tab}}</view>
</view>
</view>
//“热门搜索”盒子
<view class="recommend">
<view class="topTitle">
<view class="text">热门搜索</view>
</view>
<view class="tabs">
<view class="tab" v-for="tab in recommendList" :key="tab"
@click="clickTab(tab)">{{tab}}</view>
</view>
</view>
</view>
//当没有“搜索记录”时,显示的说明数据 利用插件uv-empty
//在浏览器中搜索“dcloud”,然后搜索插件uv-empty
//这是一个固定语法
<view class="noSearch" v-if="noSearch">
<uv-empty mode="search" icon="http://cdn.uviewui.com/uview/empty/search.png"></uv-empty>
</view>
//搜索列表数据:
<view v-else>
<view class="list">
<navigator :url="`/pages/preview/preview?id=${item._id}`" class="item"
v-for="item in classList" :key="item._id">
<image :src="item.smallPicurl" mode="aspectFill"></image>
</navigator>
</view>
<view class="loadingLayout" v-if="noData || classList.length">
<uni-load-more :status="noData?'noMore':'loading'"/>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.searchLayout{
.search{
padding:0 10rpx;
}
.topTitle{
display: flex;
justify-content: space-between;
align-items: center;
font-size: 32rpx;
color:#999;
}
.history{
padding:30rpx;
}
.recommend{
padding:30rpx;
}
.tabs{
display: flex;
align-items: center;
flex-wrap: wrap;
padding-top:20rpx;
.tab{
background: #F4F4F4;
font-size: 28rpx;
color:#333;
padding:10rpx 28rpx;
border-radius: 50rpx;
margin-right: 20rpx;
margin-top: 20rpx;
}
}
.list{
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 5rpx;
padding:20rpx 5rpx;
.item{
height: 440rpx;
image{
width: 100%;
height: 100%;
display: block;
}
}
}
}
</style>
2、准备一个“最近搜索”记录数组以及一个“热门搜索”记录数组:
const historySearch=ref([])
const recommendList = ref(["美女","帅哥","宠物","卡通"]);
//页面中进行数据渲染
//“最近搜索”盒子:
<view class=""history>
<view class="topTitle"></>
<view class="tabs">
<view class="tab" v-for="tab in historySearch" :key="tab">
{{tab}}
</view>
</view>
</view>
//“推荐搜索”盒子:
<view class="recommend">
<view class="topTitle"></>
<view class="tabs">
<view class="tab" v-for="item in recommendSearch" :key="tab">
{{tab}}
</view>
</view>
3、封装接口方法用于请求“搜索列表数据”:
api/apis.js:
在“搜索页”中准备接口需要的请求参数:
pages/search/search.vue:
let queryParams=ref({
keyword:'',
pageNum:1,
pageSize:12
})
封装一个函数用于调用接口方法,获取数据:
//准备一个搜索列表变量
const classList=ref([])
const searchData=async()=>{
try{
let res=await apiSearchData(queryParams.value)
classList.value=res.data
}finally{
uni.hideLoading()
}
}
4、实现“搜索列表”中触底加载更多数据显示:
与先前在“分类列表页”中的同理:
//设置一个变量用来表示是否还有新的数据存在
let noData=ref(false)
//当页面出现触底现象时,触发onReachBottom生命周期函数
onReachBottom(()=>{
if(noData.value) return;
queryParams.value.pageNum++
searchData()
})
//完善先前封装好的用于调用接口,获取数据的函数:
const searchData=async()=>{
try{
const res=await apiSearchData(queryParams)
classList.value=[...classList.value,...res.data]
//进行判断是否还有新的数据存在
if(queryParams.value.pageSize>res.data.length) noData.value=true
//将获取到的“搜索列表”数据存入本地中,便于之后在“图片预览页”中,可以直接从本地获取数据。
uni.setStorageSync("storgClassList",classList.value)
}
}finally{
uni.hideLoading()
}
}
5、实现当获取到了搜索结果时,“搜索列表”就显示,“最近搜索”盒子与“热门搜索”盒子就隐藏:
//设置一个变量用来表示是否有搜索结果
let noSearch=ref(false)
const searchData=async()=>{
try{
const res=await apiSearchData(queryParams)
classList.value=[...classList.value,...res.data]
//进行判断是否还有新的数据存在
if(queryParams.value.pageSize>res.data.length) noData.value=true
//将获取到的“搜索列表”数据存入本地中,便于之后在“图片预览页”中,可以直接从本地获取数据。
uni.setStorageSync("storgClassList",classList.value)
//判断是否获取到了搜索列表,来决定是否存在搜索结果:
//如果当前获取到的搜索数据长度为0并且搜索列表为空,则说明没有搜索结果。
if(res.data.length===0 && classList.value.length ===0) noSearch.value=true
}finally{}
}
下面实现条件渲染页面:如果不存在搜索结果,则搜索列表不显示。否则,搜索列表显示,“最近搜索”盒子以及“热门搜索”盒子不显示。
“最近搜索”盒子只有在有搜索记录时显示
<view class="" v-if="historySearch.length"></>
“最近搜索”盒子和“热门搜索”盒子只有在当前页面中没有搜索列表显示classlist.length==0 或者 没有搜索结果时显示 noSearch === true
而“搜索列表”盒子恰好与其相反,利用v-else
<view v-if="!classList.length || noSearch">
<view class="history" v-if="historySearch.length"></>
<view class="recommend" v-if="recommendSearch"></>
</view>
//搜索列表盒子
<view v-else>
<view class="list">
</>
</>
!!!6、用户点击“搜索”或者按下“回车键”时,触发@confirm事件,执行搜索功能:
<uni-search-bar @confirm="onSearch"></>
const onSearch=()=>{
uni.showLoading()
//先将“搜索关键字”追加进“最近搜索”记录数组中
//使用[...new Set(数组)]实现去重,避免有相同的关键字存在。
historySearch.value =
[...new Set([queryParams.value.keyword,...historySearch.value])].slice(0,10);
//再将“最近搜索”记录数组存入本地中,防止页面刷新后,记录丢失
uni.setStorageSync("historySearch",historySearch.value);
//每次发送请求,获取搜索列表时,都要进行初始化,避免先前搜索的列表数据存在
initParams(queryParams.value.keyword);
//再调用函数,请求搜索
searchData()
}
//所以“最近搜索”记录数组,在打开页面后,先从本地中拿记录数据,如果没有数据,则设置为[]
let historySearch=ref(uni.getStorageSync("historySearch") || []);
!!!7、实现点击“最近搜索”记录数组中的标签,也可以实现搜索功能:
<view class="tabs">
<view class="tab" v-for="tab in historySearch" :key="tab" @click="clickTab(tab)"></>
</>
<view class="tabs">
<view class="tab" v-for="tab in recommendSearch" :key="tab" @click="clickTab(tab)"></>
</>
const clickTab=(value)=>{
//首先进行初始化页面,避免先前的搜索列表数据存在
initParams(value)
//再执行搜索功能(包括将搜索关键字追加进“最近搜索”记录数组,也包括将记录数据存入本地,也包括调用函数,请求搜素,所以直接调用onSearch方法)
onSearch()
}
8、实现页面数据初始化:
const initParams = (value='')=>{
classList.value = [];
noData.value = false;
noSearch.value = false;
queryParams.value = {
pageNum:1,
pageSize:12,
keyword:"" || value
}
}
9、实现“清除”功能以及“取消”功能:
“取消功能”:
const onClear=()=>{
//初始化重置
initParams();
}
“清除关键字”功能:
const removeHistory=()=>{
//弹出提示,提示用户是否执行清除?
uni.showModal({
title:"是否清空历史搜索?",
success:(res)=>{
//判断用户是否点击“确认”?如果是,则清除本地记录以及“最近搜索”记录数组
if(res.confirm)
{
uni.removeStorageSync("historySearch");
historySearch.value=[]
}
})
}
六、实现“首页”中点击“轮播图组件”中的图片,跳转到对应的“分类列表页”:
由于请求获取“轮播图组件”中的图片数据时,返回的数据是:
可以看出,属性url包含了“分类列表页”中需要的参数信息id以及导航栏标题name
所以在执行路由跳转时,要携带上参数url
const goRouter=(value)=>{
uni.navigateTo({
url:`/pages/classify/classlist?${value}`
})
}
七、实现在首页中的“专题精选部分”,点击“more+”,可以跳转到“分类页”:
由于“分类页”属于底部tabBar导航栏中的路由页面,因此跳转时需要open-type="relanuch"