UNIAPP实战项目笔记21 搜索关键词判断和隐藏键盘搜索词记录清除搜索记录
搜索关键词判断和隐藏键盘
搜索词记录
清除搜索记录
搜索词传值APP端
实例效果图
项目分析
三 搜索列表 search-list
1. 商品的筛选
封装: 否
- 问题二和问题三
1 判断关键词,古国关键词为空则提示信息.
2 进入搜索页结果页面软键盘需要隐藏
3 点击软键盘的搜索也可以进入到搜索结果页面
4 搜索词
4.1 用本地存储
4.2 搜索词重复判断
4.3 最新搜索的词前置
5 清除最近搜索记录=>提示无搜索记录
6 搜索词不通过展示的数据不同
7 排序=>链接数据库,sql语句
目录结构
前端目录结构
-
manifest.json 配置文件: appid、logo…
-
pages.json 配置文件: 导航、 tabbar、 路由
-
main.js vue初始化入口文件
-
App.vue 全局配置:样式、全局监视
-
static 静态资源:图片、字体图标
-
page 页面
- index
- index.vue
- list
- list.vue
- my
- my.vue
- search
- search.vue
- search-list
- search-list.vue
- shopcart
- shopcart.vue
- index
-
components 组件
- index
- Banner.vue
- Hot.vue
- Icons.vue
- indexSwiper.vue
- Recommend.vue
- Shop.vue
- common
- Card.vue
- Commondity.vue
- CommondityList.vue
- Line.vue
- ShopList.vue
- index
-
common 公共文件:全局css文件 || 全局js文件
- api
- request.js
- common.css
- uni.css
- api
主要代码
- search.vue
<template>
<view class="search">
<Lines/>
<view class="search-item">
<view class="search-title">
<view class="f-color">最近搜索</view>
<view class="iconfont icon-shanchu" @tap="clearHistory"></view>
</view>
<view class="f-color"
v-if="searchData.length > 0"
>
<view class="search-name"
v-for="(item,index) in searchData"
:key="index"
>
{{item}}
</view>
</view>
<view v-else class="search-end f-color">
暂无搜索记录
</view>
</view>
<view class="search-item">
<view class="search-title">
<view class="f-color">热门搜索</view>
</view>
<view class="f-color">
<view class="search-name">四件套</view>
<view class="search-name">面膜</view>
</view>
</view>
</view>
</template>
<script>
import Lines from '@/components/common/Lines.vue'
export default {
data() {
return {
// 输入的关键词
keyword:'',
// 搜索过的词记录
searchData:[]
};
},
// 页面加载的时候
onLoad() {
uni.getStorage({
key:'searchData',
success: (res) => {
this.searchData = JSON.parse(res.data)
}
})
},
// 监控input输入内容
onNavigationBarSearchInputChanged(e) {
this.keyword = e.text;
},
// 点击顶栏中的搜索文字按钮
onNavigationBarButtonTap(e) {
this.search();
},
// 监听软键盘上的搜索按钮点击
onNavigationBarSearchInputConfirmed() {
this.search();
},
components:{
// 组件名称不要用 Line 和系统组件冲突
Lines
},
methods:{
// 判断关键词是否为空和跳转页面
search(){
if(this.keyword === ''){
uni.showToast({
title:"关键词不能为空",
icon:'none'
})
}else{
uni.navigateTo({
url:"/pages/search-list/search-list"
});
}
// 隐藏软键盘
uni.hideKeyboard();
this.addSearch();
},
// 记录最近搜索词
addSearch(){
// 先判断是否已存在
let idx = this.searchData.indexOf(this.keyword);
if(idx<0){
// 不存在直接添加
this.searchData.unshift(this.keyword)
}else{
// 先删除再去添加
this.searchData.unshift( this.searchData.splice(idx,1)[0] )
}
// 存入本地缓存
uni.setStorage({
key:'searchData',
data:JSON.stringify(this.searchData)
})
},
// 清除搜索记录
clearHistory(){
uni.showModal({
title:"重要提示",
content:"是否要清除搜索记录?",
cancelText:"取消",
confirmText:"确定",
success: (res) => {
if(res.confirm){
uni.removeStorage({
key:"searchData"
});
this.searchData=[];
}
}
})
}
}
}
</script>
<style lang="less">
.search-item{
padding: 20rpx;
}
.search-title{
display: flex;
justify-content: space-between;
}
.search-name{
padding: 4rpx 24rpx;
background-color: #E1E1E1;
display: inline-block;
border-radius: 26rpx;
margin: 10rpx;
}
.search-end{
text-align: center;
}
</style>
搜索词传值到组件并将搜索框显示为搜索词
search.vue
<template>
<view class="search">
<Lines/>
<view class="search-item">
<view class="search-title">
<view class="f-color">最近搜索</view>
<view class="iconfont icon-shanchu" @tap="clearHistory"></view>
</view>
<view class="f-color"
v-if="searchData.length > 0"
>
<view class="search-name"
v-for="(item,index) in searchData"
:key="index"
>
{{item}}
</view>
</view>
<view v-else class="search-end f-color">
暂无搜索记录
</view>
</view>
<view class="search-item">
<view class="search-title">
<view class="f-color">热门搜索</view>
</view>
<view class="f-color">
<view class="search-name">四件套</view>
<view class="search-name">面膜</view>
</view>
</view>
</view>
</template>
<script>
import Lines from '@/components/common/Lines.vue'
export default {
data() {
return {
// 输入的关键词
keyword:'',
// 搜索过的词记录
searchData:[]
};
},
// 页面加载的时候
onLoad() {
uni.getStorage({
key:'searchData',
success: (res) => {
this.searchData = JSON.parse(res.data)
}
})
},
// 监控input输入内容
onNavigationBarSearchInputChanged(e) {
this.keyword = e.text;
},
// 点击顶栏中的搜索文字按钮
onNavigationBarButtonTap(e) {
this.search();
},
// 监听软键盘上的搜索按钮点击
onNavigationBarSearchInputConfirmed() {
this.search();
},
components:{
// 组件名称不要用 Line 和系统组件冲突
Lines
},
methods:{
// 判断关键词是否为空和跳转页面
search(){
if(this.keyword === ''){
uni.showToast({
title:"关键词不能为空",
icon:'none'
})
}else{
uni.navigateTo({
url:"/pages/search-list/search-list?keyword="+this.keyword
});
}
// 隐藏软键盘
uni.hideKeyboard();
this.addSearch();
},
// 记录最近搜索词
addSearch(){
// 先判断是否已存在
let idx = this.searchData.indexOf(this.keyword);
if(idx<0){
// 不存在直接添加
this.searchData.unshift(this.keyword)
}else{
// 先删除再去添加
this.searchData.unshift( this.searchData.splice(idx,1)[0] )
}
// 存入本地缓存
uni.setStorage({
key:'searchData',
data:JSON.stringify(this.searchData)
})
},
// 清除搜索记录
clearHistory(){
uni.showModal({
title:"重要提示",
content:"是否要清除搜索记录?",
cancelText:"取消",
confirmText:"确定",
success: (res) => {
if(res.confirm){
uni.removeStorage({
key:"searchData"
});
this.searchData=[];
}
}
})
}
}
}
</script>
<style lang="less">
.search-item{
padding: 20rpx;
}
.search-title{
display: flex;
justify-content: space-between;
}
.search-name{
padding: 4rpx 24rpx;
background-color: #E1E1E1;
display: inline-block;
border-radius: 26rpx;
margin: 10rpx;
}
.search-end{
text-align: center;
}
</style>
search-list.vue
<template>
<view class="search-list">
<ShopList :keyword='keyword'></ShopList>
</view>
</template>
<script>
import ShopList from '@/components/common/ShopList.vue'
export default {
data() {
return {
keyword:""
};
},
onLoad(e) {
// 获取传递过来的参数
this.keyword = e.keyword;
// APP端 通过webView的方式改变 标题输入框的值
// #ifdef APP-PLUS
var webView = this.$mp.page.$getAppWebview();
webView.setTitleNViewSearchInputText(e.keyword);
console.log(e.keyword);
// #endif
},
components:{
ShopList
}
}
</script>
<style lang="scss">
.search-list{
width: 100%;
}
</style>
Ship List.vue
<template>
<view class="shop-list">{{keyword}}
<view class="shop-title f-color">
<view class="shop-item"
v-for="(item,index) in shopList.data"
:key="index"
@tap="changeTab(index)"
>
<view :class="shopList.currentIndex==index?'f-active-color':''">{{item.name}}</view>
<view class="shop-icon">
<view class="iconfont icon-shangjiantou up"
:class="item.status===1?'f-active-color':''"
></view>
<view class="iconfont icon-xiajiantou down"
:class="item.status===2?'f-active-color':''"
></view>
</view>
</view>
</view>
<Lines></Lines>
<CommodityList :dataList="dataList"></CommodityList>
</view>
</template>
<script>
import Lines from '@/components/common/Lines.vue'
import CommodityList from './CommodityList.vue'
export default {
props:{
keyword:String
},
data() {
return {
shopList:{
currentIndex:0,
data:[
{name:'价格',status:1},
{name:'折扣',status:0},
{name:'品牌',status:0}
]
},
dataList:[
{
id:1,
imgUrl:"../../static/logo.png",
name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",
pprice:"299",
oprice:"659",
discount:"5.2"
},
{
id:2,
imgUrl:"../../static/logo.png",
name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",
pprice:"299",
oprice:"659",
discount:"5.2"
},{
id:3,
imgUrl:"../../static/logo.png",
name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",
pprice:"299",
oprice:"659",
discount:"5.2"
},
{
id:4,
imgUrl:"../../static/logo.png",
name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",
pprice:"299",
oprice:"659",
discount:"5.2"
},
]
};
},
components:{
Lines,
CommodityList
},
methods:{
// 点击切换颜色
changeTab(index){
// 索引值
let idx = this.shopList.currentIndex;
// 具体哪一个对象
let item = this.shopList.data[idx];
if(idx == index){
return item.status = item.status === 1 ? 2 : 1
}
// 新值
let newItem = this.shopList.data[index];
item.status = 0; //旧的回复默认
this.shopList.currentIndex = index;
newItem.status = 1; // 新的给颜色
}
}
}
</script>
<style lang="scss">
.shop-title{
display:flex;
}
.shop-item{
flex:1;
display: flex;
justify-content: center;
align-items: center;
height: 80rpx;
}
.shop-icon{
position: relative;
margin-left: 10rpx;
}
.iconfont{
width: 16rpx;
height: 8rpx;
position: absolute;
left: 0;
}
.up{
top: -25rpx;
}
.down{
top: -5rpx;
}
</style>