6商品相关页面

效果图

在这里插入图片描述


一、分类页顶栏

pages.json
新增配置

,{
            "path" : "pages/list/list",
            "style" : {
            	"navigationBarBackgroundColor":"#FFFFFF",
            	"app-plus":{
            		"scrollIndicator":"none",
            		"titleNView":{
            			"searchInput":{
            				"placeholder":"请输入关键字",
            				"disabled":true,
            				"align":"left",
            				"borderRadius":"15px",
            				"backgroundColor":"#F7F7F7",
            				"placeholderColor":"#B3B3B3"
            			}
            		}
            	}
            }
        }

页面生命周期

onNavigationBarSearchinputClicked监听原生标题栏搜索输入框点击事件

点击搜索栏,进入搜索页

list.vue

//input输入框点击事件
		onNavigationBarSearchInputClicked(){
			uni.navigateTo({
				url:'../search/search'
			})
		}

引入lines

<template>
	<view class='list'>
		<Lines />
	</view>
</template>

<script>
import Lines from '@/components/common/Lines.vue'
	export default {
		data() {
			return {
				
			}
		},
		components:{
			Lines
		}

二、构建商品分类页数据(后端)

1.1接口功能
获取商品分类
1.2URL
地址/api/goods/list
1.3支持格式
JSON
1.4 HTTP请求方式
GET
1.5 请求参数

参数必选类型说明

1.6 返回字段

返回字段字段类型说明
codestring返回结果状态。0:正常;1:错误。
dataobject商品分类数据

1.7 接口示例

{
	“code”:0,
	“data”: [
	 {
		Id:1,
		name:’家居家纺’,
		data:[
		{
			name:’上装’,
			List:[
				{
					id:1
					Name:’夹克’,
					imgUrl:’xx.jpeg’
				}
			]
		}
		]
	}
	]
}

在 server/routes/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/list', function(req, res, next) {
   res.json({
	   code:0,
	   data:[
		   {
			   id:1,
			   name:"家居家纺",
			   data:[
				   {
					   name:"家纺",
					   list:[
						   {
							   id:1,
							   name:"毛巾/浴巾",
							   imgUrl:"../../static/img/list1.jpg"
						   },
						   {
							   id:2,
							   name:"枕头",
							   imgUrl:"../../static/img/list1.jpg"
						   }
					   ]
				   },
				   {
					   name:"生活用品",
					   list:[
						   {
							   id:1,
							   name:"浴室用品",
							   imgUrl:"../../static/img/list1.jpg"
						   },
						   {
							   id:2,
							   name:"洗晒",
							   imgUrl:"../../static/img/list1.jpg"
						   }
					   ]
				   }
			   ]
		   },
		   {
			   id:2,
			   name:"女装",
			   data:[
				   {
					   name:"裙装",
					   list:[
						   {
							   id:1,
							   name:"半身裙",
							   imgUrl:"../../static/img/list1.jpg"
						   },
						   {
							   id:2,
							   name:"连衣裙",
							   imgUrl:"../../static/img/list1.jpg"
						   }
					   ]
				   },
				   {
					   name:"上衣",
					   list:[
						   {
							   id:1,
							   name:"T恤",
							   imgUrl:"../../static/img/list1.jpg"
						   },
						   {
							   id:2,
							   name:"衬衫",
							   imgUrl:"../../static/img/list1.jpg"
						   }
					   ]
				   }
			   ]
		   }
	   ]
   })
});

三、商品分类内容布局

<template>
	<view>
		<Lines />
		
		<view class='list'>
			
			<!--左侧滑动-->
			<scroll-view scroll-y="true" class='list-left'>
				<view v-for='i in 50' class='left-item'>
					<view class='left-name'>{{i}}</view>
				</view>
			</scroll-view>
			
			<!--右侧滑动-->
			<scroll-view scroll-y="true" class='list-right'>
				<view class='righ-list'>
					<view class='list-title'>家纺</view>
					<view class='right-content'>
						<view class='right-item'>
							<image class='right-img' src="../../static/img/list1.jpg" mode=""></image>
							<view class='right-name'>毛巾</view>
						</view>
						<view class='right-item'>
							<image class='right-img' src="../../static/img/list1.jpg" mode=""></image>
							<view class='right-name'>毛巾</view>
						</view>
						<view class='right-item'>
							<image class='right-img' src="../../static/img/list1.jpg" mode=""></image>
							<view class='right-name'>毛巾</view>
						</view>
						<view class='right-item'>
							<image class='right-img' src="../../static/img/list1.jpg" mode=""></image>
							<view class='right-name'>毛巾</view>
						</view>
					</view>
				</view>
				<view class='righ-list'>
					<view class='list-title'>家纺</view>
					<view class='right-content'>
						<view class='right-item'>
							<image class='right-img' src="../../static/img/list1.jpg" mode=""></image>
							<view class='right-name'>毛巾</view>
						</view>
						<view class='right-item'>
							<image class='right-img' src="../../static/img/list1.jpg" mode=""></image>
							<view class='right-name'>毛巾</view>
						</view>
						<view class='right-item'>
							<image class='right-img' src="../../static/img/list1.jpg" mode=""></image>
							<view class='right-name'>毛巾</view>
						</view>
					</view>
				</view>
				<view class='righ-list'>
					<view class='list-title'>家纺</view>
					<view class='right-content'>
						<view class='right-item'>
							<image class='right-img' src="../../static/img/list1.jpg" mode=""></image>
							<view class='right-name'>毛巾</view>
						</view>
					</view>
				</view>
			</scroll-view>
			
		</view>
		
	</view>
