在设计一个小程序的首页时,包含轮播图、通知栏和商品列表这三个元素是非常常见且有效的布局方式。这样的设计既能够吸引用户的注意力,又能够高效地展示信息和商品。
小程序首页幻灯片通常位于小程序的顶部或显著位置,通过滑动屏幕可以切换不同的幻灯片内容。这些幻灯片可以包含图片、文字、链接等元素,为用户提供丰富的视觉体验和信息传递。
组件模板里找到轮播组件,把组件拖动进设计器。
轮播组件显示数据来源于API,配置域名、API接口
点击数据绑定,找到对应API返回轮播数据列表。
由于轮播图片、标题不同用户API返回结构会不同。所以要进行数据源绑定。
拖动通知栏组件进设计区,同样跟轮播增加通知API接口,绑定数据源、标题。
首先我们要造好一个商品模板,包括了图片、标题、价格及划线价格,大家参照FLEX组件教程或者直接用组件模板里的模板快速复用。
商品API参照轮播的API进行新增,但有一个小细节,我们希望拖动页面时进行无限加载商品数据。API上面有个小细节,大家要进行开启。
定位循环绑定产品FLEX组件进行数据源绑定。
首页核心展示我们这里就基本上完成了。
点击保存源码至本地,我们即可看见效果了。
<template>
<view class="container container329916">
<view class="flex flex-wrap diygw-col-24 justify-center items-center flex15-clz" @tap="navigateTo" data-type="page" data-url="/pages/goods">
<text class="flex icon diygw-col-0 diy-icon-search"></text>
<text class="diygw-col-0"> 搜索 </text>
</view>
<view class="flex diygw-col-24 swiper-clz">
<swiper :current="swiperIndex" class="swiper" @change="changeSwiper" indicator-color="rgba(51, 51, 51, 0.39)" indicator-active-color="#fff" indicator-dots="true" autoplay interval="3000" circular="true" style="height: 276rpx">
<swiper-item v-for="(item, index) in swipers.rows" :key="index" class="diygw-swiper-item">
<view class="diygw-swiper-item-wrap">
<image :src="item.img" class="diygw-swiper-image"></image>
<view class="diygw-swiper-item-title swiper-title">
{{ item.title }}
</view>
</view>
</swiper-item>
</swiper>
</view>
<view class="flex diygw-col-24 noticebar-clz">
<diy-noticebar class="flex1 diy-notice-bar" :remote="true" :list="notices.rows" color="#fb4833" bgColor="#ffe8e8" leftIcon="diy-icon-notification">
<block v-slot:content>
<text class="diy-notice-item" v-for="(item, index) in notices.rows" :key="index">
{{ item.title }}
</text>
</block>
</diy-noticebar>
</view>
<view v-if="goods.total > 0" class="flex diygw-col-24 items-stretch flex-wrap flex-clz">
<view v-for="(item, index) in goods.rows" :key="index" class="flex flex-wrap diygw-col-12 flex-direction-column items-stretch flex6-clz" @tap="navigateTo" data-type="page" data-url="/pages/goods/detail" :data-id="item.id">
<view class="flex flex-wrap diygw-col-0 flex-direction-column items-center">
<image :src="item.img" class="image-size diygw-image diygw-col-24" mode="aspectFit"></image>
</view>
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-between flex20-clz">
<text class="diygw-col-0 text11-clz">
{{ item.title }}
</text>
<text class="diygw-text-line2 diygw-col-0">
{{ item.remark }}
</text>
<view class="flex flex-wrap diygw-col-0 items-center">
<text class="diygw-col-0 text7-clz"> ¥{{ item.price }} </text>
<text class="diygw-text-line2 diygw-col-0 text8-clz"> ¥{{ item.linePrice }} </text>
</view>
</view>
</view>
</view>
<view v-if="globalData.isshow && goods.code == 200 && goods.total == 0" class="flex flex-wrap diygw-col-24 flex-direction-column items-center flex1-clz">
<image src="/static/zwjl.png" class="image1-size diygw-image diygw-col-0" mode="widthFix"></image>
<text class="diygw-col-0 text-clz"> 未找到任何数据 </text>
</view>
<view class="flex flex-wrap diygw-col-24 items-end diygw-bottom flex2-clz">
<view class="flex flex-wrap diygw-col-6 flex-direction-column items-center flex8-clz">
<view class="flex flex-wrap diygw-col-0 flex-direction-column items-center">
<image src="/static/sy3on.png" class="image2-size diygw-image diygw-col-0" mode="widthFix"></image>
</view>
<text class="diygw-text-line1 diygw-col-0"> 首页 </text>
</view>
<view class="flex flex-wrap diygw-col-6 flex-direction-column items-center flex11-clz" @tap="navigateTo" data-type="page" data-url="/pages/goods" data-redirect="1">
<view class="flex flex-wrap diygw-col-0 flex-direction-column items-center">
<image src="/static/fl.png" class="image8-size diygw-image diygw-col-0" mode="widthFix"></image>
</view>
<text class="diygw-text-line1 diygw-col-0"> 分类 </text>
</view>
<view class="flex flex-wrap diygw-col-6 flex-direction-column items-center flex9-clz" @tap="navigateTo" data-type="page" data-url="/pages/cart" data-redirect="1">
<view class="flex flex-wrap diygw-col-0 flex-direction-column items-center">
<text v-if="userInfo.carts && userInfo.carts.length > 0" class="diygw-text-line1 diygw-col-0 animate__animated animate__heartBeat animate__infinite text2-clz"> </text>
<image src="/static/gwc.png" class="image5-size diygw-image diygw-col-0" mode="widthFix"></image>
</view>
<text class="diygw-text-line1 diygw-col-0"> 购物车 </text>
</view>
<view class="flex flex-wrap diygw-col-6 flex-direction-column items-center flex4-clz" @tap="navigateTo" data-type="page" data-url="/pages/articles" data-redirect="1">
<view class="flex flex-wrap diygw-col-0 flex-direction-column items-center">
<image src="/static/cp1.png" class="image3-size diygw-image diygw-col-0" mode="widthFix"></image>
</view>
<text class="diygw-text-line1 diygw-col-0"> 文章 </text>
</view>
<view class="flex flex-wrap diygw-col-6 flex-direction-column items-center flex12-clz" @tap="navigateTo" data-type="page" data-url="/pages/user" data-redirect="1">
<view class="flex flex-wrap diygw-col-0 flex-direction-column items-center">
<image src="/static/wd.png" class="image4-size diygw-image diygw-col-0" mode="widthFix"></image>
</view>
<text class="diygw-text-line1 diygw-col-0"> 我的 </text>
</view>
</view>
<view class="clearfix"></view>
</view>
</template>
<script>
export default {
data() {
return {
//用户全局信息
userInfo: {},
//页面传参
globalOption: {},
//自定义全局变量
globalData: { isshow: false },
swipersNum: 1,
swipers: {
rows: [
{
id: 0,
title: '',
remark: '',
img: '',
path: null,
userId: 0,
createTime: '',
updateTime: '',
deleteTime: null
}
],
total: 0,
code: 0,
msg: ''
},
noticesNum: 1,
notices: {
rows: [
{
id: 0,
title: '',
remark: '',
userId: 0,
createTime: '',
updateTime: '',
deleteTime: null
}
],
total: 0,
code: 0,
msg: ''
},
goodsNum: 1,
goods: {
rows: [
{
id: 0,
title: '',
remark: '',
img: '',
imgs: '',
status: '',
content: '',
price: '',
amount: 0,
sellamonut: null,
skus: '',
sortnum: null,
cateId: 0,
userId: 0,
createTime: '',
updateTime: '',
deleteTime: null,
linePrice: '',
skuType: ''
}
],
total: 0,
code: 0,
msg: ''
},
swiperIndex: 0
};
},
onShow() {
this.setCurrentPage(this);
},
onLoad(option) {
this.setCurrentPage(this);
if (option) {
this.setData({
globalOption: this.getOption(option)
});
}
this.init();
},
methods: {
async init() {
await this.swipersApi();
await this.noticesApi();
await this.goodsApi();
},
// 轮播数据 API请求方法
async swipersApi(param) {
let thiz = this;
param = param || {};
//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
let http_url = '/cms/api.swiper/list';
let http_data = {
pageNum: this.swipersNum,
pageSize: 10,
pageSize: param.pageSize || '5'
};
let http_header = {};
let swipers = await this.$http.post(http_url, http_data, http_header, 'json');
this.swipers = swipers;
this.globalData.isshow = true;
},
// 公告数据 API请求方法
async noticesApi(param) {
let thiz = this;
param = param || {};
//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
let http_url = '/cms/api.notice/list';
let http_data = {
pageNum: this.noticesNum,
pageSize: 10,
pageSize: param.pageSize || '5'
};
let http_header = {};
let notices = await this.$http.post(http_url, http_data, http_header, 'json');
this.notices = notices;
},
// 商品数据 API请求方法
async goodsApi(param) {
let thiz = this;
param = param || {};
//如果请求要重置页面,请配置点击附加参数refresh=1 增加判断如输入框回调param不是对象
if (param.refresh || typeof param != 'object') {
this.goodsNum = 1;
}
//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
let http_url = '/shop/api.goods/list';
let http_data = {
pageNum: this.goodsNum,
pageSize: 10
};
let http_header = {};
let goods = await this.$http.post(http_url, http_data, http_header, 'json');
let datarows = goods.rows;
if (http_data.pageNum == 1) {
this.goods = goods;
} else if (datarows) {
let rows = this.goods.rows.concat(datarows);
goods.rows = rows;
this.goods = goods;
}
if (datarows && datarows.length > 0) {
this.goodsNum = this.goodsNum + 1;
}
this.globalData.isshow = true;
},
changeSwiper(evt) {
let swiperIndex = evt.detail.current;
this.setData({ swiperIndex });
}
},
onPullDownRefresh() {
// 商品数据 API请求方法
this.goodsNum = 1;
this.goodsApi();
uni.stopPullDownRefresh();
},
onReachBottom() {
// 商品数据 API请求方法
this.goodsApi();
}
};
</script>
<style lang="scss" scoped>
.flex15-clz {
padding-top: 16rpx;
border-bottom-left-radius: 120rpx;
padding-left: 10rpx;
padding-bottom: 16rpx;
border-top-right-radius: 120rpx;
margin-right: 20rpx;
background-color: #ffffff;
margin-left: 20rpx;
box-shadow: 0rpx 0rpx 12rpx 2px rgba(219, 219, 219, 0.31);
overflow: hidden;
width: calc(100% - 20rpx - 20rpx) !important;
border-top-left-radius: 120rpx;
margin-top: 10rpx;
border-bottom-right-radius: 120rpx;
margin-bottom: 10rpx;
padding-right: 10rpx;
}
.icon {
font-size: 36rpx;
}
.swiper-clz {
margin-left: 20rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
width: calc(100% - 20rpx - 20rpx) !important;
border-top-left-radius: 12rpx;
margin-top: 10rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
margin-bottom: 10rpx;
margin-right: 20rpx;
}
.swiper-title {
background-color: rgba(0, 0, 0, 0.281);
color: #e6e6e6;
}
.noticebar-clz {
margin-left: 20rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
width: calc(100% - 20rpx - 20rpx) !important;
border-top-left-radius: 12rpx;
margin-top: 10rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
margin-bottom: 10rpx;
margin-right: 20rpx;
}
.flex-clz {
padding-top: 10rpx;
padding-left: 10rpx;
padding-bottom: 10rpx;
padding-right: 10rpx;
}
.flex6-clz {
padding-top: 20rpx;
border-bottom-left-radius: 12rpx;
padding-left: 20rpx;
padding-bottom: 20rpx;
border-top-right-radius: 12rpx;
margin-right: 10rpx;
background-color: #ffffff;
margin-left: 10rpx;
box-shadow: 0rpx 0rpx 12rpx 2px rgba(219, 219, 219, 0.31);
overflow: hidden;
width: calc(50% - 10rpx - 10rpx) !important;
border-top-left-radius: 12rpx;
margin-top: 10rpx;
border-bottom-right-radius: 12rpx;
margin-bottom: 10rpx;
padding-right: 20rpx;
}
.image-size {
height: 200rpx !important;
width: 100%;
}
.flex20-clz {
padding-top: 10rpx;
flex: 1;
padding-left: 10rpx;
padding-bottom: 10rpx;
padding-right: 10rpx;
}
.text11-clz {
font-weight: bold;
font-size: 28rpx !important;
}
.text7-clz {
color: #f20000;
font-weight: bold;
font-size: 28rpx !important;
}
.text8-clz {
text-decoration: line-through;
}
.flex1-clz {
padding-top: 20rpx;
padding-left: 20rpx;
padding-bottom: 20rpx;
padding-right: 20rpx;
}
.image1-size {
height: 400rpx !important;
width: 400rpx !important;
}
.text-clz {
color: #969696;
font-size: 28rpx !important;
}
.flex2-clz {
border-top: 2rpx solid #e4e4e4;
padding-top: 16rpx;
border-bottom-left-radius: 0rpx;
bottom: 0rpx;
padding-left: 16rpx;
padding-bottom: 16rpx;
border-top-right-radius: 24rpx;
background-color: #ffffff;
box-shadow: 0rpx 4rpx 12rpx rgba(31, 31, 31, 0.16);
overflow: visible;
left: 0rpx;
border-top-left-radius: 24rpx;
border-bottom-right-radius: 0rpx;
padding-right: 16rpx;
}
.flex8-clz {
color: #fa240b;
flex: 1;
}
.image2-size {
height: 48rpx !important;
width: 48rpx !important;
}
.flex11-clz {
flex: 1;
}
.image8-size {
height: 48rpx !important;
width: 48rpx !important;
}
.flex9-clz {
flex: 1;
}
.text2-clz {
border: 2rpx solid #eee;
border-bottom-left-radius: 40rpx;
-webkit-animation-duration: 5000ms;
color: #ffffff;
animation-delay: 1000ms;
-webkit-animation-delay: 1000ms;
border-top-right-radius: 40rpx;
right: -8rpx;
background-color: rgba(255, 17, 17, 0.91);
animation-duration: 5000ms;
flex-shrink: 0;
overflow: hidden;
top: -8rpx;
width: 16rpx !important;
border-top-left-radius: 40rpx;
border-bottom-right-radius: 40rpx;
position: absolute;
height: 16rpx !important;
}
.image5-size {
height: 48rpx !important;
width: 48rpx !important;
}
.flex4-clz {
flex: 1;
}
.image3-size {
height: 48rpx !important;
width: 48rpx !important;
}
.flex12-clz {
flex: 1;
}
.image4-size {
height: 48rpx !important;
width: 48rpx !important;
}
.container329916 {
padding-bottom: 160rpx;
background-color: #f5f5f5;
}
</style>
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。