搜索页面布局
- 在src/router/index.js中配置路由,在src/views新建Search.vue文件
{
path: "/search",
name: "Search",
component: () =>
import("../views/Search.vue"),
}
- 在Header.vue中添加点击事件,js代码如下:
<script>
export default{
methods:{
goSearch(){
this.$router.push('/search')
}
}
}
</script>
- 在sec/components/search创建Header.vue文件,在Search.vue中引入Header,Tabbar,Like组件,挂载
- 页面布局
…xie bu xia qu le…
渲染搜索结果(后端)
-
新建vue_store数据库,新建goods_list 表
-
后端安装mysq
l–cnpm install mysql -S
– -
node连接数据库,在server/db目录下新建sql.js,进行数据库配置
const mysql = require('mysql');
let connection = mysql.createConnection({
host:'localhost',
user:'root',
password:"root123",
database:'vue_store'
})
module.exports = connection;
- 在server/routes/index.js中引用,并设置接口,对搜索商品的价格和销量实现排序
–var connection = require('../db/sql.js');
–
//查询商品数据接口
router.get('/api/goods/shopList',function(req,res,next){
//前端给后端的数据
let [searchName,orderName] = Object.keys(req.query);
let [name,order] = Object.values(req.query);
connection.query('select * from goods_list where name like "%'+name+'%" order by '+orderName+' '+order+'',function(error,results){
res.send({
code:0,
data:results
})
})
})
- 在src/views/search/Search-list.vue中配置接口,Search-list.vue完整代码如下:
<template>
<div class='search-list'>
<div class='headers'>
<Header></Header>
<ul>
<li
v-for='(item,index) in searchList.data'
:key='index'
@click='changeTab(index)'
>
<div :class=' searchList.currentIndex == index ?"active":"" '>{{item.name}}</div>
<div class='search-filter' v-if='index !=0 '>
<i
class='iconfont icon-arrow_up_fat'
:class=' item.status == 1 ? "active" : ""'
></i>
<i
class='iconfont icon-arrow_down_fat'
:class=' item.status == 2 ? "active" : ""'
></i>
</div>
</li>
</ul>
</div>
<section>
<ul v-if='goodsList.length'>
<li
v-for='(item,index) in goodsList'
:key='index'
>
<img v-lazy="item.imgUrl" alt="">
<h3>{{item.name}}</h3>
<div class='price'>
<div>
<span>¥</span>
<b>{{item.price}}</b>
</div>
<div>立即购买</div>
</div>
</li>
</ul>
<h1 v-else>暂无数据...</h1>
</section>
<Tabbar></Tabbar>
</div>
</template>
<script>
import Header from '@/components/search/Header.vue'
import Tabbar from '@/components/common/Tabbar.vue'
import http from '@/common/api/request.js'
export default{
data () {
return {
goodsList:[],
searchList:{
currentIndex:0,
data:[
/*
status:0 都不亮
status:1 上箭头亮
status:2 下箭头亮
*/
{name:'综合',key:'zh'},
{name:'价格',status:0,key:'price'},
{name:'销量',status:0,key:'num'}
]
}
}
},
computed:{
orderBy(){
//知道当前是哪一个对象
let obj = this.searchList.data[this.searchList.currentIndex];
//针对于状态,判断是升序还是降序
let val = obj.status == '1' ? 'asc' : 'desc';
return {
[obj.key]:val
}
}
},
components:{
Header,
Tabbar
},
created(){
this.getData();
},
methods:{
getData(){
http.$axios({
url:'/api/goods/shopList',
params:{
searchName:this.$route.query.key,
...this.orderBy
}
}).then(res=>{
this.goodsList = res;
})
},
changeTab( index ){
this.searchList.currentIndex = index;
//点击的下标对应数据的哪一个
let item = this.searchList.data[index];
//取消所有的状态值===》都变成0
this.searchList.data.forEach((v,i)=>{
if( i != index ){
v.status = 0;
}
})
//当前点击的改变状态
if( index == this.searchList.currentIndex ){
item.status = item.status == 1 ? 2 : 1;
}
//发送请求进行数据排序
this.getData();
}
},
watch:{
$route(){
this.getData();
}
}
}
</script>
<style scoped lang='scss'>
.search-list{
display: flex;
flex-direction: column;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.headers ul{
display: flex;
justify-content: space-around;
padding:0.533333rem 0;
font-size:0.426666rem;
}
.headers ul li{
display: flex;
align-items: center;
}
.headers ul li > div{
padding:0 0.08rem;
}
.headers ul li .search-filter{
display: flex;
flex-direction: column;
}
section{
flex:1;
overflow: hidden;
ul{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
li {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-sizing: border-box;
width: 50%;
padding:0.266666rem;
}
}
}
section ul li img{
width: 4.533333rem;
height: 4.533333rem;
}
section ul li img[lazy=loading] {
background-color: #f7f7f7;
}
section ul li h3{
width: 100%;
font-size:0.373333rem;
color:#222;
font-weight: 400;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
section ul li .price{
display: flex;
justify-content: space-between;
padding:0.266666rem 0;
width: 100%;
font-size:14px;
}
section ul li .price div:first-child span{
font-size: 0.32rem;
color:#b0352f;
}
section ul li .price div:first-child b{
color:#b0352f;
font-size:0.426666rem;
}
section ul li .price div:last-child{
padding:0.08rem 0.16rem;
color:#fff;
background-color: #b0352f;
border-radius: 0.16rem;
}
.active{
color:red;
}
</style>
这里对axios进行了二次封装在request.js中,代码如下:
import { Indicator } from 'mint-ui';
import axios from 'axios'
import store from '@/store'
import router from '@/router'
export default{
common:{
method:'GET',
data:{},
params:{},
headers:{}
},
$axios( options={} ){
options.method = options.method || this.common.method;
options.data = options.data || this.common.data;
options.params = options.params || this.common.params;
options.headers = options.headers || this.common.headers;
//请求前==》显示加载中...
Indicator.open('加载中...');
//是否是登录状态
if( options.headers.token ){
options.headers.token = store.state.user.token;
if( !options.headers.token ){
router.push('/login');
}
}
return axios(options).then(v=>{
let data = v.data.data;
//如果token过期,重新登录
if( data.code == 1000 ){
Indicator.close();
return router.push('/login');
}
return new Promise((res,rej)=>{
if( !v ) return rej();
//结束===》关闭加载中
setTimeout(()=>{
Indicator.close();
},500)
res( data );
})
})
}
}
点击历史搜索,进入搜索结果页面
- 在src/views/search/Search-list.vue中添加点击事件
//点击历史搜索,进入搜索结果页面
goSearchList(item){
this.$router.push({
name:'list',
query:{
key:item
}
})
}
性能优化-懒加载
<img v-lazy="item.imgUrl" alt="">
img[lazy=loading] {
background-color: #f7f7f7;
}