微信小程序picker組件遇到的問題與解決方案

1、picker基本概念

固然先看官方文檔 picker說明搞清楚基本概念
「從底部彈起的滾動選擇器,現支持三種選擇器,經過mode來區分,分別是普通選擇器,時間選擇器,日期選擇器,默認是普通選擇器。」
幾個主要屬性:
range: 選取範圍,數據類型爲Array / Object Array,mode爲 普通選擇器 時,range 有效;
value: value 的值表示選擇了 range 中的第幾個(下標從 0 開始),數據類型確定是Number;
bindchange: 綁定事件,value 改變時觸發 change 事件,event.detail = {value: value}。html

2、遇到問題

今天在同一個頁面使用多個普通選擇器遇到了問題,選擇一個選項,其餘選項也跟隨着改變了.
代碼以下:git

//picker.wxml:   
<view class="column_list" >
        <text class="font15">選項一</text>
        <picker class="inputText" bindchange="bindchange1" value="{{index}}" range="{{option1}}">
            <view class="select_picker">
                {{option1[index]}}
                <image  mode="aspectFit"  class="select_arrow" src="../../images/select_arrow.png"></image>
            </view>
        </picker>
    </view>
    <view class="column_list" >
        <text class="font15">選項二</text>
        <picker class="inputText" bindchange="bindchange1" value="{{index}}" range="{{option2}}">
            <view class="select_picker">
                {{option2[index]}}
                <image  mode="aspectFit"  class="select_arrow" src="../../images/select_arrow.png"></image>
            </view>
        </picker>
    </view>
    <view class="column_list" >
        <text class="font15">選項三</text>
        <picker class="inputText" bindchange="bindchange1" value="{{index}}" range="{{option3}}">
            <view class="select_picker">
                {{option3[index]}}
                <image  mode="aspectFit"  class="select_arrow" src="../../images/select_arrow.png"></image>
            </view>
        </picker>
    </view>

//picker.js
    Page({
    data: {
        index:0,//設置索引值默認爲0
        option1: ['1', '2', '3','4','5'],
        option2: ['一', '二', '三','四','五'],
        option3: ['①', '②', '③','④','⑤'],
    },
    bindchange1:function (e) {
       // console.log('picker發送選擇改變,攜帶值爲', e.detail.value)
       // 設置這個攜帶值賦值給索引值index
       // 因此option1 ,option2 ,option3的索引值都是同樣的
        this.setData({
            index: e.detail.value
        })
    }
})

由於默認索引值(也叫「下標」)都是index,綁定事件也只是改變了index。因此改變一個選項,其餘選項都跟着改變了。github

3、怎麼解決呢?

首先想到的是給三個選項自定義不一樣的索引值index1,index2,index3,分別綁定不一樣的事件bindchange1,bindchange2,bindchange3改變其對應的索引值,互不干擾。
代碼以下:json

//picker.wxml: 
 <view class="column_list" >
        <text class="font15">選項一</text>
        <picker class="inputText" bindchange="bindchange1" value="{{index1}}" range="{{option1}}">
            <view class="select_picker">
                {{option1[index1]}}
                <image  mode="aspectFit"  class="select_arrow" src="../../images/select_arrow.png"></image>
            </view>
        </picker>
    </view>
    <view class="column_list" >
        <text class="font15">選項二</text>
        <picker class="inputText" bindchange="bindchange2" value="{{index2}}" range="{{option2}}">
            <view class="select_picker">
                {{option2[index2]}}
                <image  mode="aspectFit"  class="select_arrow" src="../../images/select_arrow.png"></image>
            </view>
        </picker>
    </view>
    <view class="column_list" >
        <text class="font15">選項三</text>
        <picker class="inputText" bindchange="bindchange3" value="{{index3}}" range="{{option3}}">
            <view class="select_picker">
                {{option3[index3]}}
                <image  mode="aspectFit"  class="select_arrow" src="../../images/select_arrow.png"></image>
            </view>
        </picker>
    </view>
    // picker.js
    Page({
    data: {
        index1:0,
        index2:0,
        index3:0,
        option1: ['1', '2', '3','4','5'],
        option2: ['一', '二', '三','四','五'],
        option3: ['①', '②', '③','④','⑤'],
    },
    bindchange1:function (e) {
        this.setData({
            index1: e.detail.value
        })
    },
    bindchange2:function (e) {
        this.setData({
            index2: e.detail.value
        })
    },
    bindchange3:function (e) {
        this.setData({
            index3: e.detail.value
        })
    }

})

這樣,一個頁面使用多個picker的問題就解決了。但在發現小一個問題。
搜索到jiong也提出了這個問題:
「爲何多個picker會出現相互影響的問題?好比在第一個選擇器選擇了3,剩下的選擇器點進去默認都是從第3個開始?」
小程序開發工具(PC端)中的確存在,也沒有好的解決辦法。
可是,我用手機親測不存在這個問題。新版小程序開發工具已經修復此Bug小程序

4、延伸思考

在這裏我屢次使用了picker,因而我想到了使用循環 wx:for,(之後若是還要用能夠作成一個模板)
那麼數據就要修改成對象的數組(Object Array) ,我理解爲json格式(不知道對不對)segmentfault

picker.js

// picker.js
Page({
    data: {
    //每一個對象就是一個選擇器,有本身的索引值index,標題title,選項option(又是一個數組)
        objArray:[
            {
                index:0,
                title:'選項一',
                option: ['1', '2', '3','4','5'],
            },
            {
                index:0,
                title:'選項二',
                option: ['一', '二', '三','四','五'],
            },
            {
                index:0,
                title:'選項三',
                option: ['①', '②', '③','④','⑤']
            },
        ]
    },
    // 綁定事件,由於不能用this.setData直接設置每一個對象的索引值index。
    // 因此用自定義屬性current來標記每一個數組對象的下標
    bindChange_select: function(ev) {
    // 定義一個變量curindex 儲存觸發事件的數組對象的下標
        const curindex = ev.target.dataset.current
    // 根據下標 改變該數組對象中的index值
        this.data.objArray[curindex].index = ev.detail.value
    // 把改變某個數組對象index值以後的全新objArray從新 賦值給objArray
        this.setData({
            objArray: this.data.objArray
        })
    }
})

picker.wxml

wx:for綁定數組objArray,當前項的下標變量名默認爲index,數組當前項的變量名默認爲item,爲了區分選項option中的下標
使用 wx:for-item 能夠指定數組當前元素的變量名爲itm,
使用 wx:for-index 能夠指定數組當前下標的變量名爲idx
關鍵點是:自定義一個屬性對應當前下標 data-current="{{idx}}",綁定事件bindChange_select觸發時判斷出是哪一個數組對象觸發的,就改變該數組對象中的index值數組

//picker.wxml:
 <view class="column_list mt_10" wx:for="{{objArray}}" wx:for-item="itm"  wx:for-index="idx" >
        <text class="font15">{{itm.title}} </text>
        <picker  class="inputText"  bindchange="bindChange_select" value="{{itm.index}}" data-current="{{idx}}" range="{{itm.option}}" >
            <view class="select_picker">
                 {{itm.option[itm.index]}}
                <image  mode="aspectFit"  class="select_arrow" src="../../images/select_arrow.png"></image>
            </view>
        </picker>
    </view>

圖片描述
完整案例工具

相關文章
相關標籤/搜索