目录
一、小程序环境搭建和创建项目
【慕尚花坊小程序】项目使用原生小程序进行搭建开发,项目涵盖电商项目常见的功能模块:
项目首页、 商品分类 、商品列表、 商品详情 、用户管理、 收货地址、 购物车、 结算支付、 订单管理 等……
1.新建一个文件夹并给它命名
2.打开微信开发者工具,创建项目,
-
在目录中引入刚刚创建的新文件夹,
-
填写自己的APPID,
-
选择不使用云服务,选择js基础模板。
二. 项目初始化
项目目录结构如下:
三、自定义构建 npm + 集成Scss
为了方便进行项目的开发,开发人员通常会对目录结构进行调整优化,在这个项目中, 我们就需要将小程序源码放到 miniprogram 目录下
四、构建项目页面和首页页面
在app.json文件中, 定义页面的路径:
定义应用的窗口样式和底部导航栏的布局和样式:
"window": {
//设置窗口的背景文字样式为浅色。
"backgroundTextStyle":"light",
//设置导航栏的标题为“慕尚花坊”。
"navigationBarTitleText": "慕尚花坊",
//设置导航栏的背景颜色为#f3514f
"navigationBarBackgroundColor": "#f3514f",
//设置导航栏的文字颜色为白色
"navigationBarTextStyle":"white"
},
"tabBar": {
//设置 tabBar 上未选中文字的颜色为#252933。
"color":"#252933",
//设置 tabBar 上选中文字的颜色为#FF734C。
"selectedColor": "#FF734C",
// 设置 tabBar 的背景颜色为白色。
"backgroundColor": "#ffffff",
//设置 tabBar 的边框样式为黑色
"borderStyle":"black",
//list 属性定义了 tabBar 的各个标签项
"list": [
//首页
{
"pagePath": "pages/index/index",
"text":"首页",
"iconPath": "assets/tabbar/index.png",
"selectedIconPath": "assets/tabbar/index-active.png"
}
1.首页页面
如图所示:
在index.wxml里搭建首页结构
<!--index.wxml-->
<view class="index-container">
<!-- ⾸⻚背景图 -->
<view class="window-bgc"></view>
<!-- ⻚⾯主体区域 -->
<view class="container">
<!-- 轮播图区域 -->
<banner />
<!-- 导航区域 -->
<entrance />
</view>
</view>
并设置首页背景图的样式:
//首页背景图
.window-bgc {
height: 200rpx;
position:absoulte;
width: 100%;
background-color:#f3514f;
border-radius:0rpx 0rpx 40% 40%;
}
2.新建banner组件(轮播图区域)和entrance组件(导航区域)
在banner.json和entrance.json中搭建组件结构:
{
"usingComponents": {},
"component": true
}
"usingComponents": {}: 这是一个对象,它的键是usingComponents。这个对象通常用于声明当前组件所使用的其他组件。在{}内部,会看到一系列的键值对,其中键是自定义组件的标签名,值是组件的路径。但是在这个例子中,它是空的,表示当前组件没有使用其他组件。
"component": true: 这是一个键值对,其中键是component,值是true。这通常表示当前描述的是一个组件。在某些框架或系统中,它可能用于标记或标识一个对象或文件为一个组件。
在index.json中表示当前index组件使用了这些组件,并且引入他们的路径:
{
"usingComponents": {
"banner":"./banner/banner",
"entrance":"./entrance/entrance",
"goods-list":"../../components/goods-list/goods-list"
},
"navigationBarTitleText": "慕尚花坊"
}
a:完成轮播图组件
在banner.wxml中
- 使用swiper组件创建一个自动轮播的图片列表。
- 通过
wx:for
循环遍历bannerList
数组,为每一个图片链接创建一个swiper-item
。 - 在轮播图的下方,根据
bannerList
的长度生成相应数量的指示点。
//这是一个容器,其类名为"swiper-box",用于包裹轮播组件并提供样式。
<view class="swiper-box">
<swiper
autoplay class="swiper"
indicator-active-color="#FF734C"
interval="2000"
duration="1000"
indicator-color="rgba(0,0,0,.3)">
//这是一个循环,用于遍历bannerList数组。
wx:for是微信小程序的循环指令,
而wx:key用于指定列表中项目的唯一的标识符,这里使用index作为键。
<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>
样式:在banner.scss中设置样式: (注释和代码如下所示)
/* pages/banner/banner.wxss */
// 轮播图样式
.swiper-box{
//设置相对定位
position: relative;
//距离下280rpx
bottom: 280rpx;
.swiper {
height: 320rpx;
// 设置圆角弧度
border-radius: 18rpx;
// 设置溢出隐藏
overflow: hidden;
width: 95%;
//margin 设置外边距
margin: 0 auto;
}
.swiper-item {
//图片占满盒子的100%
//圆角弧度18rpx
.img {
width:100% ;
height: 100%;
border-radius: 18rpx;
}
}
// 面板指示器
.indicator {
//设置弹性布局
display: flex;
justify-content: center;
//设置绝对定位
position: absolute;
bottom: 16rpx;
left: 0;
right: 0;
//面板指示器的样式
.rectangle{
width: 40rpx;
height: 6rpx;
background-color: red;
border-radius: 6rpx;
margin: 0 8rpx;
}
}
}
b:完成导航区域组件
在entrance.wxml中渲染一个导航列表
<!-- 定义一个名为nav-list的视图容器,用来包裹导航列表 -->
<view class="nav-list">
<!-- 使用wx:for指令循环渲染10个视图元素 -->
<!-- wx:for="{{ 10 }}" 表示循环次数为10次 -->
<!-- wx:key="index" 用于指定列表中项目的唯一的标识符,这里使用循环的索引作为键 -->
<view wx:for="{{ 10 }}" wx:key="index" class="nav-item">
<!-- 使用navigator组件创建一个导航链接 -->
<!-- url="" 属性中应该填写具体的跳转链接,目前为空 -->
<navigator url="" class="navigator-nav">
<!-- 使用image组件展示一个图片 -->
<!-- src属性指定图片的路径 -->
<!-- class指定图片的样式类 -->
<image src="../../../assets/images/cate-1.png" class="nav-img"/>
<!-- 使用text组件展示文本为鲜花玫瑰 -->
<!-- class指定文本的样式类 -->
<text class="nav-text">鲜花玫瑰</text>
</navigator>
</view>
</view>
样式:代码和注释如图所示
.nav-img{
/* 设置图片的宽度为66rpx */
width: 66rpx;
/* 设置图片的高度为66rpx */
height: 66rpx;
}
.nav-list{
/* 设置外边距为20rpx */
margin: 20rpx;
/* 设置边框圆角为18rpx */
border-radius: 18rpx;
/* 设置内边距为顶部和底部10px,左侧10px,右侧0px */
padding: 10px 0px 10px 10px;
/* 设置背景颜色为白色 */
background-color: white;
/* 设置定位方式为相对定位 */
position: relative;
/* 设置距离底部的距离为300rpx */
bottom: 300rpx;
/* 设置元素为弹性盒子 */
display: flex;
/* 设置弹性盒子内的项目换行显示 */
flex-wrap: wrap;
/* 设置弹性盒子内的项目在交叉轴上居中 */
align-items: center;
/* 设置弹性盒子内的项目在主轴上居中 */
justify-content: center;
/* 定义.nav-item类的样式,嵌套在.nav-list中 */
.nav-item{
/* 定义.navigator-nav类的样式,嵌套在.nav-item中 */
.navigator-nav{
/* 设置元素为弹性盒子 */
display: flex;
/*更改主轴方向 */
/* 设置弹性盒子内的项目主轴方向为纵向排列 */
flex-direction: column;
/* 设置弹性盒子内的项目在交叉轴上居中 */
align-items: center;
/* 设置弹性盒子内的项目在主轴上居中 */
justify-content: center;
/* 设置右边距为21px */
margin-right: 21px;
/* 设置上边距为10px */
margin-top: 10px;
/* 定义.nav-text类的样式,嵌套在.navigator-nav中 */
.nav-text{
/* 设置上边距为4px */
margin-top: 4px;
/* 设置字体大小为12px */
font-size: 12px;
}
}
}
}
3.编写广告区域和商品列表区域
a:广告区域
在index.wxml中编写广告区域的结构
<!-- ⼴告区域 -->
<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>
样式设置:
//广告区域
.adver {
display:flex;
position: relative;
bottom: 330rpx;
// 居中 外边距 上下为0 左右自动平分距离
margin: 0 auto;
width: 96%;
padding: 18rpx;
box-sizing :border-box;
background-color: white;
border-radius: 18rpx;
.adver-left {
width: 50%;
// 内边距 上右下左
padding: 8rpx 8rpx 0rpx 8rpx;
}
.adver-right {
width: 50%;
padding: 8rpx 8rpx 0rpx 8rpx;
//选中第二张图片
view:last-child{
padding-top: 10rpx;
}
}
image{
width: 100%;
}
}
b:商品列表区域
注册goods-card和goods-list全局组件
完成goods-card和goods-list组件
在index.wxml中,使用自定义组件<goods-list>
来展示商品列表。两个<goods-list>
组件,每个组件都有一个title
属性,分别设置了不同的标题:“猜你喜欢”和“人气推荐”。
<!-- 商品列表 -->
<goods-list title="猜你喜欢"></goods-list>
<goods-list title="人气推荐"></goods-list>
在goods-card.js中,定义了一个空的框架,它有一个属性 goodItem
,但没有初始数据和方法。在使用中,可能会在 data
中定义一些状态变量,在 methods
中定义一些事件处理函数或逻辑处理函数,并在组件的模板中使用这些数据和方法来渲染。
Component({
properties:{
goodItem:{
type:Object,
value:{}
}
},
data:{},
methods:{}
})
在goods-list.js中 ,定义了一个组件,包含组件的属性、初始数据和方法的定义。
Component({
// 组件的属性列表
properties: {
// 列表标题
title: {
type: String,
value: ''
},
// 传递的列表数据
list: {
type: Array,
value: [{}, {}, {}]
}
},
// 组件的初始数据
data: {},
// 组件的⽅法列表
methods: {}
})
在goods-card.wxml中,渲染一个商品卡片:
<!-- 列表分类卡片 -->
<view class="goods-cart-container">
<!-- 图片 -->
<navigator class="navigator-nav" url="">
<image class="good-img" src="../../assets/images/floor.jpg" mode="widthFix"/>
<!-- 详细信息 -->
<view class="goods-item-info">
<!-- 商品名称 -->
<text class="goods-item-info-name">红玫瑰</text>
<!-- 商品描述 -->
<text class="goods-item-info-promo">爱他/她 就送红玫瑰/情人节99999999</text>
<!-- 商品价钱 -->
<view class="goods-item-info-bottom">
<!-- 优惠价钱 -->
<view class="goods-item-info-price">
<text>$</text>399
</view>
<!-- 原价 -->
<view class="goods-item-oringin-price">
<text class="text">$</text>599{{goodItem.markPrice}}
</view>
<!-- 加入购物车图片 -->
<view class="goods-item-info-btn">
<image src="../../assets/images/buybtn.png" class="goods-image" mode=""/>
</view>
</view>
</view>
</navigator>
</view>
在goods-card.scss中 设置样式 文字、图片、排列布局
.goods-cart-container{
width: 350rpx;
margin-top:18rpx ;
background: #fff;
border-radius: 18rpx;
position: relative;
bottom: 300rpx;
}
// 图片
。。。。。。
.goods-item-info{
//文字 纵向排列
display: flex;
// 更改主轴方向为纵轴
flex-direction: column;
padding: 10rpx 20rpx;
}
.goods-item-info .goods-item-info-name{
// 设置字体粗细
font-weight:600;
font-size:30rpx;
line-height:20px;
// 溢出隐藏
overflow:hidden;
// 溢出之后的文本
text-overflow:ellipsis;
// 超出一行算溢出
white-space: nowrap;
}
。。。。。。。
}
.goods-item-info-bottom{
// 设置三个弹性布局 将块级元素在一行显示
display: flex;
line-height: 50rpx;
margin-top: 20rpx;
}
。。。。。。
// 原价标签
.goods-item-oringin-price {
// flex设置为1 则改元素拥有所有剩余部分
flex: 1;
font-size: 20rpx;
color: #71797f;
text-decoration-line: line-through;
margin-left: 6%;
margin-top: 4rpx;
}
。。。。。。。
}
在goods-list.json中,这个配置文件表示当前定义的是一个组件,并且这个组件依赖另一个名为goods-card
的自定义组件。当在这个组件的WXML文件中使用<goods-card></goods-card>
标签时,实现 goods-card
组件。
{
"component": true,
"usingComponents": {
"goods-card":"../goods-card/goods-card"
}
}
在goods-list.wxml中 编写商品列表组件:
<!-- 商品列表组件 -->
<view class="goods-container">
<!-- 显示商品列表的标题,{{title}}是一个数据绑定,它会显示传入的title变量的值。-->
<view class="goods-title">{{title}}</view>
<!-- 列表区域 -->
<view class="goods-card-list">
<block wx:for="{{ 4 }}" wx:key="index">
<goods-card>
<view>
<view>
</view>
</view>
</goods-card>
</block>
</view>
<!-- 查看更多 -->
<view class="goods-more">
<navigator url="../goods-list/goods-list" class="goods-more-btn" hover-class="navigator-hover" open-type="navigate">查看更多</navigator>
</view>
</view>
在goods-list.scss中 标题样式 商品卡片布局
// 标题
.goods-container{
// 大盒子加边距
width: 95%;
margin: 0 auto;
.goods-title {
position: relative;
bottom: 310rpx;
// 设置文本居中
text-align: center;
font-size: 40rpx;
line-height: 52rpx;
font-weight: bold;
color: #232628;
padding: 20rpx 0 0rpx 0rpx;
}
.goods-card-list {
display: flex;
// 设置换行
flex-wrap: wrap;
justify-content: space-between;
}
.goods-card-list::after {
content: '';
width: 350rpx;
}
.goods-more {
position: relative;
bottom: 300rpx;
margin: 10rpx 0;
}
.goods-more-btn {
width: 95%;
display: flex;
text-align: center;
justify-content: center;
align-items: center;
margin: 0 auto;
background: #ffffff;
border-radius: 20px;
height: 40px;
line-height: 40px;
font-size: 14px;
color: rgba(35, 38, 40, 0.7);
}
}
完成后如图所示 :
五、分类页面
在category.wxml中完成展示商品的分类 二级菜单
- 页面容器:整体使用
<view>
标签作为页面容器。 - 分类容器:内部的
<view class="category-container">
作为分类的容器,包含了左右两个滚动视图区域。 - 左侧滚动视图:
<scroll-view class="category-left-view" scroll-y>
是左侧的滚动区域,沿着y轴滚动。这里列出了几个一级分类,如“爱礼精选”、“鲜花玫瑰”等,其中“爱礼精选”是当前被选中的分类,有“active”类名。 - 右侧滚动视图:
<scroll-view class="category-right-view" scroll-y>
是右侧的滚动区域,也沿着y轴滚动。这里使用wx:for
指令循环渲染了10个二级分类项,每个项都包含一个图片(例如“cate-1.png”)和一个商品名称(例如“真情告白”)。
<!--pages/category/category.wxml-->
<view>
<view class="category-container">
<!-- 左侧的滚动视图区域 -->
<!-- 滚动标签 延着y轴滚动 -->
<scroll-view class="category-left-view" scroll-y >
<!-- 一级分类 -->
<!-- 被选中的类名 active -->
<view class="left-view-item active">爱礼精选</view>
<view class="left-view-item">鲜花玫瑰</view>
<view class="left-view-item ">永生玫瑰</view>
<view class="left-view-item ">玫瑰珠宝</view>
</scroll-view>
<!-- 右侧的滚动视图区域 -->
<scroll-view class="category-right-view" scroll-y >
<!-- 二级分类 -->
<view class="test">
<!-- 渲染10个 -->
<view wx:for="{{ 10 }}" wx:key="index" class="right-view-item">
<!-- -->
<navigator class="navigator" url=" ">
<image class="" src="../../assets/images/cate-1.png"></image>
<text class="goods-item-name">真情告白</text>
</navigator>
</view>
</view>
</scroll-view>
</view>
</view>
在category.scss中设置左侧菜单的样式:
/* 类别容器样式 */
.category-container {
display: flex; /* 使用弹性布局 */
/* 左侧一级分类样式 */
.category-left-view {
width: 220rpx; /* 宽度设为220rpx(微信小程序中使用的单位,通常用于响应式设计) */
height: 100vh; /* 高度占满整个视口高度 */
background: #fff !important; /* 背景色为白色,并使用!important确保优先级 */
.left-view-item {
line-height: 99rpx; /* 行高设为99rpx */
text-align: center; /* 文本居中对齐 */
font-size: 26rpx; /* 字体大小设为26rpx */
}
.active {
background-color: #ffffff; /* 背景色为白色 */
position: relative; /* 设置相对定位 */
color: #f3514f; /* 文本颜色设为红色 */
/* 伪元素选择器,用于在.active元素前添加内容 */
&::before {
content: ' '; /* 内容为一个空格 */
display: block; /* 设置为块级元素 */
width: 6rpx; /* 宽度设为6rpx */
height: 66rpx; /* 高度设为66rpx */
background-color: #f3514f; /* 背景色为红色 */
position: absolute; /* 绝对定位 */
left: 0; /* 距离左侧为0 */
top: 50%; /* 距离顶部为50% */
transform: translateY(-50%); /* 沿y轴平移-50%,使元素垂直居中 */
}
}
}
右侧菜单样式:
/* 右侧二级分类样式 */
.category-right-view {
width: 100%; /* 宽度占满整个容器 */
height: 100vh; /* 高度占满整个视口高度 */
flex-wrap: wrap; /* 弹性布局的子项换行 */
background: #ffffff !important; /* 背景色为白色,并使用!important确保优先级 */
margin-left: 8rpx; /* 左侧外边距为8rpx */
/* 伪元素选择器,用于在.category-right-view元素前添加内容 */
&::before {
content: ''; /* 内容为空 */
display: block; /* 设置为块级元素 */
width: 6rpx; /* 宽度设为6rpx */
height: 100vh; /* 高度占满整个视口高度 */
background-color: rgba(252, 9, 9, 0.144); /* 背景色为半透明的红色 */
position: absolute; /* 绝对定位 */
}
.right-view-item {
width: 33%; /* 宽度设为容器宽度的33% */
float: left; /* 左浮动,使其左对齐并相邻显示 */
margin-top: 30rpx; /* 上外边距为30rpx */
.navigator {
display: flex; /* 使用弹性布局 */
flex-direction: column; /* 子项沿纵轴排列 */
align-items: center; /* 子项在交叉轴上居中 */
}
/* 注意:这里不应该直接写标签名,应该使用类名或ID来定义样式 */
image {
width: 90rpx; /* 宽度设为90rpx */
height: 90rpx; /* 高度设为90rpx */
}
text {
font-size: 26rpx; /* 字体大小设为26rpx */
margin-top: 18rpx; /* 上外边距为18rpx */
}
}
}
}
ps:代码中出现了 &::before
这种写法,这是伪元素选择器,
所谓“伪元素”,就是在dom结构中本来是不存在的,但是通过css创建出来的元素。
::before ::after
用于向指定元素的前面或者加入特定的内容。