选择器

选择器是一个强大的组件,它允许您创建自定义覆盖选择器,它们看起来像 iOS 原生选择器。

选择器可以用作内联组件或作为覆盖层。平板电脑(iPad)上的覆盖选择器将自动转换为弹出提示。

选择器应用方法

让我们看看相关的应用方法来使用选择器

app.picker.create(parameters) - 创建选择器实例

  • parameters - object。带有选择器参数的对象

方法返回创建的选择器实例

app.picker.destroy(el) - 销毁选择器实例

  • el - HTMLElementstring(带 CSS 选择器)或 object。选择器元素或待销毁的选择器实例。

app.picker.get(el) - 根据 HTML 元素获取选择器实例

  • el - HTMLElementstring(带 CSS 选择器)。选择器元素。

方法返回选择器的实例

app.picker.close(el) - 关闭选择器

  • el - HTMLElementstring(带 CSS 选择器)。待关闭的选择器元素。

方法返回选择器的实例

示例

var picker = app.picker.create({
  inputEl: '#picker-input',
  cols: [
     {
       values: ['apple', 'orange', 'banana'],
       displayValues: ['Apple', 'Orange', 'Banana'],
     }
   ]
});

选择器参数

我们来看一下所有可用的选择器参数列表

参数类型默认值说明
rotateEffectbooleanfalse启用 3D 旋转效果
freeModebooleanfalse禁用值捕捉
valuearray带有初始值的数组。数组的每个条目都表示相关列的值
formatValuefunction (values, displayValues)格式化输入值的函数,应当返回新的/格式化的字符串值。valuesdisplayValues 是数组,其中每个条目都表示相关列的值/显示值
colsarray带有列的数组。数组的每个条目都表示带列参数的对象
容器/开启程序特定参数
containerElstring
HTMLElement
带有 CSS 选择器或 HTMLElement 的字符串,用于放置生成的 HTML Picker。仅用于内联选择器
openInstringauto可以为 autopopover(以浮动层形式开启选择器)、sheet(以模态面板形式开启)。如果是 auto,则会在小屏幕上以模态面板形式开启,在大屏幕上以浮动层形式开启。
backdropboolean为选择器容器(浮动层或面板)(后面的深色半透明图层)启用幕布。默认情况下,它根据开启方式(面板或浮动层)使用默认值。
sheetPushbooleanfalse开启后,选择器面板可以在开启时将后面的视图推送
sheetSwipeToClosebooleanfalse启用通过滑动关闭选择器面板的功能
inputElstring 或 HTMLElement带有 CSS 选择器或 HTMLElement 的字符串,用于相关输入元素
scrollToInputbooleantrue当选择器开启时,滚动视口(页面内容)至输入
inputReadOnlybooleantrue对指定的输入设置“readonly”属性
cssClassstring其他 CSS 类名称,用于设置选择器元素
closeByOutsideClickbooleantrue启用后,单击选择器或相关输入元素外部将会关闭选择器
工具栏booleantrue启用选择器工具栏
toolbarCloseTextstring完成完成/关闭工具栏按钮文本
routableModalsbooleanfalse将打开的选择器添加到路由器历史记录,这使你可以通过返回路由器历史记录并设置当前路由到选择器模态来关闭选择器
urlstringselect/将被设置为当前路由的选择器模态 URL
viewobject启用routableModals时的设置路由的视图。默认为inputEl的父视图,如果未找到父视图则默认为主视图
渲染函数
renderToolbarfunction渲染工具栏的函数。必须返回工具栏 HTML 字符串
renderfunction渲染整个选择器的函数。必须返回选择器完整的 HTML 字符串
事件
onobject

带有事件处理程序的对象。例如

var picker = app.picker.create({
  ...
  on: {
    opened: function () {
      console.log('Picker opened')
    }
  }
})

请注意,在picker属性下的全局应用参数中可以使用以下所有参数来设置所有选择器的默认值。例如

var app = new Framework7({
  picker: {
    rotateEffect: true,
    openIn: 'popover',
  }
});

列参数

当我们配置选择器时,我们需要传递cols参数。它是一个数组,其中每个项目都是一个带有列参数的对象

参数类型默认值说明
valuesarray带有字符串列值的数组
displayValuesarray带有将在选择器中显示的字符串列值的数组。如果未指定,它将显示参数中的值
cssClassstring在列 HTML 容器上设置的附加 CSS 类名
textAlignstring列值的文本对齐方式,可以是“左”、“中”或“右”
widthnumber列宽(以像素为单位)。如果你需要在具有相关列的选择器中修复列宽,这很有用。默认情况下,自动计算
dividerbooleanfalse定义应作为视觉分隔符的列,它没有任何值
contentstring应为分隔线列(divider:true)指定,其中包含列的内容
onChangefunction(picker, value, displayValue)选择器值更改时执行的回调函数。

