微信小程序开发笔记(五)官方组件及扩展

微信小程序示例

这里仅仅记录下我在使用的时候遇到的问题以及如何解决,有可能会出现误导,或者不是最佳实现方式,欢迎批评指正。

提示:微信小程序在不断更新完善,所以看文档真的很重要,同时关注官方文档更新是一个很好的习惯哦。

一)swiper

官方文档Swiper

swiper.jpg

轮播组件,APP中使用非常广泛,当然小程序中用的也很多,通常情况下都是几张图片,下面会有面板指示点,最直白的理解方式 上面的截图就是一个标准的轮播图,这样应该比较清楚一点。最基本的轮播样式 可通过文档知道各个属性的用途, circular='true' 属性可以知道 轮播是否衔接切换。如果不指定 则轮播结束后 会倒回到第一张,感觉比较生硬,使用了这个属性就会无缝切换到第一张。

swiper最基本的使用:
wxml:
补充说明: data-id="{{item}}" 为组件绑定数据,itemimgUrls的某一项的值,indeximgUrls的下标。这个属性特别好用,例如 一个商品列表,用户点击了某个商品,我们不仅可以通过下标去获取对应的 商品列表数组 中的商品,也可以 直接绑定该商品的信息。

   <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/>的一个元素。如下效果图;

img

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的实现方式,当然,如果同一个页面有两个自定义指示器的时候,要用两个变量分别存储,否则滑动的时候,两个同步滑动就不好了。

swiperTab.png

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滑动一半就停下的现象。如下图所示:


scrollTabs.png

需要注意的是,当文字过长时会出现不协调,需要做下处理。
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 图片显示三张,显示第一第三的部分,第二完整

image.png

查看文档可以发现
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

可以直接在全局配置中,进行配置就可以了。

tabbarStyle.png

在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

微信小程序 picker 文档为我们提供了5中选择器,【 selector 普通选择器 、 multiSelector 多列选择器、time 时间选择器、date 日期选择器、region 省市区选择器】

省市区选择器:

可以直接使用微信提供的省市区选择器,用着很简单,BUT,地址信息可能会和自己公司的数据不符,并且只能获取省市区的名称,和数据库对接的时候不方便。


image.png

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格式的数据存储在本地,直接进行读取。

自定义省市区选择器

pickerrange放的就是picker显示的数据,可以是一个对象数组也可以直接放一个数组,如果是对象数组则需要用range-key指定对象中的key来作为选择器显示的内容,如果直接用的数组,则不需要用range-keybindcolumnchange会在滑动选择器的时候调用,可以在e.detail中取到滑动的那一列以及该列的滑动位置(也就是数组中的下标), bindchange点击确定的时候调用,可以在e.detail.value中取到用户选择的值。

image.png

对于省市区的数组,可以这样理解,[[省列表],[市列表],[区/县列表]]对应的真实数据是这个样子的 ...... 代指同级的其他数据,

[
[ "河北省",......],
[["石家庄市", "唐山市", "秦皇岛市", "邯郸市", "邢台市", "保定市", "张家口市", "承德市", "沧州市", "廊坊市", "衡水市"],......],
[["长安区", "桥西区", "新华区", "井陉矿区", "裕华区", "藁城区", "鹿泉区", "栾城区", "井陉县", "正定新区", "行唐县", "灵寿县", "高邑县", "深泽县", "赞皇县", "无极县", "平山县", "元氏县", "赵县", "辛集市", "晋州市", "新乐市", "高新区", "经济技术开发区"], ["路南区", "路北区", "古冶区", "开平区", "丰南区", "丰润区", "曹妃甸区", "滦县", "滦南县", "乐亭县", "迁西县", "玉田县", "遵化市", "迁安市"], ["海港区", "山海关区", "北戴河区", "抚宁区", "青龙满族自治县", "昌黎县", "卢龙县", "北戴河新区"],...... ]
] 
image.png

一个省对应多个市,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上,查看官方示例,微信小程序示例, 亲测,这个方法很好使。

最后,惯例 送给自己一句话
今天夜凉望你心暖安康
鹿先森乐队 晚安 中的一句

微信小程序开发系列笔记:
微信小程序开发笔记(四)
微信小程序开发笔记(三)
微信小程序开发笔记(二)
微信小程序开发笔记(一)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容