搜索相关功能
一、进入搜索页面
1.1 在pages下创建搜索页面为:search
1.2 在index.vue中点击进入搜素页面
onNavigationBarButtonTap(e){if(e.float=='left'){uni.navigateTo({url:'/pages/search/search'})}},
1.3 在pages.json中配置搜索页面头部
{"path" : "pages/search/search","style" : {"navigationBarBackgroundColor":"#FFFFFF","app-plus":{"scrollIndicator":"none","titleNView":{"searchInput":{"placeholder":"nike","disabled":false,"align":"left","autoFocus":true,"borderRadius":"15px","backgroundColor":"#F7F7F7","placeholderColor":"#B3B3B3"},"buttons":[{"float":"right","color":"#636263","text":"搜索","fontSize":"16px","width":"60px"}]}}}}
参考uniapp文档
注:api命名不能和默认组件冲突
二、搜索页面内容布局
1.1 页面布局代码:
<template><view class='search'><Lines /><view class='search-item'><view class='search-title'><view class='f-color'>最近搜索</view><view class='iconfont icon-iconset0213'></view></view><view><view class='search-name f-color'>四件套</view><view class='search-name f-color'>面膜</view></view></view><view class='search-item'><view class='search-title'><view class='f-color'>热门搜索</view></view><view><view class='search-name f-color'>四件套</view><view class='search-name f-color'>面膜</view></view></view></view>
</template><script>import Lines from '@/components/common/Lines.vue'export default {data() {return {}},components:{Lines},methods: {}}
</script><style scoped>
.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;
}
</style>
三、进入搜索结果页
1.1 在pages中创建search-list页面
1.2 在search.vue中加入:跳转到search-list页面
onNavigationBarButtonTap(e){if(e.float === 'right'){uni.navigateTo({url:"../search-list/search-list"})}},
1.3 在pages.json中配置搜索结果页面的头部
{"path" : "pages/search-list/search-list","style" : {"navigationBarBackgroundColor":"#FFFFFF","app-plus":{"scrollIndicator":"none","titleNView":{"searchInput":{"placeholder":"nike","disabled":false,"align":"left","borderRadius":"15px","backgroundColor":"#F7F7F7","placeholderColor":"#B3B3B3"},"buttons":[{"float":"right","color":"#636263","text":"筛选","fontSize":"16px","width":"60px"}]}}}}
四、搜索结果页布局和封装
1.1 在components下的common目录中新建ShopList.vue组件
1.2 上半部分布局,下半部分调用之前引入创建的商品列表组件
1.3 布局代码如下:
<template><view class='shop-list'><view class='shop-title f-color'><view class='shop-item'><view>价格</view><view class='shop-icon'><view class='iconfont icon-shangjiantou up'></view><view class='iconfont icon-xiajiantou down'></view></view></view><view class='shop-item'><view>折扣</view><view class='shop-icon'><view class='iconfont icon-shangjiantou up'></view><view class='iconfont icon-xiajiantou down'></view></view></view><view class='shop-item'><view>品牌</view><view class='shop-icon'><view class='iconfont icon-shangjiantou up'></view><view class='iconfont icon-xiajiantou down'></view></view></view></view><Lines /><CommodityList :dataList='dataList'></CommodityList></view>
</template><script>
import Lines from '@/components/common/Lines.vue'
import CommodityList from './CommodityList.vue'
export default {data() {return {dataList:[{id:1,imgUrl:"../../static/img/commodity1.jpg",name:"大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/img/commodity2.jpg",name:"大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/img/commodity3.jpg",name:"大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",pprice:"299",oprice:"659",discount:"5.2"},{id:4,imgUrl:"../../static/img/commodity4.jpg",name:"大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",pprice:"299",oprice:"659",discount:"5.2"}]}},components:{Lines,CommodityList},methods: {}}
</script><style scoped>
.shop-title{display: flex;
}
.shop-item{flex:1;display: flex;justify-content: center;align-items: center;height: 80rpx;
}
.shop-icon{position: relative;margin-lef:10rpx;
}
.iconfont{width:16rpx;height: 8rpx;position: absolute;left:0;
}
.up{top:-34rpx;
}
.down{top:-24rpx;
}
</style>
五、搜索结果页排序功能
Shoplist.vue
<view class='shop-title f-color'><view class='shop-item'v-for="(item,index) in shopList.data":key='index'@tap='changTab(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>
选中变色判断方法
0,1 list是否被选择
1,2 上下箭头
shopList:{currentIndex:0,data:[{name:"价格",status:1},{name:"折扣",status:0},{name:"品牌",status:0}]
methods: {changTab(index){//索引值let idx = this.shopList.currentIndex;//idx//具体哪一个对象let item = this.shopList.data[idx];if( idx == index ){return item.status = item.status === 1 ? 2:1; //data的状态值}//新的值,let newItem = this.shopList.data[index];//indexitem.status = 0;this.shopList.currentIndex = index;newItem.status = 1;}}
六、搜索关键词判断和隐藏键盘
解决问题
- 判断关键词,如果关键词为空需要提示
- 进入搜索结果页需要隐藏键盘
- 点击软键盘的搜索也可以进入到搜索结果页面
- 搜索词
4.1用本地存储记录
4.2搜索词重复判断
4.3最新搜索到词循序前置 - 清除最近搜索记录=>提示无搜索记录
- 搜索词不通过展示的数据不同
- 排序=>链接数据库,sql语句
uniapp 页面生命周期的
<script>import Lines from '@/components/common/Lines.vue'export default {data() {return {keyword:''}},//监听input输入内容onNavigationBarSearchInputChanged(e){this.keyword = e.text;},//点击顶栏中的搜索按钮onNavigationBarButtonTap(e){this.search(); },//监听软键盘的搜索按钮点击的onNavigationBarSearchInputConfirmed(){this.search(); },components:{Lines},methods: {//判断关键词是否为空和跳转页面的search(){if( this.keyword ==="" ){return uni.showToast({title:"关键词不能为空",icon:"none"})}else{uni.navigateTo({url:"../search-list/search-list"})}uni.hideKeyboard();//隐藏键盘}}}
</script>
七、搜索词记录
- 用本地存储记录
- 搜索词重复判断
- 最新搜索到词循序前置
<view v-else class='search-end'>暂无搜索记录</view>
//页面加载的时候onLoad(){uni.getStorage({key:"searchData",success: (res) => {this.searchData = JSON.parse( res.data );}})},
//记录最近搜索词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] );//删除再添加}//uniapp api 数据缓存uni.setStorage({key:"searchData",data: JSON.stringify(this.searchData)})
八、清除最近搜索记录
api: confirmText
//清除搜索记录clearHistory(){uni.showModal({title:"重要提示",content:'是否要清除搜索记录',cancelText:'取消',confirmText:"确定",success: (res) => {if(res.confirm){uni.removeStorage({key:"searchData"})this.searchData=[];}}})}
九、搜索词传值
search-list.vue
onLoad(e) {this.keyword = e.keyword;// #ifdef APP-PLUS uniapp 方法 动态修改原生导航栏var webView = this.$mp.page.$getAppWebview(); webView.setTitleNViewSearchInputText( e.keyword);//接收// #endif},
search.vue
传值
//判断关键词是否为空和跳转页面的search(){if( this.keyword ==="" ){return uni.showToast({title:"关键词不能为空",icon:"none"})}else{uni.navigateTo({url:"../search-list/search-list?keyword="+this.keyword+""})}uni.hideKeyboard();this.addSearch();},
子传父
search-list.vue
<template><view><ShopList :keyword='keyword'></ShopList></view>
</template>
Shoplist.vue
props:{keyword:String},
十、搭建数据库表
接口文档
1.2 URL
地址/api/goods/search
1.3 支持格式
JSON
1.4 HTTP请求方式
GET
1.5 请求参数
参数 | 必选 | 类型 | 说明 | |
---|---|---|---|---|
name | 是 | string | 搜索的关键词 | |
pprice 或 discount | 否 | string | 排序 |
1.6 返回字段
返回字段 | 字段类型 | 说明 | |
---|---|---|---|
code | string | 返回结果状态。0:正常;1:错误。 | |
data | object | 搜索到的数据 |
{
“code”: ‘0’,
“data”:[{id:1,ImgUrl:"../../static/img/commodity1.jpg",name:"大姨绒",pprice:"299",oprice:"659",discount:"5.2"}]
}
npm install mysql
mkdir db
vim sql.js
var mysql = require('mysql');
var connection = mysql.createConnection({host : 'localhost',user : 'root',password : 'root',database : 'aolai'
});
module.exports = connection;
index.js
var express = require('express');
var router = express.Router();
var connection = require('../db/sql.js');/* GET home page. */
router.get('/', function(req, res, next) {res.render('index', { title: 'Express' });
});router.get("/api/goods/search",function(req, res, next) {//desc降序 asc升序//获取对象的keylet [goodsName,orderName] = Object.keys(req.query);//name参数的值let name = req.query.name;//orderName的key的值let order = req.query[orderName];connection.query("select * from goods_search where name like '%"+name+"%' order by "+orderName+" "+order+"", function (error, results, fields) {if (error) throw error;res.send({code:"0",data:results})});});
十一、请求搜索接口
显示不同搜索页
Shoplist.vue
mounted(){this.getData();},methods: {//请求数据数据getData(){$http.request({url:"/goods/search",data:{name:this.keyword,pprice:"desc"}}).then((res)=>{this.dataList = res;}).catch(()=>{uni.showToast({title:'请求失败',icon:'none'})})},
search-list.vue
<view class='search-name f-color'v-for='(item,index) in searchData':key='index'@tap='toSearchList(item)'>{{item}}
</view>
//点击搜索记录进入页面toSearchList(item){uni.navigateTo({url:"../search-list/search-list?keyword="+item+""})}
//判断关键词是否为空和跳转页面的search(){if( this.keyword ==="" ){return uni.showToast({title:"关键词不能为空",icon:"none"})}else{this.toSearchList(this.keyword);//use}uni.hideKeyboard();this.addSearch();},
十二、商品排序
Shoplist.vue
添加
computed:{orderBy(){//拿到当前对象let obj = this.shopList.data[this.shopList.currentIndex];let val = obj.status === 1 ? "asc" : "desc" ;return {[obj.key]:val}}},
修改为动态的排序
//请求数据数据getData(){$http.request({url:"/goods/search",data:{name:this.keyword,...this.orderBy}
加载页面数据多怎么办,limit限制+分页