项目介绍
1.1项目概述
慕尚花坊是⼀款同城鲜花订购 的小程序,项目常用功能模块分为项目首页、商品分类、商品列表、商品详情、用户管理、收货地址、购物车、结算支付和订单管理等等。
1.2项目技术栈
小程序内置组件:采用小程序内置组件,结合 Vant 组件库实现⻚⾯结构的搭建。
项⽬中使⽤了 css 拓展语言 Scss 绘制页面的结构。
小程序内置API:交互、支付、文件上传、地图定位、网络请求、预览图片、本地存储等。
小程序分包加载:降低⼩程序的启动时间、包的体积,提升⽤户体验度。
小程序组件开发:将页面内的功能模块抽象成⾃定义组件,实现代码的复⽤。
网络请求封装:request 方法封装、快捷⽅式封装、响应拦截器、请求拦截器。
骨架屏组件:利⽤开发者⼯具提供了⾃动⽣成⻣架屏代码的能力,提⾼了整体使用体验和用户满意 度。
UI 组件库:使用 Vant 组件库实现小程序 结构的绘制。
LBS :使⽤腾讯地图服务进行 LBS逆地址解析,实现选择收货地址功能。
miniprogram-licia :使用 licia 进行函数的防抖节流。
async-validator :使用async-validator 实现表单验证。
miniprogram-computed : 使用 miniprogram-computed 进行计算属性功能。
mobx-miniprogram :使用 mobx-miniprogram 进行项目状态的管理。
通⽤模块封装
1:wx.showToast()基本使⽤。
wx.showToast() 消息提示框是在项⽬中频繁使⽤的⼀个⼩程序 API ,常⽤来给⽤户进⾏消息提示反
馈。使⽤⽅式如下:
1 // app.js
2
3 App({
4 // ⻚⾯显示⽣命周期函数
5 onShow(){
6 wx.showToast({
7 title: '消息提示框', // 提示的内容
8 icon: 'success', // 提示的图标,success(成功)、error(失败)、loading(加
载)、none(不显示图标)
9 duration: 2000, // 提示的延迟时间
10 mask: true // 是否显示透明蒙层,防⽌触摸穿透
11 })
12
13 }
14
15 // ⽣命周期函数
16 // 在使⽤Page()构造⻚⾯时,需要使⽤⽣命周期函数。
17 // onLoad:⻚⾯加载时⽣命周期函数。
18 // onShow:⻚⾯显示⽣命周期函数。每次打开⻚⾯时都会调⽤⼀次。⻚⾯显示/切⼊前台前触发。
19 // onReady:⻚⾯初次渲染完成⽣命周期函数。⻚⾯初次渲染完成时触发。
20 // onHide:⻚⾯隐藏⽣命周期函数。如⻚⾯之间跳转或通过底部Tab切换到其他⻚⾯,⼩程序切⼊后
台。
21 // onUnload:⻚⾯卸载⽣命周期函数。⻚⾯卸载时触发,如⻚⾯跳转或者返回到之前的⻚⾯时。
22
23 })
2:为什么要进⾏模块封装
如果每次使⽤的时候,都直接调⽤这些 API ,会导致代码很冗余,为了减少了代码冗余,我们需要将 这些 API 封装成公共⽅法
3:封装思路
a:创建⼀个 toast ⽅法对 wx.showToast() ⽅法进⾏封装
b:调⽤该⽅法时,传递对象作为参数
如果没有传递任何参数,设置⼀个空对象 {} 作为默认参数
从对象中包含 title 、 icon 、 duration 、 mask 参数,并给参数设置默认值
1 const toast = ({ title = " 数据加载中 " , icon = "none" , duration = 2000 , mask = true } = {}) =>
{
2 wx . showToast ({
3 title ,
4 icon ,
5 duration ,
6 mask
7 })
8 }
在需要显示弹出框的时候调⽤ toast ⽅法,并传⼊相关的参数,有两种参数⽅式:不传递参数,使⽤默认参值传⼊部分参数,覆盖默认的参数
4:调⽤⽅法
a:模块化的⽅式导⼊使⽤
1 export { toast }
2
3 import { toast } from './extendApi'
4
5 toast ()
6 toast ({ title : ' 数据加载失败 ....' , m
ask : true })
将封装的模块挂载到 wx 全局对象身上
1 wx . toast = toast
2
3 import './utils/extendApi'
4
5 wx . toast ()
6 wx . toast ({ title : '数据加载 失败....' , mask : true })
————————————————
封装步骤
a:在utils⽂件夹内新建extendApi.js
b:完成extendApi.js⽂件
1 // function toast () {}
2
3 // 在使⽤toast⽅法时,可以传⼊参数,也可以不传⼊参数。
4 // 如果需要传⼊参数,要传⼊对象作为参数。
5 // const toast = (option = {}) => { }
6
7 // 在形参数、位置通过解构的⽅式获取⽤户传⼊的参数,同时设置默认
8 const toast = ({title="数据加载中",icon="none",duration=2000,mask=true} = {}) =>
{
9 wx.showToast({
10 title,
11 icon,
12 duration,
13 mask
14 })
15 }
16
17 // 局部暴露toast⽅法
18 export { toast }
19
20 // 如果其他.js⽂件,需要使⽤toast⽅法,需要导⼊toast,然后进⾏调⽤才可以。
21
22 // 如果有很多的.js⽂件,都需要调⽤toast⽅法
23 // 每次使⽤都需要导⼊toast再调⽤,太麻烦了
24 // 可以将toast⽅法挂载到wx全局对象上
25 // 全局挂载⽅法
26 wx.toast = toast
1 // app.js
2 // import { toast } from './utils/extendApi'
3 // import './utils/extendApi'
4
5 App({
6 // ⻚⾯显示⽣命周期函数
7 onShow() {
8
9 // 局部导⼊
10 // 不传参数
11 // toast()
12 // 传⼊参数,传⼊的参数会覆盖默认的参数。
13 // toast({title:'数据加载完毕', icon:'success'})
14
15 // 全局导⼊
16 // wx.toast()
17 // wx.toast({ title: '数据加载失败....', mask: true })
18
19 }
20 })
21
localStorage、sessionStorage、cookie分别是什么以及区别
cookie是客户端与服务器端进行会话使用的一个能够在浏览器本地化存储的技术
localStorage是永久存储在客户端浏览器上,除非手动去清除
sessionStorage也是存储在客户端浏览器上,但仅在当前会话有效,关闭页面或浏览器后被清除
localStorage、sessionStorage、cookie在同名时都是可以被覆盖的
区别:
1.cookie数据始终携带在http请求中,而sessionStorage和Localstorage不会自动把数据发送给服务器,只在本地保存
2.存储大小不同,cookie数据不能超过4k,所有cookie只适合保存很小的数据。sessionStorage和Localstorage存储大小比cookie大很多,可以达到5M或更大。
3.数据存储的有效期不同,cookie的有效期在设置的cookie过期时间内(如果不给cookie设置过期时间,会在浏览器会话结束时过期),sessionStorage的有效期是仅保持在当前页面,浏览器会话结束时(关闭窗口或浏览器)失效,localStorage的有效期是在不进行手动删除的情况下是一直有效的
4.读写操作的便捷程度,cookie的相关操作操作起来较为繁琐,而 sessionStorage和Localstorage的api接口使用方便
5.cookie出现的时间较早,目前见到的浏览器都支持,而localStorage和sessionStorage出现的时间较晚,对于版本较低的浏览器不支持。
6.web Storage支持事件通知机制,可以将数据更新的通知发送给监听者。
二:GET、POST、PUT、DELETE、HEAD五种请求方法的不同区别
1.GET方法:主要用于从指定的资源请求数据
安全性:GET请求的参数会附加在URL后面,并以查询字符串的形式呈现。
长度限制:由于URL的长度有限制,GET请求的参数数量和数据量也相应地受到限制。
数据传输方式:GET请求通常只包含URL中的查询参数,不包含请求体。
通信类型:单向请求-响应协议,客户端发送请求,服务器返回数据。
幂等性:GET请求是幂等的,这意味着对同一URL的多个GET请求应该产生相同的结果
2.POST方法:主要用于向服务器提交数据
非幂等性:POST方法是非幂等的,即多次发送相同的POST请求可能会导致不同的结果。
请求体:POST请求包含请求体,可以发送各种类型的数据,如表单数据、JSON、XML等。
用途:用于向服务器提交数据以创建或更新资源。
安全性:相比GET方法,POST方法更为安全,因为它将参数包含在请求体中而不是URL中
数据传输方式:POST请求的数据包含在请求体中,可以传输大量数据,且支持多种数据类型。
通信类型:仍然是单向请求-响应协议,但侧重于数据的提交和处理。
3.PUT方法:用于更新服务器上已有的资源
用途:用于替换服务器上的资源。
幂等性:PUT请求是幂等的,这意味着对同一资源的多次PUT请求应该产生相同的结果。
请求体:PUT请求通常包含请求体,用于传输要更新的资源内容。
数据传输方式:PUT请求的数据也包含在请求体中,它通常用于上传整个资源或文件。
通信类型:与POST类似,但语义上更侧重于资源的替换而非创建。
4.DELETE方法:主要用于请求服务器删除指定的资源
安全性:DELETE请求通常不会缓存,也不会在浏览器的历史记录中留下痕迹,这使得它相对更安全。
用途:请求服务器删除指定的资源。
数据传输方式:通常不需要额外的请求体数据。
通信类型:单向请求-响应协议,专注于资源的删除操作。
幂等性:DELETE请求不是幂等的,这意味着多次发送相同的DELETE请求可能会导致不同的结果
5.HEAD方法:
用途:与GET方法类似,但服务器在响应中只返回HTTP头部,不返回实际数据。
数据传输方式:只返回响应头,不包含响应体。
通信类型:单向请求-响应协议,主要用于获取资源的元信息。
navigator是一个全局对象,它提供了与浏览器相关的信息和操作接口。在前端开发中,我们通常会使用 navigator 对象来获取用户浏览器的相关信息。
navigator 对象的常见属性和方法包括:
navigator.userAgent: 返回当前浏览器的用户代理字符串。
navigator.appName: 返回当前浏览器的名称。
navigator.appVersion: 返回当前浏览器的版本号。
navigator.language: 返回当前浏览器的语言设置。
navigator.platform: 返回当前浏览器所在设备的操作系统平台。
navigator.geolocation: 提供了一组 API,用于获取当前设备的地理位置信息。
navigator.mediaDevices: 提供了一组 API,用于访问当前设备的音频、视频、屏幕等媒体设备。
navigator.serviceWorker: 提供了一组 API,用于在浏览器中注册和管理 Service Worker,实现离线缓存和推送通知等功能
flex布局
flex-direction属性
flex-direction属性用于设置主轴方向,通过设置主轴方向可以规定项目的排列方向。
row:默认值,主轴为从左到右的水平方向。
row-reverse:主轴为从右到左的水平方向。
column:主轴为从上到下的垂直方向。
column-reverse:主轴为从下到上的垂直方向。
justify-content属性
justify-content属性用于设置项目在主轴方向上的对齐方式。能够分配项目之间及其周围 多余的空间。
flex-start:默认值,表示项目对齐到主轴起点,项目间不留空隙。
flex-end:项目对齐到主轴终点,项目间不留空隙。
center:项目在主轴上居中排列,项目间不留空
space-between:两端对齐,两端的项目分别靠向容器的两端,其他项目之间的间隔相等 space-around:每个项目之间的距离相等
align-items属性align-items属性用于设置项目在交叉轴上的对齐方式。
center:项目在交叉轴的中间位置对齐。
flex-start:项目顶部与交叉轴起点对齐,flex-end:项目底部与交叉轴终点对齐。
baseline:项目的第一行文字的基线对齐。
轮播图组件
在banner.wxml中通过swiper组件建立一个自动轮播列表
使用wx:for循环遍历bannerList数组
bannerList.length为数组长度
<view class="swiperbox">
<swiper autoplay class="swiper" indicator-active-color="#FF734C" interval="2000" duration="1000" indicator-color="rgba(0,0,0,3)">
<block wx:for="{{ bannerList }}" wx:key="index">
<swiper-item class="swiper-item">
<image class="img" src="{{item}}"></image>
</swiper-item>
</block>
</swiper>
<view class="indicator">
<text wx:for="{{bannerList.length}}" wx:key="id"
class="rectangle"></text>
</view>
</view>
设置swiperbox样式
.swiperbox{
position: relative;
.swiper{
height: 320rpx;
//设置圆角弧度
border-radius: 18rpx;
//设置溢出隐藏
overflow: hidden;
width: 95%;
//margin设置外边距
margin: 0 auto;
}
.swiper-item{
.img{
width: 100%;
height: 100%;
border-radius: 18rpx;
}
}
.indicator{
display: flex;
justify-content: center;
position: absolute;
bottom: 16rpx;
left: 0rpx;
right: 0rpx;
.rectangle{
width: 30rpx;
height: 6rpx;
background-color: #f3514f;
margin: 0 8rpx;
border-radius: 6rpx;
}
}
}
1.5entrance导航组件
在entrance.wxml中渲染一个导航列表
<view class="nav-list">
<view wx:for="{{10}}" wx:key="index" class="nav-item">
<navigator url="" class="navigator-nav">
<image src="../../../assets/images/cate-1.png" mode="" class="nav-img"/>
<text class="nav-text">鲜花玫瑰</text>
</navigator>
</view>
</view>
导航分类样式
.nav-list {
//设置弹性布局
display: flex;
//设置换行
flex-wrap: wrap;
margin: 20rpx;
border-radius: 18rpx;
padding: 10px 0px 10px 10px;
background-color: white;
}
.nav-item {
.navigator-nav {
//更改主轴方向
//由默认的横向排列更改为纵向排列
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-right: 10px;
margin-top: 10px;
.nav-text {
margin-top: 4px;
font-size: 12px;
}
.nav-img {
width: 66rpx;
height: 66rpx;
}
}
}
广告区域结构
<!-- 广告区域 -->
<view class="adver">
<view class="adver-left">
<navigator url="">
<image src="../../assets/images/love.jpg" mode="widthFix" />
</navigator>
</view>
<view class="adver-right">
<view>
<navigator url="">
<image src="../../assets/images/elder.jpg" mode="widthFix" />
</navigator>
</view>
<view>
<navigator url="">
<image src="../../assets/images/friend.jpg" mode="widthFix" />
</navigator>
</view>
</view>
</view>
app.json引入图标
{
"pages": [
"pages/my/my",
"pages/index/index",
"pages/cart/cart",
"pages/goods/goods",
"pages/category/category",
"pages/index/banner/banner",
"pages/index/entrance/entrance",
"components/goods-card/goods-card",
"components/goods-list/goods-list",
"pages/list/list",
"pages/tist/tist",
"pages/test/test"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "慕尚花坊",
"navigationBarBackgroundColor": "#FF734C"
},
"tabBar": {
"color": "#252933",
"selectedColor": "#FF734C",
"backgroundColor": "#ffffff",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "assets/tabbar/index.png",
"selectedIconPath": "assets/tabbar/index-active.png"
},
{
"pagePath": "pages/category/category",
"text": "分类",
"iconPath": "assets/tabbar/cate.png",
"selectedIconPath": "assets/tabbar/cate-active.png"
},
{
"pagePath": "pages/cart/cart",
"text": "购物车",
"iconPath": "assets/tabbar/cart.png",
"selectedIconPath": "assets/tabbar/cart-active.png"
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "assets/tabbar/my.png",
"selectedIconPath": "assets/tabbar/my-active.png"
}
]
},
"sitemapLocation": "sitemap.json",
"lazyCodeLoading": "requiredComponents",
"usingComponents": {
"van-button": "@vant/weapp/button/index",
"van-card": "@vant/weapp/card/index",
"van-submit-bar": "@vant/weapp/submit-bar/index",
"van-checkbox": "@vant/weapp/checkbox/index",
"van-checkbox-group": "@vant/weapp/checkbox-group/index",
"van-stepper": "@vant/weapp/stepper/index",
"van-empty": "@vant/weapp/empty/index",
"van-goods-action": "@vant/weapp/goods-action/index",
"van-goods-action-icon": "@vant/weapp/goods-action-icon/index",
"van-goods-action-button": "@vant/weapp/goods-action-button/index",
"van-action-sheet": "@vant/weapp/action-sheet/index",
"van-panel": "@vant/weapp/panel/index"
}
}
购物车页面
Page({
/**
* 页面的初始数据
*/
data:{
carList:[1]
},
navigateBtn:function(){
wx.navigateTo({
url: '/miniprogram/components/good',
success:function(res){
console.log(res);
},
fail:function(){
},
complete:function(){
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
{
"component": true,
"styleIsolation": "shared",
"usingComponents": {}
}
.container {
background-color: whitesmoke;
height: 100vh;
}
.carList-container{
.carList-container-cell {
.goods-info {
display: flex;
background-color: white;
border-radius: 16rpx;
margin: 20rpx 20rpx 10rpx 20rpx;
padding: 24rpx 16rpx;
.left{
display: flex;
align-items: center;
}
.mid {
width: 300rpx;
height: 300rpx;
image {
width: 100%;
height: 100%;
}
}
}
.right {
display: flex;
flex-direction: column;
height: 300rpx;
justify-content: space-between;
padding-left: 20rpx;
.title{
font-size: 26rpx;
}
.buy{
display: flex;
justify-content: space-between;
.price{
font-size: 30rpx;
color: #fa4126;
}
}
}
}
}
.van-empty__bottom{
display: flex;
height: 250rpx;
flex-direction: column;
justify-content: space-between;
}
<view class="container">
<!-- 购物车列表区域 -->
<view class="carList-container" wx:if="{{carList.length}}">
<view class="carList-container-cell" wx:for="{{carList}}" wx:key="index">
<van-swipe-cell right-width="{{ 65 }}" left-width="{{ 65 }}">
<van-cell-group>
<view class="goods-info">
<view class="left">
<van-checkbox value="{{ false }}" checked-color="#e60017" bind:change="onChange">
</van-checkbox>
</view>
<view class="mid">
<image src="../../assets/images/floor-img.jpg" mode="" />
</view>
<view class="right">
<view class="title">【11支红玫瑰】买花就送女友送爱人送老婆11111111111</view>
<view class="buy">
<view class="price">¥99.99</view>
<view class="buy-btn">
<van-stepper value="{{ 1 }}" bind:change="onChange" />
</view>
</view>
</view>
</view>
</van-cell-group>
</van-swipe-cell>
</view>
</view>
<!-- 购物车列表为空的情况 -->
<van-empty description="还没有商品,快去添加吧~" wx:else="">
<navigator url="">
<van-button type="danger" round bindtap="navigateBtn">去购物</van-button>
</navigator>
<navigator url="">
<van-button type="danger" round>去登录</van-button>
</navigator>
</van-empty>
<!-- 提交订单栏区域 -->
<van-submit-bar price="{{ 3050 }}" button-text="提交订单" bind:submit="onClickButton" tip="{{ true }}">
<van-checkbox value="{{ true }}" checked-color="#e60017" bind:change="onChange">
全选
</van-checkbox>
</van-submit-bar>
</view>
商品列表页面
// pages/list/list.js
Page({
/**
* 页面的初始数据
*/
data: {
isFinish:"true"
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
}){
"usingComponents": {
"goods-card":"../../components/goods-card/goods-card"
}
}/* pages/list/list.wxss */
.container{
.goods-list{
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
}
.finish{
font-size: 28rpx;
text-align: center;
color: #f3514f;
line-height: 80rpx;
border-top: 1px solid black;
}
}<!--pages/list/list.wxml-->
<view class="container">
<!-- 用户列表区域 -->
<view class="goods-list">
<block>
<goods-card></goods-card>
<goods-card></goods-card>
<goods-card></goods-card>
<goods-card></goods-card>
</block>
</view>
<!-- 文字区域 -->
<!-- hidden属性控制文字的显示与隐藏 -->
<!-- 当数据加载完毕,isFinish为true,!isFinish为false,则这句话不隐藏,用户能看到这句话 -->
<view class="finish" hidden="{{!isFinish}}">数据加载完毕了~~</view>
</view>
商品细节页面
// pages/detail/detail.js
Page({
/**
* 页面的初始数据
*/
data: {
},
// 点击按钮事件,控制面板显示。
handelSheet(){
this.setData ({
show:true
})
},
onClose(){
this.setData ({
show:false
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
}).container {
background-color: whitesmoke;
height: 100vh;
.banner-img {
height: 800rpx;
image {
height: 100%;
}
}
// 商品基本信息
.content {
background-color: white;
// margin 设置外边距
margin: 0 20rpx;
// padding 设置内边距
padding: 40rpx;
// 设置圆角弧度
border-radius: 20rpx;
// 相对于原本的位置发生改变是相对定位
// 相对于父盒子位置发生改变是绝对定位
position: relative; //相对定位
top: -200rpx;
.price {
display: flex;
.price-num {
color: #fa4126;
font-weight: bolder;
font-size: 18px;
}
.price-origin-num {
color: #b4babf;
text-decoration: line-through;
font-size: 12px;
margin-left: 15px;
margin-top: 4px;
}
}
.title {
// 溢出隐藏
overflow: hidden;
// 超过一行就算溢出
white-space: nowrap;
// 溢出之后的文本
text-overflow: ellipsis;
font-size: 16px;
font-weight: bolder;
margin: 20rpx 0;
}
.info {
// 溢出隐藏
overflow: hidden;
// 超过一行就算溢出
white-space: nowrap;
// 溢出之后的文本
text-overflow: ellipsis;
font-size: 12px;
color: #9999;
}
}
// 商品的详细信息
.detail {
background-color: white;
padding: 20rpx;
margin: -160rpx 20rpx 0 20rpx;
border-radius: 20rpx;
image {
width: 100%;
height: 700rpx;
}
}
.sheet-container {
margin: 20rpx;
padding: 20rpx;
border-radius: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.img {
height: 400rpx;
width: 350rpx;
image {
width: 100%;
height: 100%;
}
}
.buy {
display: flex;
justify-content: space-between;
.price {
display: flex;
color: #fa4126;
}
}
.baseInfo {
display: flex;
// 设置主轴方向
flex-direction: column;
// 设置主轴上的排列方式
justify-content: space-between;
margin-left: 20rpx;
.title {
font-size: 14px;
}
}
}
.textArea {
background-color: white;
margin: 20rpx 20rpx;
.title {
margin-right: 30rpx;
margin-bottom: 20rpx;
}
.box {
background-color: whitesmoke;
width: 92%;
margin: 0 auto;
border-radius: 20rpx;
padding: 20rpx;
}
}
.btn{
width: 90%;
margin: 20rpx auto;
}
}<!--pages/goods/goods.wxml-->
<view class="container">
<!-- 商品大图 -->
<view class="banner-img">
<image src="../../assets/images/floor.jpg" mode="" />
</view>
<!-- 商品的基本信息 -->
<view class="content">
<!-- 商品标题 -->
<view class="title">亲爱的/情人节网红款/19枝</view>
<!-- 详细信息 -->
<view class=" info">情⼈节新品情⼈节新品情⼈节新品情⼈节新品</view>
<!-- 商品价格 -->
<view class="price">
<view class="price-num">¥299</view>
<view class="price-origin-num">¥399</view>
</view>
</view>
<!-- 商品的详细信息 -->
<view class="detail">
<image src="../../assets/images/floor-img.jpg" mode="" />
<image src="../../assets/images/floor-img.jpg" mode="" />
<image src="../../assets/images/floor-img.jpg" mode="" />
</view>
<!-- 商品的底部导航栏 -->
<van-goods-action>
<!-- 如果navigator标签跳转到tabber栏 则需要加open-type -->
<navigator url="/pages/index/index" open-type="'switchTab">
<van-goods-action-icon icon="wap-home-o" text="首页" />
</navigator>
<van-goods-action-icon icon="chat-o" text="客服" dot />
<van-goods-action-icon icon="cart-o" text="购物车" info="5" />
<van-goods-action-button text="加入购物车" type="warning" bind:tap="handelSheet" />
<!-- handelSheel为点击按钮事件 -->
<van-goods-action-button text="立即购买" bind:tap="handelSheet" />
</van-goods-action>
<!-- 自定义面板 -->
<!-- bind:close为面板关闭事件 -->
<van-action-sheet show="{{ show }}" bind:close="onClose" position="bottom">
<view class="sheet-container">
<view class="img">
<image src="../../assets/images/floor-img.jpg" mode="" />
</view>
<!-- 商品基本信息区域 -->
<view class="baseInfo">
<!-- 商品名称 -->
<view class="title">亲爱的/情人节网红款/19支玫瑰</view>
<!-- 商品价值区域 -->
<view class="buy">
<view class="price">
<view class="symbol">¥</view>
<view class="num">100</view>
</view>
<view class="buyBtn">
<van-stepper value="{{1}}" bind:change="onChange" />
</view>
</view>
</view>
</view>
<!-- 商品祝福语区域 -->
<view class="textArea">
<view class="title">祝福语</view>
<textarea value="" placeholder="请输入你的祝福" class="box" />
</view>
<view class="btn">
<van-button type="primary" round size="large">确定</van-button>
</view>
</van-action-sheet>
</view>
订单页面
// pages/tist/tist.js
Page({
/**
* 页面的初始数据
*/
data: {
orderList:[1,2,3]
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
/* pages/tist/tist.wxss */
.container {
background-color: whitesmoke;
height: 100vh;
.order-list {
.order-item {
width: 90%;
height: 380rpx;
margin: 20rpx auto;
padding: 20rpx;
border-radius: 20rpx;
background-color: white;
position: relative;
.top {
display: flex;
justify-content: space-between;
margin-bottom: 10rpx;
font-size: 28rpx;
font-weight: normal;
color: #333333;
}
.middle {
display: flex;
.img {
height: 200rpx;
width: 250rpx;
image {
width: 100%;
}
}
.text {
margin: 0 220rpx 0 20rpx;
.goods-name {
font-size: 28rpx;
color: #333;
line-height: 40rpx;
font-weight: 400;
}
.goods-blessing {
font-size: 24rpx;
height: 32rpx;
line-height: 32rpx;
color: #999999;
margin: 8rpx 0;
}
}
.number {
.goods-price {
white-space: nowrap;
color: #fa4126;
font-size: 24rpx;
line-height: 48rpx;
}
.goods-count {
white-space: nowrap;
order: 4;
text-align: right;
font-size: 24rpx;
color: #999;
margin: 20rpx 0 0 auto;
}
}
}
.bottom {
position: absolute;
right: 50rpx;
bottom: 50rpx;
.total-price {
display: flex;
.text {
font-size: 28rpx;
color: #333333;
margin-right: 10px;
}
.price {
font-size: 32rpx;
color: #fa4126;
font-weight: bold;
}
}
}
}
}
}
<!--pages/tist/tist.wxml-->
<view class="container" wx:if="{{ orderList.length }}">
<view class="order-list" wx:for="{{orderList}}" wx:key="index">
<view class="order-item">
<view class="top">
<view class="order-num">订单号<text class="num">679246470200</text></view>
<view class="order-status">已支付</view>
</view>
<view class="middle">
<view class="img">
<image src="../../assets/images/floor-img.jpg" mode="widthFix" />
</view>
<view class="text">
<view class="goods-name">不变的承诺</view>
<view class="goods-blessing">不变的承诺</view>
</view>
<view class="number">
<view class="goods-price">¥100</view>
<view class="goods-count">x 1</view>
</view>
<view class="bottom">
<view class="total-price">
<view class="text">实付</view>
<view class="price"><text>¥</text>666</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 购物车列表为空的情况 -->
<van-empty description="还没有购买商品,快去购买吧~" wx:else>
</van-empty>