# Picker 选择器

选择器组件,用于表单。

# 引入

import PressPicker from 'press-ui/press-picker/press-picker';

export default {
  components: {
    PressPicker,
  }
}

# 代码演示

# 基本用法

示例

<press-picker
  v-if="pickerOption.tip.show"
  :title="pickerOption.tip.title"
  :arrowIcon="pickerOption.tip.arrowIcon"
  :list="pickerOption.tip.list"
  :tip="pickerOption.tip.tip"
  :current="pickerOption.tip.current"
  @confirm="pickerOption.tip.confirm"
  @cancel="pickerOption.tip.cancel"
/>
export default {
  data() {
    return {
       pickerOption: {
        tip: {
          show: false,
          title: 'Ban位设置',
          tip: '创建比赛后,可按比赛轮次精确设置。',
          arrowIcon: false,
          list: bpList,
          current: { label: bpList[0].label, value: 1 },
          confirm: (boItem) => {
            this.pickerOption.tip.show = false;
          },
          cancel: () => {
            this.pickerOption.tip.show = false;
          },
        },
      },
    }
  },
  methods: {
    onShowPicker(type) {
      if (this.pickerOption[type]) {
        this.pickerOption[type].show = true;
      }
    },
    onConfirm(...args) {
      this.pickerOption[args[1]].show = false;
    },
    onChange(...args) {
      console.log('onChange.args', args);
    },
  }
},

# 函数式调用

支持函数式调用,需要在页面下预埋组件,并指定modefunctional

<press-picker
  :id="PRESS_PICKER_ID"
  mode="functional"
/>
export default {
  methods: {
     onShowFunctionalPicker() {
      const { bpList } = this;
      showFunctionalComponent.call(this, {
        selector: `#${PRESS_PICKER_ID}`,
        list: bpList,
        arrowIcon: true,
        current: { label: bpList[1].label, value: 3 },
        title: this.t('banSet'),
        tip: this.t('tipContent'),
      }).then((item) => {
        this.onSuccessTip(item);
      })
        .catch(() => {
          this.onTip('cancel');
        });
    },
  }
}

# 虚拟列表

对于数量大于virtual-list-threshold的列表,picker内部会使用虚拟列表。

实现原理是在picker-view上下各插入了一个占位Dom,并根据currentIndex计算它们的高度,同时将展示的数据减少。

<div
  :style="transformStyle"
>
  <div :style="hiddenUpPartStyle" />
  <div
    v-for="(item, index) in showingData"
    :key="index"
  >
    {{ item.label }}
  </div>
  <div :style="hiddenBottomPartStyle" />
</div>
export default {
  computed: {
    hiddenUpPartStyle() {
      const { currentIndex, itemHeight, virtualListThreshold } = this;
      return `height: ${(currentIndex - virtualListThreshold) * itemHeight}px;`;
    },
    hiddenBottomPartStyle() {
      const { currentIndex, data, itemHeight, virtualListThreshold } = this;
      return `height: ${(data.length - currentIndex - virtualListThreshold) * itemHeight}px;`;
    },
    showingData() {
      const { currentIndex, virtualListThreshold } = this;
      const upMissed = Math.max(0, currentIndex - virtualListThreshold);
      return this.data
        .slice(upMissed, currentIndex + virtualListThreshold).map((item, index) => ({
          ...item,
          uniqueKey: index + upMissed,
        }));
    },
    transformStyle() {
      const res = `transform: translate3d(0, ${this.currentScroll}px, 0);`;
      return res;
    },
  }
}

# API

# Props

参数 说明 类型 默认值
title 标题 string -
arrow-icon 左上角是否显示为返回箭头 boolean false
list 数据列表,每一项为对象,需包含labelvalue array []
current 当前选中项 object null
tip 提示 string -
mode 函数式调用时传functional string -
virtual-list-threshold 触发虚拟列表的最小数量 number 50

# Events

事件 说明 返回值
cancel 点击取消 -
confirm 点击确定 -

以下为废弃属性(v0.7.32):

类型
Prop show-back-arrow arrow-icon
Prop select-list list
Prop select-item current
Event onClickConfirm confirm
Event onRemove cancel

# 在线调试

# 常见问题

# 虚拟列表对比

下面是picker8000项时的对比,左图是未使用虚拟列表,右图是使用虚拟列表。

横屏