Files
test/pages/search/search.vue

274 lines
8.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="searchLayout">
<!-- cancel是"取消",clear是那个"×" -->
<view class="search">
<uni-search-bar
@confirm="onSearch"
@cancel="onClear"
@clear="onClear"
:focus="true"
placeholder="搜索"
v-model="queryParams.keyword"
>
</uni-search-bar>
</view>
<!-- 当有图片的时候就不展示这些东西标签啥的 -->
<!-- 点击标签但是没有数据时noSearch会变成true也可以显示这些标签 -->
<view v-if="!classList.length || noSearch">
<!-- 这个最近搜索的展示是根据有没有历史记录来展示的
如果没有历史记录就不展示这一框
如果有历史记录就展示这一框
-->
<view class="history" v-if="historySearch.length">
<view class="topTitle" >
<view class="text">最近搜索</view>
<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>
<!-- 这里我本来的:key="index" ,但是人家却是:key="tab"-->
<view class="tabs">
<view class="tab" v-for="tab in recommendList" :key="tab"
@click="clickTab(tab)">{{tab}}</view>
</view>
</view>
</view>
<!-- 没有搜索结果的情况,这是一个插件 -->
<view class="noSearch" v-if="noSearch">
<uv-empty mode="search" ></uv-empty>
</view>
<!-- 有搜索结果的展示区域 -->
<view v-else>
<view class="list">
<!-- 这里你单独的进行传id也是不能够看到预览页面的 -->
<!-- 因为预览页面呢个够被看到是取决你有没有缓存这个预览页面的数据的 -->
<!-- 而缓存预览页面的数据我们可以在请求网络的数据的时候就进行存储 -->
<!--
:url是:url="`/pages/preview/preview?id=${item._id}`"
不是:url="`pages/preview/preview?id=${item._id}`"
前面还要有一个 /
-->
<!-- <navigator :url="`pages/preview/preview?id=${item._id}`" class="item"
v-for="item in classList" :key="item._id"> -->
<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 v-if="noData || classList.length" class="loadingLayout">
<uni-load-more :status="noData?'noMore':'loading'"/>
</view>
</view>
</view>
</template>
<script setup>
import {ref} from "vue"
import {onReachBottom,onUnload,onLoad} from "@dcloudio/uni-app"
import {apiSearchData} from "@/api/apis.js"
//传递的参数
const queryParams = ref({
pageNum:1,
pageSize:12,
keyword:""
})
//搜索历史词
//获取历史搜索词,我们需要使其从缓存里面读取,保证刷新不会重新被赋值
// 当用户没有缓存时给一个空数组避免出现获取不到null的情况进而影响后续操作
const historySearch = ref(uni.getStorageSync("historySearch") || []);
//热门推荐词
const recommendList = ref(["美女","帅哥","宠物","卡通"])
//进到标签页面时可能发生的情况
//没有数据了
const noData = ref(false)
//没有搜索结果
const noSearch = ref(false)
//搜索结果列表 搜索的结果最终是要在preview页面进行查看的
// classList初始化为空只有在调用了searchData()函数之后才会被赋值
const classList = ref([])
//点击清除按钮
const onClear = ()=>{
initParams()
}
//点击标签进行搜索.需要一个参数接收传入的标签名
// 问题1.搜索框的值怎么表示? --》 v-model 绑定,监视:value和@input事件
// 2.怎么得到值后就自动”comfirm“
const clickTab = (value) =>{
/* 因为你在点击了标签的内容之后,还可以在搜索框继续进行搜索,那此时你新搜索的内容会跟之前一样,
被添加到原来的内容下面。因此你需要对其进行初始化并将keyword换成最新的关键词 */
initParams(value)
// 点击标签之后不是触发searchData(),因为这样不会这个点击的标签不会被添加到历史记录里面
// 点击标签之后要触发的函数是onSearch()
// searchData()
onSearch()
}
//清空最近搜索历史记录
const removeHistory = ()=>{
uni.showModal({
title:"是否清空历史搜索",
success:(res) =>{
if(res.confirm){
// console.log("确认删除");
uni.removeStorageSync("historySearch")
historySearch.value = []
}
}
})
}
//1.点击搜索,点击了之后,搜索记录里面要多加一个记录
const onSearch = ()=>{
//加一个加载页提高用户体验。那时候时候取消呢在searchData()获取数据那时候进行操作
uni.showLoading()
// console.log(queryParams.value.keyword);
// 第一种添加的方式就是直接加到前面,老的历史词就直接展开
// 第二种就是直接用数组的添加方法
//slice进行切片操作确保只有10个历史记录
historySearch.value = [...new Set([queryParams.value.keyword,...historySearch.value])].slice(0,10)
uni.setStorageSync("historySearch",historySearch.value)
/* 因为你在点击了标签的内容之后,还可以在搜索框继续进行搜索,那此时你新搜索的内容会跟之前一样,
被添加到原来的内容下面。因此你需要对其进行初始化并将keyword换成最新的关键词 */
initParams(queryParams.value.keyword)
// 只有点击“搜索”之后才要触发这个函数
searchData()
}
//搜索之后所有的要做的功能的合集
const searchData = async () =>{
// 加一个try、catch进行操作捕捉“拿不到数据”的情况。
try{
//使res等于请求过来的数据
let res = await apiSearchData(queryParams.value)
classList.value = [...classList.value,...res.data]
//将数据保存到缓存里面方便上面点击标签后要预览页面preview
uni.setStorageSync("storgClassList",classList.value)
//如果后面没有数据了就需要把noData变成true
if(queryParams.value.pageSize > res.data.length) noData.value = true
//下面这个是判断有没有搜索结果的
//如果先点击了有图片的标签,那么当你再点击没图片的标签时,就还是展示原来那个有图片的标签
//如果原本classList就是空的并且你点击的标签也没有图片时才会展示“没有搜索结果”
if(res.data.length == 0 && classList.value.length == 0) noSearch.value = true
// console.log(res);
}finally {
uni.hideLoading()
}
}
//初始化搜索框,清空原本的内容
//什么时候用呢?
// 1.当我们点击“取消”和"×"的时候进行调用
// 2.当我们点击新的标签时就要先初始化
const initParams = (value='')=>{
//清空原先已经展示的数据
classList.value = []
noData.value = false
noSearch.value = false
queryParams.value = {
pageNum:1,
pageSize:12,
// 如果有传入值就把这个值赋给keyword没有值的话就默认变成""
keyword:value || ""
}
}
//触底加载更多
onReachBottom(()=>{
//这个if表示如果后面没有数据了就直接return结束不要再进行请求数据了
if(noData.value) return
queryParams.value.pageNum++
searchData()
})
//关闭页面时将数据清除,能够提高性能
onUnload(()=>{
uni.removeStorageSync("storgClassList",classList.value)
})
</script>
<style lang="scss" scoped>
.searchLayout{
.search{
padding: 0 10rpx;
}
.topTitle{
display: flex;
justify-content: space-between;
align-items: center;
}
.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{
height: 100%;
width: 100%;
display: block;
}
}
}
}
</style>