Browse Source

feat: picker

jerry 4 years ago
parent
commit
42824b9374

+ 1 - 0
src/sites/mobile-taro/vue/src/app.config.ts

@@ -1,5 +1,6 @@
 export default {
   pages: [
+    'pages/picker/demo',
     'pages/calendar/demo',
     'pages/input/demo',
     'pages/popup/demo',

+ 129 - 0
src/sites/mobile-taro/vue/src/pages/picker/demo.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="demo">
+    <h2>基础用法</h2>
+    <nut-picker :list-data="listData1" @confirm="confirm">
+      <nut-cell title="请选择城市" :desc="desc"></nut-cell>
+    </nut-picker>
+    <h2>多列样式</h2>
+    <nut-cell title="请选择时间" :desc="desc2"></nut-cell>
+    <h2>多级联动</h2>
+    <nut-cell title="请选择地址" :desc="desc3"></nut-cell>
+
+    <!-- <nut-picker
+      v-model:visible="show2"
+      :list-data="listData2"
+      title="多列选择"
+      @confirm="confirm2"
+      @close="close"
+    ></nut-picker>
+    <nut-picker
+      v-model:visible="show3"
+      :list-data="listData3"
+      title="地址选择"
+      @confirm="confirm3"
+    ></nut-picker> -->
+  </div>
+</template>
+<script lang="ts">
+import { toRefs, ref } from 'vue';
+import { createComponent } from './../../../../../../packages/utils/create';
+import Picker from './index.taro.vue';
+import Cell from './../cell/index.taro.vue';
+const { createDemo } = createComponent('picker');
+export default createDemo({
+  components: {
+    'nut-picker': Picker,
+    'nut-cell': Cell
+  },
+  props: {},
+  setup() {
+    const listData1 = [
+      '南京市',
+      '无锡市',
+      '海北藏族自治区',
+      '北京市',
+      '连云港市',
+      '浙江市',
+      '江苏市'
+    ];
+    const listData2 = [
+      {
+        values: ['周一', '周二', '周三', '周四', '周五'],
+        defaultIndex: 2
+      },
+      // 第二列
+      {
+        values: ['上午', '下午', '晚上'],
+        defaultIndex: 1
+      }
+    ];
+    const listData3 = [
+      {
+        text: '浙江',
+        children: [
+          {
+            text: '杭州',
+            children: [{ text: '西湖区' }, { text: '余杭区' }]
+          },
+          {
+            text: '温州',
+            children: [{ text: '鹿城区' }, { text: '瓯海区' }]
+          }
+        ]
+      },
+      {
+        text: '福建',
+        children: [
+          {
+            text: '福州',
+            children: [{ text: '鼓楼区' }, { text: '台江区' }]
+          },
+          {
+            text: '厦门',
+            children: [{ text: '思明区' }, { text: '海沧区' }]
+          }
+        ]
+      }
+    ];
+    const show = ref(false);
+    const show2 = ref(false);
+    const show3 = ref(false);
+    const showList = [show, show2, show3];
+    const desc = ref(listData1[0]);
+    const desc2 = ref(
+      `${listData2[0].values[listData2[0].defaultIndex]} ${
+        listData2[1].values[listData2[1].defaultIndex]
+      }`
+    );
+    const desc3 = ref(
+      `${listData3[0].text}
+      ${listData3[0].children[0].text}
+      ${listData3[0].children[0].children[0].text}`
+    );
+    const descList = [desc, desc2, desc3];
+    return {
+      listData1,
+      listData2,
+      listData3,
+      show,
+      show2,
+      show3,
+      desc,
+      desc2,
+      desc3,
+      open: (index: number) => {
+        showList[index - 1].value = true;
+      },
+      confirm: (res: any) => {
+        desc.value = res;
+      },
+      confirm2: (res: any) => {
+        desc2.value = res.join(' ');
+      },
+      confirm3: (res: any) => {
+        desc3.value = res.join(' ');
+      }
+    };
+  }
+});
+</script>

+ 14 - 251
src/sites/mobile-taro/vue/src/pages/picker/index.taro.vue

@@ -1,266 +1,29 @@
 <template>
-  <view-block :class="classes">
-    <nut-popup
-      position="bottom"
-      :style="{ height: height + 56 + 'px' }"
-      v-model:visible="show"
-      @close="close"
-    >
-      <view-block class="nut-picker__bar">
-        <view-block class="nut-picker__left nut-picker__button" @click="close"
-          >取消</view-block
-        >
-        <view-block> {{ title }}</view-block>
-        <view-block class="nut-picker__button" @click="confirm()"
-          >确定</view-block
-        >
-      </view-block>
-
-      <view-block class="nut-picker__column">
-        <view-block
-          class="nut-picker__mask"
-          :style="{ backgroundSize: `100% ${top}px` }"
-        ></view-block>
-        <view-block
-          class="nut-picker__hairline"
-          :style="{ top: ` ${top}px` }"
-        ></view-block>
-        <view-block
-          class="nut-picker__columnitem"
-          v-for="(item, columnIndex) in columnList"
-          :key="columnIndex"
-        >
-          <nut-picker-column
-            :listData="item.values"
-            :readonly="readonly"
-            :defaultIndex="item.defaultIndex"
-            :visibleItemCount="visibleItemCount"
-            :itemHeight="itemHeight"
-            :dataType="dataType"
-            @change="
-              dataIndex => {
-                changeHandler(columnIndex, dataIndex);
-              }
-            "
-          ></nut-picker-column>
-        </view-block>
-      </view-block>
-    </nut-popup>
-  </view-block>
+  <picker mode="selector" :range="listData" @change="onChange">
+    <slot></slot>
+  </picker>
 </template>
-<script lang="ts">
-import { reactive, watch, computed, toRaw, toRefs } from 'vue';
-import { createComponent } from '@/packages/utils/create';
-import column from './Column.vue';
-import popup from '@/packages/__VUE/popup/index.vue';
-import { commonProps } from './commonProps';
-import {
-  PickerObjOpt,
-  PickerOption,
-  PickerObjectColumn,
-  PickerObjectColumns
-} from './types';
-const { create, componentName } = createComponent('picker');
 
+<script lang="ts">
+const { create } = createComponent('picker');
+import { commonProps } from '../../../../../../packages/__VUE/picker/commonProps';
+import { createComponent } from './../../../../../../packages/utils/create';
 export default create({
-  components: {
-    [column.name]: column,
-    [popup.name]: popup
-  },
   props: {
-    visible: {
-      type: Boolean,
-      default: false
-    },
-    title: {
-      type: String,
-      default: ''
-    },
     ...commonProps
   },
-  emits: ['close', 'change', 'confirm', 'update:visible'],
+  emits: ['confirm'],
   setup(props, { emit }) {
-    const childrenKey = 'children';
-    const valuesKey = 'values';
-    const state = reactive({
-      show: false,
-      formattedColumns: props.listData as PickerObjectColumn[],
-      defaultIndex: props.defaultIndex as number
-    });
-    //临时变量,当点击确定时候赋值
-    let _defaultIndex = props.defaultIndex;
-    let defaultIndexList: number[] = [];
-
-    const classes = computed(() => {
-      const prefixCls = componentName;
-      return {
-        [prefixCls]: true
-      };
-    });
-
-    const top = computed(() => {
-      return (Number(+props.visibleItemCount - 1) / 2) * +props.itemHeight;
-    });
-
-    const height = computed(() => {
-      return Number(props.visibleItemCount) * +props.itemHeight;
-    });
-
-    const dataType = computed(() => {
-      const firstColumn = state.formattedColumns[0] as PickerObjectColumn;
-      if (typeof firstColumn === 'object') {
-        if (firstColumn[childrenKey]) {
-          return 'cascade';
-        } else if (firstColumn?.[valuesKey]) {
-          addDefaultIndexList(props.listData as PickerObjectColumn[]);
-          return 'multipleColumns';
-        }
-      }
-      return 'text';
-    });
-
-    const columnList = computed(() => {
-      if (dataType.value === 'text') {
-        return [
-          { values: state.formattedColumns, defaultIndex: state.defaultIndex }
-        ];
-      } else if (dataType.value === 'multipleColumns') {
-        return state.formattedColumns;
-      } else if (dataType.value === 'cascade') {
-        return formatCascade(
-          state.formattedColumns as PickerObjectColumn[],
-          state.defaultIndex
-        );
-      }
-      return state.formattedColumns;
-    });
-
-    const addDefaultIndexList = (listData: PickerObjectColumn[]) => {
-      defaultIndexList = [];
-      listData.forEach(res => {
-        defaultIndexList.push((res.defaultIndex as number) || 0);
-      });
+    const onChange = (e: any) => {
+      emit('confirm', props.listData[e.detail.value]);
     };
 
-    const formatCascade = (
-      listData: PickerObjectColumn[],
-      defaultIndex: number
-    ) => {
-      const formatted: PickerObjectColumn[] = [];
-      let children = listData as PickerObjectColumns;
-      children.defaultIndex = defaultIndex;
-      while (children) {
-        formatted.push({
-          values: children,
-          defaultIndex: children.defaultIndex || 0
-        });
-        children = children?.[children.defaultIndex || 0].children;
-      }
-      addDefaultIndexList(formatted);
-      return formatted;
-    };
-
-    const getCascadeData = (
-      listData: PickerObjectColumn[],
-      defaultIndex: number
-    ) => {
-      let arr = listData as PickerObjectColumns;
-      arr.defaultIndex = defaultIndex;
-      const dataList: string[] = [];
-
-      while (arr) {
-        const item = arr[arr.defaultIndex ?? 0];
-        dataList.push(item.text as string);
-        arr = item.children;
-      }
-      return dataList;
-    };
-
-    const close = () => {
-      emit('close');
-      emit('update:visible', false);
-    };
-
-    const changeHandler = (columnIndex: number, dataIndex: number) => {
-      if (dataType.value === 'cascade') {
-        let cursor = state.formattedColumns as PickerObjectColumns;
-        if (columnIndex === 0) {
-          state.defaultIndex = dataIndex;
-        }
-        let i = 0;
-        while (cursor) {
-          if (i === columnIndex) {
-            cursor.defaultIndex = dataIndex;
-          } else if (i > columnIndex) {
-            cursor.defaultIndex = 0;
-          }
-          cursor = cursor[cursor.defaultIndex || 0].children;
-          i++;
-        }
-      } else if (dataType.value === 'text') {
-        _defaultIndex = dataIndex;
-      } else if (dataType.value === 'multipleColumns') {
-        defaultIndexList[columnIndex] = dataIndex;
-        const val = defaultIndexList.map(
-          (res, i) =>
-            toRaw(state.formattedColumns as PickerObjectColumns)[i].values[res]
-        );
-        emit('change', val);
-      }
-    };
-
-    const confirm = () => {
-      if (dataType.value === 'text') {
-        state.defaultIndex = _defaultIndex as number;
-        emit('confirm', state.formattedColumns[_defaultIndex as number]);
-      } else if (dataType.value === 'multipleColumns') {
-        for (let i = 0; i < defaultIndexList.length; i++) {
-          state.formattedColumns[i].defaultIndex = defaultIndexList[i];
-        }
-        const checkedArr = toRaw(state.formattedColumns).map(
-          (res: PickerObjectColumn) =>
-            res.values && res.values[res.defaultIndex as number]
-        );
-        emit('confirm', checkedArr);
-      } else if (dataType.value === 'cascade') {
-        emit(
-          'confirm',
-          getCascadeData(toRaw(state.formattedColumns), state.defaultIndex)
-        );
-      }
-
-      emit('update:visible', false);
-    };
-
-    watch(
-      () => props.visible,
-      val => {
-        state.show = val;
-      }
-    );
-
-    watch(
-      () => props.listData,
-      val => {
-        state.formattedColumns = val as PickerObjectColumns;
-      }
-    );
-
     return {
-      classes,
-      ...toRefs(state),
-      column,
-      dataType,
-      columnList,
-      top,
-      height,
-      close,
-      changeHandler,
-      confirm
+      confirm,
+      onChange
     };
   }
 });
 </script>
-<style lang="scss">
-@import 'index.scss';
-</style>
+
+<style lang="scss" scoped></style>