选择器方法和属性

在初始化选择器后,我们将在变量(如上例中的picker变量)中拥有其已初始化的实例,并带有有用的方法和属性

属性
picker.app指向全局应用实例的链接
picker.containerEl选择器包装容器 HTML 元素(当使用内联选择器时)
picker.$containerEl带有选择器包装容器 HTML 元素的 Dom7 实例(当使用内联选择器时)
picker.el选择器 HTML 元素
picker.$el带有选择器 HTML 元素的 Dom7 实例
picker.inputEl选择器输入 HTML 元素(在inputEl参数中传递)
picker.$inputEl带有选择器输入 HTML 元素的 Dom7 实例(在inputEl参数中传递)
picker.value每个项目都表示每列当前所选值的数组
picker.cols使用指定选取器列的数组。每列还具有自己的方法和属性(请参见下文)
picker.openedPicker 当前处于打开状态时为 true
picker.inline使用内嵌选取器时为 true
picker.url选取器 URL(在 url 参数中传递)
picker.view选取器视图(在 view 参数中传递)或发现父视图
picker.params包含初始化参数的对象
方法
picker.setValue(values)设置新的选取器值。values 是数组,其中每个项表示每列的值。
picker.getValue()返回当前选取器值
picker.open()打开选取器
picker.close()关闭选取器
picker.destroy()销毁选取器实例并删除所有事件
picker.on(event, handler)添加事件处理程序
picker.once(event, handler)添加事件处理程序,在事件触发后将被删除
picker.off(event, handler)移除事件处理程序
picker.off(event)移除指定事件的所有处理程序
picker.emit(event, ...args)在实例上触发事件

列方法和属性

picker.cols 数组中的每列还有自己的有用的方法和属性。

//Get first column
var col = picker.cols[0];
属性
col.el列 HTML 元素
col.$el带有列 HTML 容器的 Dom7 实例
col.items带有列项目 HTML 元素的 Dom7 实例
col.value当前选中的列值
col.displayValue当前选中的列显示值
col.activeIndex当前选定/活动项的索引号
方法
col.setValue(value)为当前列设置新值。value 是新值。
col.replaceValues(values, displayValues)用新值替换列值和显示值

选取器事件

选取器将在选取器元素上触发以下 DOM 事件,并在应用程序和选取器实例上触发事件

DOM 事件

事件目标说明
picker:open选取器元素<div class="picker">当选取器开始其打开动画时触发事件
picker:opened选取器元素<div class="picker">当选取器完成其打开动画后触发事件
picker:close选取器元素<div class="picker">当选取器开始其关闭动画时触发事件
picker:closed选取器元素<div class="picker">当选取器完成其关闭动画后触发事件

应用程序和选取器实例事件

选取器实例在自身实例和应用程序实例上触发事件。应用程序实例事件具有相同名称,前缀为 picker

事件目标参数说明
changepicker(picker, value, displayValue)当选取器值发生变化时触发事件
pickerChangeapp
initpicker(picker)当选取器初始化时触发事件
pickerInitapp
openpicker(picker)拾取器开始其启动动画时,将触发事件。作为参数,事件处理程序会接收拾取器实例
pickerOpenapp
openedpicker(picker)拾取器完成启动动画后,将触发事件。作为参数,事件处理程序会接收拾取器实例
pickerOpenedapp
closepicker(picker)拾取器开始其关闭动画时,将触发事件。作为参数,事件处理程序会接收拾取器实例
pickerCloseapp
closedpicker(picker)拾取器完成其关闭动画后,将触发事件。作为参数,事件处理程序会接收拾取器实例
pickerClosedapp
beforeDestroypicker(picker)拾取器实例将被摧毁之前,将触发事件。作为参数,事件处理程序会接收拾取器实例
pickerBeforeDestroyapp

CSS 变量

以下列出了其相关 CSS 变量(CSS 自定义属性)。

请注意,带上注释的变量未在默认情况下被指定,它们的值在此在这种情况下它们会回退到什么。

