Problems encountered by the WeChat applet picker component and solutions

1. The basic concept of picker

Let’s first take a look at the basic concept of picker in the official document :
the scrolling selector that pops up from the bottom now supports three types of selectors, which are distinguished by mode, which are ordinary selectors, time selectors, and date selectors. The default is ordinary Selector.

important attributes

  • range: selection range, the data type is Array / Object Array, and the range is valid when the mode is a normal selector;
  • value: The value of value indicates which number in the range is selected (the subscript starts from 0), and the data type must be Number;
  • bindchange: bind event, trigger change event when value changes, event.detail = {value: value}.
  • mode: selector type, which can be selector (ordinary selector), multiSelector (multi-column selector), date (time selector), time (date selector), region (province, district selector);

2. Problems encountered

问题说在前面, I encountered a problem with using multiple common selectors on the same page. When one option is selected, other options will also change accordingly.
code show as below:

//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
        })
    }
})

Because the default index value (aka "subscript") is both index, the bound event just changes index. So changing one option changes all other options.

3. How to solve

The first solution that comes to mind is to customize different index values ​​index1, index2, and index3, and bind different time bindchange1, bindchange2, and bindchange3 to change their corresponding index values.
code show as below:

//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
        })
    }
})

This solves the problem of multiple pickers on one page, but now a new problem has been discovered:
为什么多个picker会出现相互影响的问题?比如在第一个选择器选择了3,剩下的选择器点进去默认都是从第3个开始?” 小程序开发工具中的确存在,看了社区的帖子,才知道这个是官方的bug,目前还没有修复。

4. Extension

Multiple pickers are used here, and it is conceivable to use wx:fora loop, so for the convenience of rendering, the data must be modified into an array of objects.

// 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
        })
    }
})

wx:for is bound to the array objArray, the subscript variable name of the current item defaults to index, and the variable name of the current item in the array defaults to item. In order to distinguish the subscript in the option option, use wx:for-item to specify the variable of the current element of the
array The name is itm, use wx:for-index to specify the variable name of the current subscript of the array as idx.

The key point is: customize an attribute corresponding to the current subscript data-current="{ {idx}}", and when the binding event bindChange_select is triggered, it is determined which array object triggered it, and the index value in the array object is changed.

//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>

Five, renderings

insert image description here

Guess you like

Origin blog.csdn.net/qq_44880095/article/details/128543235