</template>

<script>
	import Lines from '@/components/common/Lines.vue'
	export default {
		data() {
			return {
				
			}
		},
		components:{
			Lines
		},
		methods: {
			
		},
		//input输入框点击事件
		onNavigationBarSearchInputClicked(){
			uni.navigateTo({
				url:'../search/search'
			})
		}
	}
</script>

<style scoped>
.list{
	display: flex;
}
.list-left{
	width: 200rpx;
}
.left-item{
	border-bottom:2rpx solid #FFFFFF;
	font-size:28rpx;
	font-weight: bold;  /*粗体字*/
	background-color: #F7F7F7;
}
.left-name{
	padding:30rpx 6rpx;
	text-align: center;
}
.left-name-active{
	border-left:8rpx solid #49BDFB;
	background-color: #FFFFFF;
}
.list-right{
	flex:1;
	padding-left:30rpx;
}
.list-title{
	font-weight: bold;
	padding:30rpx 0;
}
.right-content{
 /*换行*/
	display: flex;
	flex-wrap: wrap;
}
.right-item{
 /*图片大小*/
	width: 150rpx;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding:10rpx;
}
.right-name{
 /*离图片空点*/
	padding:16rpx 0;
}
.right-img{
	width: 150rpx;
	height: 150rpx;
}
</style>

四、获取高度和点击添加样式

问题:
1、左右滑动一起动,互相没有给一个对应的高度值
可视区域高度获取

<!--左侧滑动-->
			<scroll-view scroll-y="true" class='list-left' :style="'height:'+clentHeight+'px;'">

<!--右侧滑动-->
			<scroll-view scroll-y="true" class='list-right' :style="'height:'+clentHeight+'px;'">

//获取可视高度
		onReady() {
			uni.getSystemInfo({
				success: (res) => {
					this.clentHeight = res.windowHeight - this.getClientHeight();
				}
			})
		},