:root {
  --f7-picker-height: 260px;
  --f7-picker-inline-height: 200px;
  --f7-picker-popover-height: 260px;
  --f7-picker-popover-width: 280px;
  --f7-picker-landscape-height: 200px;
  --f7-picker-item-height: 36px;
  /*
  --f7-picker-sheet-bg-color: var(--f7-sheet-bg-color);
  */
}
.ios {
  --f7-picker-column-font-size: 20px;
  --f7-picker-item-selected-text-color: #000;
  --f7-picker-item-selected-bg-color: rgba(0, 0, 0, 0.12);
  --f7-picker-divider-text-color: #000;
  --f7-picker-item-text-color: rgba(0, 0, 0, 0.45);
}
.ios .dark,
.ios.dark {
  --f7-picker-item-selected-text-color: #fff;
  --f7-picker-item-selected-bg-color: rgba(255, 255, 255, 0.1);
  --f7-picker-divider-text-color: #fff;
  --f7-picker-item-text-color: rgba(255, 255, 255, 0.55);
}
.md {
  --f7-picker-column-font-size: 20px;
}
.md,
.md .dark,
.md [class*='color-'] {
  --f7-picker-item-selected-text-color: var(--f7-md-on-surface);
  --f7-picker-item-text-color: var(--f7-md-on-surface-variant);
  --f7-picker-divider-text-color: var(--f7-md-on-surface);
  --f7-picker-item-selected-border-color: var(--f7-md-outline);
}

示例

picker.html
<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="title">Picker</div>
      </div>
    </div>
    <div class="page-content">
      <div class="block">
        <p>Picker is a powerful component that allows you to create custom overlay pickers which looks like native
          picker.</p>
        <p>Picker could be used as inline component or as overlay. Overlay Picker will be automatically converted to
          Popover on tablets (iPad).</p>
      </div>
      <div class="block-title">Picker with single value</div>
      <div class="list list-strong-ios list-outline-ios">
        <ul>
          <li>
            <div class="item-content item-input">
              <div class="item-inner">
                <div class="item-input-wrap">
                  <input type="text" placeholder="Your iOS device" readonly="readonly" id="demo-picker-device" />
                </div>
              </div>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title">2 values and 3d-rotate effect</div>
      <div class="list list-strong-ios list-outline-ios">
        <ul>
          <li>
            <div class="item-content item-input">
              <div class="item-inner">
                <div class="item-input-wrap">
                  <input type="text" placeholder="Describe yourself" readonly="readonly" id="demo-picker-describe" />
                </div>
              </div>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title">Dependent values</div>
      <div class="list list-strong-ios list-outline-ios">
        <ul>
          <li>
            <div class="item-content item-input">
              <div class="item-inner">
                <div class="item-input-wrap">
                  <input type="text" placeholder="Your car" readonly="readonly" id="demo-picker-dependent" />
                </div>
              </div>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title">Custom toolbar</div>
      <div class="list list-strong-ios list-outline-ios">
        <ul>
          <li>
            <div class="item-content item-input">
              <div class="item-inner">
                <div class="item-input-wrap">
                  <input type="text" placeholder="Describe yourself" readonly="readonly"
                    id="demo-picker-custom-toolbar" />
                </div>
              </div>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title">Inline Picker / Date-time</div>
      <div class="list no-margin">
        <ul>
          <li>
            <div class="item-content item-input">
              <div class="item-inner">
                <div class="item-input-wrap">
                  <input type="text" placeholder="Date Time" readonly="readonly" id="demo-picker-date" />
                </div>
              </div>
            </div>
          </li>
        </ul>
      </div>
      <div class="block block-strong block-outline-ios inset-md no-padding no-margin-top">
        <div id="demo-picker-date-container"></div>
      </div>
    </div>
  </div>
