这里仅仅记录下我在使用的时候遇到的问题以及如何解决,有可能会出现误导,或者不是最佳实现方式,欢迎批评指正。
提示:微信小程序在不断更新完善,所以看文档真的很重要,同时关注官方文档更新是一个很好的习惯哦。
一)swiper
轮播组件,APP中使用非常广泛,当然小程序中用的也很多,通常情况下都是几张图片,下面会有面板指示点,最直白的理解方式 上面的截图就是一个标准的轮播图,这样应该比较清楚一点。最基本的轮播样式 可通过文档知道各个属性的用途, circular='true' 属性可以知道 轮播是否衔接切换。如果不指定 则轮播结束后 会倒回到第一张,感觉比较生硬,使用了这个属性就会无缝切换到第一张。
swiper最基本的使用:
wxml:
补充说明: data-id="{{item}}"
为组件绑定数据,item
指imgUrls
的某一项的值,index
指imgUrls
的下标。这个属性特别好用,例如 一个商品列表,用户点击了某个商品,我们不仅可以通过下标去获取对应的 商品列表数组 中的商品,也可以 直接绑定该商品的信息。
<swiper autoplay='true' indicator-dots='true' indicator-active-color='#fa6e57' indicator-color='#dadada' circular='true'>
<block wx:for="{{imgUrls}}" wx:key="imgswiper">
<swiper-item bindtap='tapSwiperItem' data-id="{{item}}">
<image src='{{item}}' ></image>
</swiper-item>
</block>
</swiper>
js 相关的处理 imgUrls是轮播的图片的数组 ,
补充说明:e.currentTarget.dataset.id
取出 data-id
绑定的数据
data:{
//-----------------1-----------------
imgUrls:[
"https://images.unsplash.com/photo-1551334787-21e6bd3ab135?w=640",
"../../images/temp/slider.jpg",
"https://images.unsplash.com/photo-1551214012-84f95e060dee?w=640",
"../../images/temp/slider.jpg",
"https://images.unsplash.com/photo-1551446591-142875a901a1?w=640",
"../../images/temp/slider.jpg"
],
//-----------------2-----------------
imgUrls: [
{
img: "https://images.unsplash.com/photo-1551334787-21e6bd3ab135?w=640"
}, {
img: "../../images/temp/slider.jpg",
}, {
img: "https://images.unsplash.com/photo-1551214012-84f95e060dee?w=640"
}, {
img: "https://images.unsplash.com/photo-1551446591-142875a901a1?w=640"
},
],
}
/**
* 点击轮播图
*/
tapSwiperItem:function(e){
console.log("轮播图点击》》》",e)
var index = e.currentTarget.dataset.id
}
imgUrls
是轮播的图片的数组,
1 (对应备注1)在wxml 中取值===》用item
可取到,
2 (对应备注2) 在wxml 中取值===》用item.img
可取到,
如果没有其他要求,数组1即可满足,数组2可以有多个属性来控制,也可以理解为数组2存储的是对象,数组1存储的是元素
补充:数据绑定操作 在wxml中 data-id
则 在js 中用 e.currentTarget.dataset.id
获取对应的值,用data-
来对组件进行数据绑定,在js中取对应的值,data-
后面的就是在js中取出的对应的e.currentTarget.dataset.
后面对应的内容。
至此,一个基本的简单的轮播效果就出来啦,但是,如果仅仅是这样,那就太无聊啦,重要的是扩展,怎么扩展呢,比如轮播的内容是图片和视频混的,比如轮播的指示板不想用圆点,比如tab样式想用轮播实现翻页,比如轮播默认显示的是第二张图片,可以看到第一第三的部分内容,比如.....,自己发挥想象。 OK, 继续来实现这些比如。
ONE 图片视频混排
首先,要确定数据 是图片还是视频,可以让后端小哥哥给个字段表明是图片还是视频,也可以自己通过后缀判断是图片还是视频。如果是视频就用<video />
,如果是图片就用<image />
,当前显示的是图片,需要暂停视频,如果是视频就继续播放,播放视频的时候是否需要继续轮播等。视频是固定在第一个显示还是和图片混合显示位置是不确定的。
wxml:
<swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" indicator-dots="{{indicatorDots}}" circular='true' class='swiper-hw' current-item-id="{{currentItemId}}" bindchange='swiperChange'>
<!--视频位置总在第一个,首先判断是否有视频,如果没有该组件不显示-->
<swiper-item wx:if='{{hasVideo}}' >
<video id='swiperVideo' class="swiper-video" src='{{info.itemVideoPath}}' autoplay='false' loop='true'/>
</swiper-item>
<block wx:for="{{imgUrls}}" wx:key='img'>
<swiper-item>
<view class='swiper-img-center'>
<image src="{{item}}" class="swiper-img" mode='widthFix' />
</view>
</swiper-item>
</block>
<!--视频位置不确定,判断该项内容是否是视频,如果是视频则使用video 否则使用image-->
<block wx:for="{{imgVides}}" wx:key='img'>
<swiper-item>
<video wx:if='{{item.isVideo}}' id='swiperVideo' class="swiper-video" src='{{info.itemVideoPath}}' autoplay='false' loop='true' />
<view wx:else class='swiper-img-center'>
<image src="{{item.url}}" class="swiper-img" mode='widthFix' />
</view>
</swiper-item>
</block>
</swiper>
js:
// todo. 需要完成的逻辑功能,例如 轮播到视频的时候 播放视频,播放视频的时候是否自动轮播等等,进行处理即可
TWO 自定义轮播样式
轮播图默认的是小圆点,但是呢,我想用线条来表示,首先需要把indicator-dots
属性设置为false
,然后在<swiper/>
下面,放置自定义的指示点样式。
注意:自定义的指示点不能放在<swiper/>
里,因为每个<swiper/>
就是一项内容,而指示点是应该独立在<swiper/>
之外的,不能作为<swiper/>
的一个元素。如下效果图;
wxml:
<!-- tab指示点 指示点不会随着轮播的切换而滑动 所以要放在swiper的外面-->
<view class="swiper-dots">
<block wx:for="{{imgUrls}}" wx:key="tabLine" wx:for-item='item' wx:for-index='index'>
<view wx:if='{{curTab === index}}' class="tab-dot b-7c7" />
<view wx:else class="tab-dot bg-bfbfbf"/>
</block>
</view>
wxss:
.swiper-dots {
display: flex;
flex-direction: row;
justify-content: center;
}
.tab-dot{
width: 40rpx;
height: 10rpx;
margin: 4rpx;
}
js:
switchCateTab: function (e) {
console.log('tab 滑动滑动滑动', e)
this.setData({
curTab: e.detail.current
})
}
THREE tab样式用轮播实现翻页
如图所示效果,其实就是每一个轮播的内容是一个循环,也就是说<swiper-item/>
放一个数组,或者可以直接理解为一个二维数组(也许不是很准确,我是这么理解的😂)。tab指示器的效果同TWO的实现方式,当然,如果同一个页面有两个自定义指示器的时候,要用两个变量分别存储,否则滑动的时候,两个同步滑动就不好了。
wxml
<!--自定义样式轮播图 -->
<swiper class="custom-swiper" bindchange='switchTab'>
<!-- tab轮播-->
<swiper-item class='tab-swiper' wx:for="{{tabs}}" wx:key="tabs" wx:for-item='item' wx:for-index='index'>
<block wx:for="{{item}}" wx:key="subTabs" wx:for-item='item' wx:for-index='index'>
<view class="flex-column" data-item='{{item}}' bindtap="tapTabItem">
<image src="{{item.icon}}" class="tab-icon"></image>
<text class="font28">{{item.name}}</text>
</view>
</block>
</swiper-item>
</swiper>
<!-- tab指示点 指示点不会随着轮播的切换而滑动 所以要放在swiper的外面-->
<view class="swiper-dots">
<block wx:for="{{tabs}}" wx:key="tabLine" wx:for-item='item' wx:for-index='index'>
<view wx:if='{{curTab === index}}' class="tab-dot b-7c7" />
<view wx:else class="tab-dot bg-bfbfbf" />
</block>
</view>
如果说滑动不是一屏一屏地滑动,可以用<scrollView/>来实现,里面用一个数组就可以实现,不过这种方式,有可能出现某个tab滑动一半就停下的现象。如下图所示:
需要注意的是,当文字过长时会出现不协调,需要做下处理。
wxml:
<!-- 最近浏览 -->
<view class="flex-column b-white padding20">
<text class='font36 c-333'>最近浏览</text>
<scroll-view scroll-x class='recently-scroll'>
<view class='flex-row'>
<view class='flex-column' wx:for-items="{{recentlys}}" wx:key="key" wx:for-index="idx" wx:for-item="item">
<view class='flex-column' data-id='{{idx}}' bindtap='tapStudyRecord'>
<image class='scroll-item-img' src='{{item.img}}' mode='widthFix' binderror="errorFunction1" data-errorimg="{{idx}}"></image>
</view>
<text class='font22 scroll-item-txt'>{{tools.sub4(item.title)}}</text>
</view>
</view>
</scroll-view>
</view>
FOUR 图片显示三张,显示第一第三的部分,第二完整
查看文档可以发现
previous-margin
前边距,可用于露出前一项的一小部分next-margin
后边距,可用于露出后一项的一小部分,这两个属性可以实现这个效果。
wxml:
<swiper class='swiper' indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" next-margin="135rpx" current-item-id="{{currentItemId}}" previous-margin="135rpx" circular='true'>
<block wx:for="{{imgUrls}}" wx:key="imgswiper">
<swiper-item item-id="{{index}}" data-item-id="{{index}}" class='margin-t20 margin-b20'>
<image src='{{item}}' class='swiper-img fillet' mode='widthFix'></image>
</swiper-item>
</block>
</swiper>
<image/>有默认的大小,所以在使用的时候,我们必须指定image的宽高,或者指定mode 来控制图片的显示方式。
其实 ,扩展的这些看似很多,无非就是把自己用的东西充分融合,并没有什么新东西。感觉写的不是很清楚明了,但是还没找到更好的表达方式,先凑合着看😂😂。
当想要实现某个效果的时候,先想下用什么实现,然后去尝试,不断测试,不断优化,也是一种成长的过程。
二)tab
可以直接在全局配置中,进行配置就可以了。
在app.json中配置tabBar
就可以了。其中 list 接受一个数组,只能配置最少 2 个、最多 5 个 tab。tab 按数组的顺序排序,每个项都是一个对象。
"tabBar": {
"selectedColor": "#503291",
"color": "#bfbfbf",
"backgroundColor": "white",
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "images/tab/home_gray.png",
"selectedIconPath": "images/tab/home.png"
},
{
"pagePath": "pages/index/index",
"text": "商品分类",
"iconPath": "images/tab/category_gary.png",
"selectedIconPath": "images/tab/category.png"
},
{
"pagePath": "pages/shopcart/shopcart",
"text": "购物车",
"iconPath": "images/tab/shop_cart_gray.png",
"selectedIconPath": "images/tab/shop_cart.png"
},
{
"pagePath": "pages/personal/personal",
"text": "我",
"iconPath": "images/tab/personal_gray.png",
"selectedIconPath": "images/tab/personal.png"
}
]
},
如果想自己自定义一个,也是可以的,不过对生命周期的控制,需要留心。为了练习可以自定义下玩玩,一般不会在项目中自定义(二般不保证),会比较累赘。我觉得拼多多比较厉害的就是去掉了购物车的功能,看上了就买,不买可能就找不到这个了,不给你留后路去纠结考虑。哈哈哈哈哈
三)选择器
微信小程序 picker 文档为我们提供了5中选择器,【 selector
普通选择器 、 multiSelector
多列选择器、time
时间选择器、date
日期选择器、region
省市区选择器】
省市区选择器:
可以直接使用微信提供的省市区选择器,用着很简单,BUT,地址信息可能会和自己公司的数据不符,并且只能获取省市区的名称,和数据库对接的时候不方便。
wxml:
<picker mode="region" bindchange="bindRegionChange" value="{{region}}" custom-item="{{customItem}}">
<view class='flex-row between'>
<view wx:if='{{isSelAddress}}' class='font28 c-333 txt-center'> {{region[0]}},{{region[1]}},{{region[2]}}</view>
<view wx:else class='font28 c-333 txt-center'>{{adressStr}}</view>
<!-- <view class='font28 c-333 txt-center'>{{district}}</view> -->
<view class='flex-row'>
<text class='font28 c-999 txt-center width80'>选择</text>
<image src='../../../images/common/right_arrow.png' mode='widthFix' class='right-icon' />
</view>
</view>
</picker>
js:
/**
* 地址选择
*/
bindRegionChange(e) {
console.log('picker发送选择改变,携带值为', e.detail.value)
this.setData({
region: e.detail.value,
isSelAddress: true
})
},
picker 实现自己的省市区选择器。这篇写的很详细,推荐 微信小程序-官方组件picker云开发省市区三级联动选择器,当然,你也可以把json格式的数据存储在本地,直接进行读取。
自定义省市区选择器
picker
中range
放的就是picker
显示的数据,可以是一个对象数组也可以直接放一个数组,如果是对象数组则需要用range-key
指定对象中的key来作为选择器显示的内容,如果直接用的数组,则不需要用range-key
。bindcolumnchange
会在滑动选择器的时候调用,可以在e.detail中取到滑动的那一列以及该列的滑动位置(也就是数组中的下标), bindchange
点击确定的时候调用,可以在e.detail.value中取到用户选择的值。
对于省市区的数组,可以这样理解,[[省列表],[市列表],[区/县列表]]
对应的真实数据是这个样子的 ...... 代指同级的其他数据,
[
[ "河北省",......],
[["石家庄市", "唐山市", "秦皇岛市", "邯郸市", "邢台市", "保定市", "张家口市", "承德市", "沧州市", "廊坊市", "衡水市"],......],
[["长安区", "桥西区", "新华区", "井陉矿区", "裕华区", "藁城区", "鹿泉区", "栾城区", "井陉县", "正定新区", "行唐县", "灵寿县", "高邑县", "深泽县", "赞皇县", "无极县", "平山县", "元氏县", "赵县", "辛集市", "晋州市", "新乐市", "高新区", "经济技术开发区"], ["路南区", "路北区", "古冶区", "开平区", "丰南区", "丰润区", "曹妃甸区", "滦县", "滦南县", "乐亭县", "迁西县", "玉田县", "遵化市", "迁安市"], ["海港区", "山海关区", "北戴河区", "抚宁区", "青龙满族自治县", "昌黎县", "卢龙县", "北戴河新区"],...... ]
]
一个省对应多个市,1个市对应多个区,所以市、区需要用二维数组,也就是二维数组中放着二维数组,对于这种嵌套,只要准确找到下标就可以对应相应的数据了。
wxml:
<picker mode='multiSelector' bindchange='bindMultiPickerChange' bindcolumnchange='bindMultiPickerColumnChange' value="{{multiIndex}}" range="{{multiArray}}">
<view class="picker">
当前选择:{{multiArray[0][multiIndex[0]]}},{{multiArray[1][multiIndex[1]]}},{{multiArray[2][multiIndex[2]]}}
</view>
</picker>
js:
/**
* 滑动选择器 改变对应的值
*/
bindMultiPickerColumnChange: function (e) {
console.log('picker选择器 columnChangeSelector', e)
let that = this
let column = e.detail.column // 选择的第几列 也就是 省市区 滑动的是哪一个 0省 1市 2区
let value = e.detail.value // 选择的具体的第几个值 数组中的第几个
let multiArray = that.data.multiArray
let multiIndex = that.data.multiIndex
multiIndex[column] = value
multiArray = [addressData.getProvinceName(), addressData.getCityName()[multiIndex[0]], addressData.getDistrictName()[multiIndex[0]][multiIndex[1]]]
console.log('picker选择器 multiIndex', addressData.getProvinceName())
console.log('picker选择器 multiIndex', addressData.getCityName()[multiIndex[1]])
console.log('picker选择器 getDistrictName', addressData.getDistrictName())
console.log('picker选择器 multiIndex', multiIndex)
console.log('picker选择器 multiArray', multiArray)
that.setData({
multiArray: multiArray,
multiIndex: multiIndex
})
}
multiArray 是省市区数据数组,multiIndex是对应的下标的值,因为wxml中直接用multiArray来作为选择的值,所以不需要用户点击确定,只要更新multiArray,数据就自动适配到页面上了。
有时候会觉得,我想用但是看不懂文档,或者按照文档的做了,但是没效果,SO,到Github上,查看官方示例,微信小程序示例, 亲测,这个方法很好使。
最后,惯例 送给自己一句话
今天夜凉望你心暖安康
鹿先森乐队 晚安 中的一句
微信小程序开发系列笔记:
微信小程序开发笔记(四)
微信小程序开发笔记(三)
微信小程序开发笔记(二)
微信小程序开发笔记(一)