methods: {
			//获取可视区域高度【兼容】
			getClientHeight(){
				const res = uni.getSystemInfoSync();
				const system = res.platform;
				if( system ==='ios' ){
					return 44+res.statusBarHeight;
				}else if( system==='android' ){
					return 48+res.statusBarHeight;
				}else{
					return 0;
				}
			},

左侧滑块点击显示事件

<!--左侧滑动-->
			<scroll-view scroll-y="true" class='list-left' :style="'height:'+clentHeight+'px;'">
				<view v-for='i in 50' class='left-item' @tap="changeLeftTab(i)">
					<view class='left-name' 
						:class=' activeIndex ===i ?"left-name-active":"" '
					>{{i}}</view>
				</view>
			</scroll-view>

/******/

data() {
			return {
				clentHeight:0,
				activeIndex:1
			}
		},

//左侧点击事件
			changeLeftTab(index){
				this.activeIndex = index;
			}

五、商品分类对应的数据渲染

list.vue

<!--左侧滑动-->
			<scroll-view scroll-y="true" class='list-left' :style="'height:'+clentHeight+'px;'">
				<view
					v-for='(item,index) in leftData'
					:key='index'
					@tap="changeLeftTab(index,item.id)"
				>
					<view class='left-name' 
						:class=' activeIndex ===index ?"left-name-active":"left-item" '
					>{{item.name}}</view>
				</view>
			</scroll-view>

<!--右侧滑动-->
<scroll-view scroll-y="true" class='list-right' :style="'height:'+clentHeight+'px;'">
	
	<view 
		class='righ-list'
		v-for='(item,index) in rightData'
		:key='index'
	>   <!--遍历页-->
		<block v-for='(k,i) in item'>
		<!--细分类名-->
			<view class='list-title'>{{k.name}}</view>
			<view class='right-content'>
				<view class='right-item' v-for='(j,idx) in k.list' :key='idx'>
				<!--遍历获取数据中的图片-->
					<image class='right-img' :src="j.imgUrl" mode=""></image>
					<view class='right-name'>{{j.name}}</view>
				</view>
			</view>
		</block>
	</view>
data() {
			return {
				clentHeight:0,
				activeIndex:0,
				//左侧数据
				leftData:[],
				//右侧数据
				rightData:[]
			}
		},
methods: {
			//请求数据方法
			getData(id){
				if(  id === (this.activeIndex+1) ){
					return;
				}
				//避免重复获取数据
				
				$http.request({
					url:"/goods/list"
				}).then((res)=>{
					let leftData = [];
					let rightData = []
					res.forEach(v=>{
						leftData.push({
							id:v.id,
							name:v.name
						})
						//如果点击的id值相同
						if(    v.id  === (this.activeIndex+1) ){
							rightData.push(v.data);
						}
					})
					this.leftData = leftData;
					this.rightData = rightData;
					//重复点击左侧出对应的右侧
					
				}).catch(()=>{
					uni.showToast({
						title:'请求失败',
						icon:'none'
					})
				})	
			},

六、商品详情页

在这里插入图片描述

点击和跳转已经实现

mkdir /pages/details

vim details.vue

配置 pages.json
app-plus 里 title-view
type 导航栏样式。“default”-默认样式; “transparent”-滚动透明渐变;“float”-悬浮导航栏。

{
            "path" : "pages/details/details",
            "style" : {
				"navigationBarTitleText": "商品详情",
				"app-plus":{
					"titleNView":{
						"type":"transparent",
						"buttons":[
							{
								"type":"menu"
							},
							{
								"type":"share"
							}
						]
					}
				}
			}
        }
<!-- 单个商品组件 -->
		
		<view class='commodity-item' 
			v-for="(item,index) in dataList"
			:key='index'
			:style="'width:'+itemW+';'"
			@tap='goDetails'
		>
methods:{
		goDetails(){
			uni.navigateTo({
				url:'../../pages/details/details'
			})
		}
	}

七、商品详情页内容块布局

<template>
	<view class='details'>
		<!--商品图-->
		<swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
			<swiper-item v-for='(item,index) in swiperList' :key='index'>
				<view class="swiper-item">
					<image class='swiper-img' :src="item.imgUrl" mode=""></image>
				</view>
			</swiper-item>
		</swiper>
		<!--价格和名称-->
		<view class='details-goods'>
			<view class='goods-pprice'>¥399.00</view>
			<view class='goods-oprice'>¥599.00</view>
			<view class='goods-name'>大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须</view>
		</view>
		<!--商品详情图-->
		<view>
			<view><image class='details-img' src="../../static/img/detail1.jpg" mode=""></image></view>
			<view><image class='details-img' src="../../static/img/detail2.jpg" mode=""></image></view>
			<view><image class='details-img' src="../../static/img/detail3.jpg" mode=""></image></view>
			<view><image class='details-img' src="../../static/img/detail4.jpg" mode=""></image></view>
			<view><image class='details-img' src="../../static/img/detail5.jpg" mode=""></image></view>
		</view>
		
		<Card cardTitle='看了又看'></Card>
		<CommodityList :dataList='dataList'></CommodityList>
		
	</view>
</template>

script

data() {
			return {
				swiperList:[
					{imgUrl:"../../static/img/details1.jpeg"},
					{imgUrl:"../../static/img/details2.jpeg"},
					{imgUrl:"../../static/img/details3.jpeg"}
				],

style

.swiper-img{
	width: 100%;
	height: 700rpx;
}
.details-goods{
	text-align: center;
	font-weight: bold;
	font-size:36rpx;
	padding:10rpx 0;
}
.details-img{
	width: 100%;
}
</style>

八、固定底部布局

<!--底部-->
		<view class='details-foot'>
			<view class='iconfont icon-xiaoxi'></view>
			<view class='iconfont icon-gouwuche'></view>
			<view class='add-shopcart'>加入购物车</view>
			<view class='purchase'>立即购买</view>
		</view>

style

.details-foot .iconfont{
	width:60rpx;
	height: 60rpx;
	border-radius: 100%;
	background-color: #000000;
	color:#FFFFFF;
	text-align: center;
	margin:0 10rpx;
}
.add-shopcart{
	margin:0 40rpx;
	padding:6rpx 30rpx;
	background-color: #000000;
	color:#FFFFFF;
	border-radius: 40rpx;
}
.purchase{
	margin:0 40rpx;
	padding:6rpx 30rpx;
	background-color: #49BDFB;
	color:#FFFFFF;
	border-radius: 40rpx;
}

九、底部滑块动画效果

在这里插入图片描述
deatils.vue

template

<!--底部弹出层-->
		
		<view class="pop" v-show='isShow' @touchmove.stop.prevent=''>
			<!--蒙层-->
			<view class='pop-mask' @tap='hidePop'></view>
			<!--内容块-->
			<view class='pop-box' :animation="animationData"></view>
		</view>

script
api: uni.createAnimation 赋值 animationData 产生效果

methods: {
			showPop(){
				var animation = uni.createAnimation({
				   duration: 200
				})
				animation.translateY(600).step();
				this.animationData = animation.export();
				this.isShow = true;
				setTimeout(()=>{
					animation.translateY(0).step();
					this.animationData = animation.export();
				},200)
			},
			hidePop(){
				var animation = uni.createAnimation({
				   duration: 200
				})
				animation.translateY(600).step();
				this.animationData = animation.export();
				this.isShow = true;
				setTimeout(()=>{
					animation.translateY(0).step();
					this.isShow = false;
				},200)
			}
		}

style

.pop{
	position: fixed;
	left:0;
	top:0;
	width: 100%;
	height: 100%;
	z-index: 9999;
}
.pop-mask{
	position: absolute;
	left:0;
	top:0;
	width: 100%;
	height: 100%;
	background-color: rgba(0,0,0,0.3);
}
.pop-box{
	position: absolute;
	left:0;
	bottom:0;
	width: 100%;
	height: 400px;
	background-color: #E80080;
}

小问题

:弹出动画后,详情页还在滑动,
@touchmove.stop.prevent=’ ’

十、完善购物车滑块

api:
UniNumberBox


		<!--底部弹出层-->
		
		<view class="pop" v-show='isShow' @touchmove.stop.prevent=''>
			<!--蒙层-->
			<view class='pop-mask' @tap='hidePop'></view>
			<!--内容块-->
			<view class='pop-box' :animation="animationData">
				<view>
					<image class='pop-img' src="../../static/img/Furnishing1.jpg" mode=""></image>
				</view>
				<view class='pop-num'>
					<view>购买数量</view>
					<UniNumberBox 
						min='1'
					></UniNumberBox>
				</view>
				<view class='pop-sub'>
					确定
				</view>
			</view>
		</view>
.pop-img{
	width: 260rpx;
	height: 260rpx;
}
.pop-num{
	padding:20rpx;
	display: flex;
	justify-content: space-between;
}
.pop-sub{
	line-height: 80rpx;
	background-color: #49BDFB;
	color:#FFFFFF;
	text-align: center;
}

十一、修改返回键行为

页面周期

//修改返回默认行为
		onBackPress(){
			if(this.isShow){
				this.hidePop();
				return true;
			}
		}

十二、商品详情对应数据

Commodity.vue

methods:{
		goDetails(id){
			uni.navigateTo({
				url:'../../pages/details/details?id='+id+''
			})
		}

details.vue

onLoad(e) {
			this.getData(e.id);
			}

/server/route/index.js

router.get('/api/goods/id', function(req, res, next) {
  let id = req.query.id;
  connection.query("select * from goods_search where id="+id+"", function (error, results, fields) {
    if (error) throw error;
    res.send({
  	  code:"0",
  	  data:results
    })
  });
});

details.vue

methods: {
			//请求商品
			getData(id){
				$http.request({
					url:"/goods/id",
					data:{
						id:id
					}
				}).then((res)=>{
					this.goodsContent = res[0];
				}).catch(()=>{
					uni.showToast({
						title:'请求失败',
						icon:'none'
					})
				})
			},
data() {
			return {
				goodsContent:{},
<view class='details'>
		<!--商品图-->
		<swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
			<swiper-item>
				<view class="swiper-item">
					<image class='swiper-img' :src="goodsContent.imgUrl" mode=""></image>
				</view>
			</swiper-item>
		</swiper>
		<!--价格和名称-->
		<view class='details-goods'>
			<view class='goods-pprice'>¥{{goodsContent.pprice}}</view>
			<view class='goods-oprice'>¥{{goodsContent.oprice}}</view>
			<view class='goods-name'>{{goodsContent.name}}</view>
		</view>

跨域

express 接口设置

router.all('*', function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  //Access-Control-Allow-Headers ,可根据浏览器的F12查看,把对应的粘贴在这里就行
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.header('Access-Control-Allow-Methods', '*');
  res.header('Content-Type', 'application/json;charset=utf-8');
  next();
});

十三、商品分享

使用 uni.share API方式调用社交sdk分享

//点击分享
		onNavigationBarButtonTap(e) {
			if(e.type==='share'){
				uni.share({
					"provider":"weixin",
					"type":0,
					"scene":"WXSceneSession",
					"title":this.goodsContent.name,
					"href":"http://192.168.8.6:8080/#/pages/details/details?id="+this.goodsContent.id+"",
					imageUrl:this.goodsContent.imgUrl,
					success: function (res) {
						uni.showTabBar({
							title:"分享成功"
						})
					},
					fail: function (err) {
						console.log("fail:" + JSON.stringify(err));
					}
					
				})
			}
		},
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值