1 新建数据表
2 后端连接器按照请求查询数据并返回给前端
3 前端传递参数给后端获取需要的数据
4 通过组件展示实现功能
<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"
@tap="toSearchList(item)"
>
{{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{
this.toSearchList(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=[];
}
}
})
},
// 点击搜索记录进入页面
toSearchList(item){
uni.navigateTo({
url:'../search-list/search-list?keyword='+item
})
}
}
}
</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
// let view = uni.createSelectorQuery().select(".uni-input-input");
// console.log(view);
},
components:{
ShopList
}
}
</script>
<style lang="scss">
.search-list{
width: 100%;
}
</style>
服务器端代码,链接数据库并按照传递的参数请求相应的数据
nodeJS端文件 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' });
});
/* GET databases goods. */
router.get('/api/goods/search', function(req, res, next) {
/*
desc 降序 asc 升序
*/
// 获取对象的key
let [goodsName,orderName] = Object.keys(req.query);
// name参数的值
let name = req.query.name;
// orderName的key值
let order = req.query[orderName];
let sql = "select * from goods_search";
if(!(name == undefined || orderName == undefined || order == undefined)){
sql = "select * from goods_search where name like '%"+name+"%' order by "+orderName+" "+order;
}
connection.query(sql,function(error,results,fields){
res.send({
code:"0",
data:results
});
})
});
/* 首页第一次触底的数据 */
router.get('/api/index_list/1/data/2', function(req, res, next) {
res.send({
code:"0",
data:[
{
type:"commodityList",
data:[
{
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"
},
]
},
]
});
});
/* 运动户外第二次触底的数据 */
router.get('/api/index_list/2/data/3', function(req, res, next) {
res.send({
code:"0",
data:[
{
type:"commodityList",
data:[
{
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"
},
]
},
]
});
});
/* 运动户外第一次触底的数据 */
router.get('/api/index_list/2/data/2', function(req, res, next) {
res.send({
code:"0",
data:[
{
type:"commodityList",
data:[
{
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"
},
]
},
]
});
});
/* 运动户外第一次加载的数据 */
router.get('/api/index_list/2/data/1', function(req, res, next) {
res.send({
code:"0",
data:[
{
type:"bannerList",
imgUrl:"../../static/img/b3.jpg",
},
{
type:"iconsList",
data:[
{imgUrl:"../../static/logo.png",name:"运动户外"},
{imgUrl:"../../static/logo.png",name:"运动户外"},
{imgUrl:"../../static/logo.png",name:"运动户外"},
{imgUrl:"../../static/logo.png",name:"运动户外"},
{imgUrl:"../../static/logo.png",name:"运动户外"},
{imgUrl:"../../static/logo.png",name:"运动户外"},
{imgUrl:"../../static/logo.png",name:"运动户外"},
{imgUrl:"../../static/logo.png",name:"运动户外"}
]
},
{
type:"hotList",
data:[
{
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"
}
]
},
{
type:"shopList",
data:[
{
bigUrl:"../../static/img/b3.jpg",
data:[
{
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"
}
]
}
],
},
{
type:"commodityList",
data:[
{
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"
},
]
},
]
});
});
/* 服饰内衣第一次加载的数据 */
router.get('/api/index_list/3/data/1', function(req, res, next) {
res.send({
code:"0",
data:[
{
type:"bannerList",
imgUrl:"../../static/img/b3.jpg",
},
{
type:"iconsList",
data:[
{imgUrl:"../../static/logo.png",name:"服饰内衣"},
{imgUrl:"../../static/logo.png",name:"服饰内衣"},
{imgUrl:"../../static/logo.png",name:"服饰内衣"},
{imgUrl:"../../static/logo.png",name:"服饰内衣"},
{imgUrl:"../../static/logo.png",name:"服饰内衣"},
{imgUrl:"../../static/logo.png",name:"服饰内衣"},
{imgUrl:"../../static/logo.png",name:"服饰内衣"},
{imgUrl:"../../static/logo.png",name:"服饰内衣"}
]
},
{
type:"hotList",
data:[
{
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"
}
]
},
{
type:"shopList",
data:[
{
bigUrl:"../../static/img/b3.jpg",
data:[
{
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"
}
]
}
],
},
{
type:"commodityList",
data:[
{
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"
},
]
},
]
});
});
/* 首页推荐数据 */
router.get('/api/index_list/data', function(req, res, next) {
res.send({
"code":0,
"data":{
topBar:[
{id:1,name:'推荐'},
{id:2,name:'运动户外'},
{id:3,name:'服饰内衣'},
{id:4,name:'鞋靴箱包'},
{id:5,name:'美妆个护'},
{id:6,name:'家居数码'},
{id:7,name:'食品母婴'}
],
data:[
{
type:"swiperList",
data:[
{imgUrl:'/static/img/b3.jpg'},
{imgUrl:'/static/img/b3.jpg'},
{imgUrl:'/static/img/b3.jpg'}
]
},{
type:"recommendList",
data:[
{
bigUrl:"../../static/img/b3.jpg",
data:[
{imgUrl:'../../static/logo.png'},
{imgUrl:'../../static/logo.png'},
{imgUrl:'../../static/logo.png'}
]
},{
bigUrl:"../../static/img/b3.jpg",
data:[
{imgUrl:'../../static/logo.png'},
{imgUrl:'../../static/logo.png'},
{imgUrl:'../../static/logo.png'}
]
}
]
},{
type:"commodityList",
data:[
{
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"
},
]
},
]
}
})
});
module.exports = router;
将组件中的数据改为动态获取
shopList.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 $http from '@/common/api/request.js'
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,key:"pprice"},
{name:'折扣',status:0,key:"discount"},
{name:'品牌',status:0,key:"brand"}
]
},
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"
},
*/
]
};
},
computed:{
orderBy(){
// 拿到当前对象
let obj = this.shopList.data[this.shopList.currentIndex];
let val = obj.status === 1 ? "asc" : "desc";
return {
[obj.key]:val
}
}
},
components:{
Lines,
CommodityList
},
mounted() {
this.getData();
},
methods:{
// 请求数据
getData(){
$http.request({
url:"/goods/search",
data:{
name:this.keyword,
...this.orderBy
}
}).then((res)=>{
this.dataList = res;
}).catch(()=>{
uni.showToast({
title:'请求失败',
icon:'none'
})
})
},
// 点击切换颜色
changeTab(index){
// 点击排序 => 重新请求了数据
this.getData();
// 索引值
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>
通过nodejs连接池连接到Mysql数据库
数据库连接
sql.js
var mysql = require('mysql');
var connection = mysql.createPool({
host :'127.0.0.1',
user :"root",
password:"123123123",
database:"aolai_test",
multipleStatements:true //允许执行多条语句
});
module.exports = connection;
manifest.json 配置文件: appid、logo…
pages.json 配置文件: 导航、 tabbar、 路由
main.js vue初始化入口文件
App.vue 全局配置:样式、全局监视
static 静态资源:图片、字体图标
page 页面
components 组件
common 公共文件:全局css文件 || 全局js文件
三 搜索数据
1.1 接口功能
通过搜索关键词获取到数据
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 | 搜索到的数据 |
1.7 接口示例
{
"code":'0',
"data":[
{
id:1,
imgUrl:"../../static/logo.png",
name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",
pprice:"299",
oprice:"659",
discount:"5.2"
}
]
}
数据库中的数据表和结构(例子使用的是mysql数据库,请自行搭建)
实际效果图,排序功能完善,点击已经搜索词也可以搜索