</template>
<script>
  export default (props, { $f7, $on }) => {
    let pickerDevice;
    let pickerDescribe;
    let pickerDependent;
    let pickerCustomToolbar;

    $on('pageInit', () => {
      // iOS Device picker
      pickerDevice = $f7.picker.create({
        inputEl: '#demo-picker-device',
        cols: [
          {
            textAlign: 'center',
            values: ['iPhone 4', 'iPhone 4S', 'iPhone 5', 'iPhone 5S', 'iPhone 6', 'iPhone 6 Plus', 'iPad 2', 'iPad Retina', 'iPad Air', 'iPad mini', 'iPad mini 2', 'iPad mini 3']
          }
        ]
      });

      // Describe yourself picker
      pickerDescribe = $f7.picker.create({
        inputEl: '#demo-picker-describe',
        rotateEffect: true,
        cols: [
          {
            textAlign: 'left',
            values: ('Super Amazing Bat Iron Rocket Lex Beautiful Wonderful Raining Happy Funny Cool Hot').split(' ')
          },
          {
            values: ('Man Luthor Woman Boy Girl Person Cutie Babe Raccoon').split(' ')
          },
        ]
      });

      // Dependent values
      var carVendors = {
        Japanese: ['Honda', 'Lexus', 'Mazda', 'Nissan', 'Toyota'],
        German: ['Audi', 'BMW', 'Mercedes', 'Volkswagen', 'Volvo'],
        American: ['Cadillac', 'Chrysler', 'Dodge', 'Ford']
      };
      pickerDependent = $f7.picker.create({
        inputEl: '#demo-picker-dependent',
        rotateEffect: true,
        formatValue: function (values) {
          return values[1];
        },
        cols: [
          {
            textAlign: 'left',
            values: ['Japanese', 'German', 'American'],
            onChange: function (picker, country) {
              if (picker.cols[1].replaceValues) {
                picker.cols[1].replaceValues(carVendors[country]);
              }
            }
          },
          {
            values: carVendors.Japanese,
            width: 160,
          },
        ]
      });

      // Custom Toolbar
      pickerCustomToolbar = $f7.picker.create({
        inputEl: '#demo-picker-custom-toolbar',
        rotateEffect: true,
        renderToolbar: function () {
          return '<div class="toolbar">' +
            '<div class="toolbar-inner">' +
            '<div class="left">' +
            '<a  class="link toolbar-randomize-link">Randomize</a>' +
            '</div>' +
            '<div class="right">' +
            '<a  class="link sheet-close popover-close">That\'s me</a>' +
            '</div>' +
            '</div>' +
            '</div>';
        },
        cols: [
          {
            values: ['Mr', 'Ms'],
          },
          {
            textAlign: 'left',
            values: ('Super Amazing Bat Iron Rocket Lex Beautiful Wonderful Raining Happy Funny Cool Hot').split(' ')
          },
          {
            values: ('Man Luthor Woman Boy Girl Person Cutie Babe Raccoon').split(' ')
          },
        ],
        on: {
          open: function (picker) {
            picker.$el.find('.toolbar-randomize-link').on('click', function () {
              var col0Values = picker.cols[0].values;
              var col0Random = col0Values[Math.floor(Math.random() * col0Values.length)];

              var col1Values = picker.cols[1].values;
              var col1Random = col1Values[Math.floor(Math.random() * col1Values.length)];

              var col2Values = picker.cols[2].values;
              var col2Random = col2Values[Math.floor(Math.random() * col2Values.length)];

              picker.setValue([col0Random, col1Random, col2Random]);
            });
          },
        }
      });
      // Inline date-time
      const today = new Date();
      pickerInline = $f7.picker.create({
        containerEl: '#demo-picker-date-container',
        inputEl: '#demo-picker-date',
        toolbar: false,
        rotateEffect: true,
        value: [
          today.getMonth(),
          today.getDate(),
          today.getFullYear(),
          today.getHours(),
          today.getMinutes() < 10 ? '0' + today.getMinutes() : today.getMinutes()
        ],
        formatValue: function (values, displayValues) {
          return displayValues[0] + ' ' + values[1] + ', ' + values[2] + ' ' + values[3] + ':' + values[4];
        },
        cols: [
          // Months
          {
            values: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
            displayValues: ('January February March April May June July August September October November December').split(' '),
            textAlign: 'left'
          },
          // Days
          {
            values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31],
          },
          // Years
          {
            values: (function () {
              var arr = [];
              for (var i = 1950; i <= 2030; i++) { arr.push(i); }
              return arr;
            })(),
          },
          // Space divider
          {
            divider: true,
            content: '&nbsp;&nbsp;'
          },
          // Hours
          {
            values: (function () {
              var arr = [];
              for (var i = 0; i <= 23; i++) { arr.push(i); }
              return arr;
            })(),
          },
          // Divider
          {
            divider: true,
            content: ':'
          },
          // Minutes
          {
            values: (function () {
              var arr = [];
              for (var i = 0; i <= 59; i++) { arr.push(i < 10 ? '0' + i : i); }
              return arr;
            })(),
          }
        ],
        on: {
          change: function (picker, values, displayValues) {
            var daysInMonth = new Date(picker.value[2], picker.value[0] * 1 + 1, 0).getDate();
            if (values[1] > daysInMonth) {
              picker.cols[1].setValue(daysInMonth);
            }
          },
        }
      });
    });
    $on('pageBeforeRemove', () => {
      pickerDevice.destroy();
      pickerDescribe.destroy();
      pickerDependent.destroy();
      pickerCustomToolbar.destroy();
    });

    return $render;
  };

</script>