Vue电商平台项目(4)

搜索页面布局

  1. 在src/router/index.js中配置路由,在src/views新建Search.vue文件
{
    path: "/search",
    name: "Search",
    component: () =>
      import("../views/Search.vue"),
  }
  1. 在Header.vue中添加点击事件,js代码如下:
<script>
	export default{
		methods:{
			goSearch(){
				this.$router.push('/search')
			}
		}
	}
</script>
  1. 在sec/components/search创建Header.vue文件,在Search.vue中引入Header,Tabbar,Like组件,挂载
  2. 页面布局
    …xie bu xia qu le…

渲染搜索结果(后端)

  1. 新建vue_store数据库,新建goods_list 表
    在这里插入图片描述

  2. 后端安装mysq
    l–cnpm install mysql -S

  3. 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;
  1. 在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
		})
	})
	
})
  1. 在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 );
            })
            
		})
		
	}
	
}

点击历史搜索,进入搜索结果页面

  1. 在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;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值