开始前,请先完成首页的开发,详见
【微信小程序-原生开发】实用教程05-首页(含自定义调试模式、插入图片、图文排版、底部留白、添加本地图片)
https://blog.csdn.net/weixin_41192489/article/details/128729732
需求描述
今天整个稍微复杂点的,效果如下:
但在开始前,我们需要做几项其他的准备
升级到最新版的 Tdesign 组件库
按教程01 默认模板创建的项目的 Tdesign 组件不是最新版的,需手动升级一下,操作流程如下:
cnpm i tdesign-miniprogram -S --production
未安装 cnpm 的朋友,先执行 npm i cnpm 安装 cnpm
切换为最新版的调试基础库
默认的调试基础库版本比较低,请按下图进行切换
调整全局样式
通过 app.wxss 可以设置全局样式,以便所有页面共享,现将 app.wxss 里的代码全部替换为下方代码:
/* app.wxss 定义全局样式 */
page {
/* 默认页面底色设置为白色 */
background: white;
/* 底部留白的高度需与底部导航的高度相同 */
padding-bottom: 100rpx;
}
有了全局样式后,便可删除首页中底部的占位区间啦!
pages\index\index.wxml
<view class="blankBar">
view>
pages\index\index.wxss
.blankBar {
/* 底部留白的高度需与底部导航的高度相同 */
height: 100rpx;
}
配置组件按需注入
修改全局配置文件 app.json
"lazyCodeLoading": "requiredComponents",
这两项配置的改变,都是为了实现组件按需注入
,从而提升微信小程序的加载和渲染速度。
添加网络图片素材
因微信小程序的限制,图片视频等媒体素材总大小不能超过200k,所以图片需先上传到 CDN 后引入其网址使用。
让我们将图片的网址整理存到 assets文件夹中(无相关路径的文件夹或文件,请自行创建)
assets\images\美女\data.js
export default {
'1':'https://img-blog.csdnimg.cn/6dca0e87288a4c37b76e7d26e016e299.jpeg',
'2':'https://img-blog.csdnimg.cn/8dd7ab28ae6246b69a1722b3ad18d506.jpeg'
}
assets\images\帅哥\data.js
export default {
'1':'https://img-blog.csdnimg.cn/de253e12408f4133adf8f82982e22ce5.jpeg',
'2':'https://img-blog.csdnimg.cn/e9fb6f4e461744e593ca305440760e16.jpeg',
'3':'https://img-blog.csdnimg.cn/63926e3235434cd8bd30285f5612d303.jpeg',
'4':'https://img-blog.csdnimg.cn/601a29123c17471dac01e358dce8e1fe.jpeg',
}
代码实现
准备工作完毕,终于可以开始开发啦!
我先给出最终的总代码,然后分别解析各部分的核心实现哈:
{
"usingComponents": {
"t-swiper": "tdesign-miniprogram/swiper/swiper",
"t-tabs": "tdesign-miniprogram/tabs/tabs",
"t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel",
"t-avatar": "tdesign-miniprogram/avatar/avatar"
}
}
<view class="swiperBox">
<t-swiper image-props="{{imageProps}}" current="{{current}}" autoplay="{{autoplay}}" duration="{{duration}}" interval="{{interval}}" list="{{swiperList}}" navigation="{{ { type: 'dots-bar' } }}" />
view>
<t-tabs defaultValue="{{defaultTab}}" theme="card" bindchange='tabChange'>
<t-tab-panel wx:for="{{tabList}}" wx:key="index" label="{{item.label}}" value="{{item.index}}" />
t-tabs>
<view wx:for="{{filteredMemberList}}" wx:key="index" class="memberBox">
<t-avatar class="avatar-example" shape="round" image="{{item.imgURL}}" />
<view class="memberName">
{{item.name}}
view>
<view class="memberStaus">
{{item.status}} ing
view>
view>
.swiperBox{
padding: 30rpx;
}
.memberBox{
padding: 20rpx;
display: flex;
align-items: center;
border-bottom: 1rpx solid rgb(223, 217, 217);
background-color: #ffffff;
}
.memberName{
font-weight: bold;
font-size: 40rpx;
padding-left: 30rpx;
}
.memberStaus{
padding-left: 40rpx;
}
// 导入图片素材
import girlImgDic from '../../assets/images/美女/data'
import boyImgDic from '../../assets/images/帅哥/data'
Page({
data: {
// 添加轮播图片的属性
imageProps: {
// 图片按宽度自适应
mode: 'widthFix'
},
// 轮播从下标为 0 的图片开始
current: 0,
// 自动轮播
autoplay: true,
// 每张图片的停留时间
duration: 500,
// 轮播时间间隔
interval: 5000,
// 轮播图的图片列表
swiperList: [
girlImgDic['1'],
girlImgDic['2'],
boyImgDic['4'],
],
// 默认 tab 页签的 index
defaultTab: '0',
// 分类页签 tab 列表
tabList: [{
index: '0',
label: '全部'
},
{
index: '1',
label: '男'
},
{
index: '2',
label: '女'
},
],
// 过滤后的成员列表
filteredMemberList: [],
// 总成员列表,其中 gender '1'为男,'2'为女
allMemberList: [{
imgURL: girlImgDic['1'],
name: '小霞',
gender: '2',
status: '筹备婚礼'
},
{
imgURL: girlImgDic['2'],
name: '若依',
gender: '2',
status: '享受泡澡'
},
{
imgURL: boyImgDic['1'],
name: '约翰',
gender: '1',
status: '忧郁'
},
{
imgURL: boyImgDic['2'],
name: '陈翔',
gender: '1',
status: '思考'
},
{
imgURL: boyImgDic['4'],
name: '李阳',
gender: '1',
status: '沉醉'
},
]
},
// 切换页签时触发
tabChange: function (e) {
let gender = e.detail.value
if (gender !== '0') {
this.setData({
filteredMemberList: this.data.allMemberList.filter(item => item.gender === gender)
})
} else {
this.setData({
filteredMemberList: this.data.allMemberList
})
}
},
// 生命周期--页面加载时执行
onLoad(options) {
this.setData({
filteredMemberList: this.data.allMemberList
})
},
onShow() {
this.getTabBar().init();
},
})
组件文档见
https://tdesign.tencent.com/miniprogram/components/swiper
<view class="swiperBox">
<t-swiper image-props="{{imageProps}}" current="{{current}}" autoplay="{{autoplay}}" duration="{{duration}}" interval="{{interval}}" list="{{swiperList}}" navigation="{{ { type: 'dots-bar' } }}" />
view>
.swiperBox{
padding: 30rpx;
}
// 添加轮播图片的属性
imageProps: {
// 图片按宽度自适应
mode: 'widthFix'
},
// 轮播从下标为 0 的图片开始
current: 0,
// 自动轮播
autoplay: true,
// 每张图片的停留时间
duration: 500,
// 轮播时间间隔
interval: 5000,
// 轮播图的图片列表
swiperList: [
girlImgDic['1'],
girlImgDic['2'],
boyImgDic['4'],
],
重点留意:
widthFix
,以便按手机宽度自适应。
<t-tabs defaultValue="{{defaultTab}}" theme="card" bindchange='tabChange'>
<t-tab-panel wx:for="{{tabList}}" wx:key="index" label="{{item.label}}" value="{{item.index}}" />
t-tabs>
// 默认 tab 页签的 index
defaultTab: '0',
// 分类页签 tab 列表
tabList: [{
index: '0',
label: '全部'
},
{
index: '1',
label: '男'
},
{
index: '2',
label: '女'
},
],
重点留意:页签的切换事件
// 切换页签时触发
tabChange: function (e) {
let gender = e.detail.value
if (gender !== '0') {
this.setData({
filteredMemberList: this.data.allMemberList.filter(item => item.gender === gender)
})
} else {
this.setData({
filteredMemberList: this.data.allMemberList
})
}
},
此处因未访问接口,只是前端按性别字段,对成员列表进行了过滤。
<view wx:for="{{filteredMemberList}}" wx:key="index" class="memberBox">
<t-avatar class="avatar-example" shape="round" image="{{item.imgURL}}" />
<view class="memberName">
{{item.name}}
view>
<view class="memberStaus">
{{item.status}} ing
view>
view>
.memberBox{
padding: 20rpx;
display: flex;
align-items: center;
border-bottom: 1rpx solid rgb(223, 217, 217);
background-color: #ffffff;
}
.memberName{
font-weight: bold;
font-size: 40rpx;
padding-left: 30rpx;
}
.memberStaus{
padding-left: 40rpx;
}
样式部分即最基础的 flex 布局,注意提一下 wxml 中的新语法 wx:for
类似 vue 中的 v-for,用于循环遍历渲染列表,注意其书写格式
wx:for="{{filteredMemberList}}" wx:key="index"
<view class="memberName">
{{item.name}}
view>
本例中,最终渲染的成员列表是 filteredMemberList,但其在最开始是空的,需在页面加载时,赋予初始值 allMemberList,故需使用页面加载时的生命周期 onLoad
// 生命周期--页面加载时执行
onLoad(options) {
this.setData({
filteredMemberList: this.data.allMemberList
})
},