浏览代码

feat: picker组件去掉内置popup

yangxiaolu3 3 年之前
父节点
当前提交
dd702320d2

+ 1 - 9
src/packages/__VUE/picker/Column.vue

@@ -43,18 +43,10 @@ export default create({
     // 当前选中项
     value: [String, Number],
     columnsType: String,
-    itemShow: {
-      type: Boolean,
-      default: false
-    },
     column: {
       type: Array as PropType<PickerOption[]>,
       default: () => []
     },
-    readonly: {
-      type: Boolean,
-      default: false
-    },
     // 是否开启3D效果
     threeDimensional: {
       type: Boolean,
@@ -168,7 +160,7 @@ export default create({
       setMove(move);
     };
 
-    const onTouchEnd = (event: TouchEvent) => {
+    const onTouchEnd = () => {
       state.touchParams.lastY = touch.deltaY.value;
       state.touchParams.lastTime = Date.now();
       let move = state.touchParams.lastY - state.touchParams.startY;

+ 46 - 0
src/packages/__VUE/picker/baseProps.ts

@@ -0,0 +1,46 @@
+import { PropType } from 'vue';
+import { PickerOption } from './types';
+export default {
+  modelValue: {
+    type: Array as PropType<(string | number)[]>,
+    default: () => []
+  },
+  title: {
+    type: String,
+    default: ''
+  },
+  cancelText: {
+    type: String,
+    default: ''
+  },
+  okText: {
+    type: String,
+    default: ''
+  },
+  columns: {
+    type: Array as PropType<(PickerOption | PickerOption[])[]>,
+    default: () => {
+      return [];
+    }
+  },
+  threeDimensional: {
+    type: Boolean,
+    default: true
+  },
+  swipeDuration: {
+    type: [Number, String],
+    default: 1000
+  },
+  showToolbar: {
+    type: Boolean,
+    default: true
+  },
+  visibleOptionNum: {
+    type: [Number, String],
+    default: 7
+  },
+  optionHeight: {
+    type: [Number, String],
+    default: 36
+  }
+};

+ 40 - 152
src/packages/__VUE/picker/common.ts

@@ -1,67 +1,22 @@
-import { ref, onMounted, onBeforeUnmount, reactive, watch, computed, toRaw, toRefs, PropType } from 'vue';
+import { ref, onMounted, onBeforeUnmount, reactive, watch, computed, CSSProperties, toRefs, PropType } from 'vue';
 import { createComponent } from '@/packages/utils/create';
-const { componentName, create, translate } = createComponent('picker');
+const { translate } = createComponent('picker');
 import { usePicker } from './usePicker';
-import { popupProps } from '../popup/props';
 import column from './Column.vue';
-import Taro from '@tarojs/taro';
-
-export interface PickerOption {
-  text: string | number;
-  value: string | number;
-  disabled?: string;
-  children?: PickerOption[];
-  className?: string | number;
-}
+import Taro, { nextTick } from '@tarojs/taro';
+import baseProps from './baseProps';
 
 export const componentWeb = {
   components: {
     [column.name]: column
   },
-  props: {
-    ...popupProps,
-    modelValue: {
-      type: Array as PropType<(string | number)[]>,
-      default: () => []
-    },
-    title: {
-      type: String,
-      default: ''
-    },
-    cancelText: {
-      type: String,
-      default: ''
-    },
-    okText: {
-      type: String,
-      default: ''
-    },
-    columns: {
-      type: Array as PropType<(PickerOption | PickerOption[])[]>,
-      default: () => {
-        return [];
-      }
-    },
-    readonly: {
-      type: Boolean,
-      default: false
-    },
-    threeDimensional: {
-      type: Boolean,
-      default: true
-    },
-    swipeDuration: {
-      type: [Number, String],
-      default: 1000
-    }
-  },
-  emits: ['close', 'change', 'confirm', 'update:visible', 'update:modelValue'],
+  props: baseProps,
+  emits: ['cancel', 'change', 'confirm', 'update:modelValue'],
   setup(props: any, { emit }: any) {
-    const { changeHandler, confirm, defaultValues, columnsList, selectedOptions, columnsType, classes, close } =
+    const { changeHandler, confirm, defaultValues, columnsList, selectedOptions, columnsType, classes, cancel } =
       usePicker(props, emit);
 
     const state = reactive({
-      show: false,
       ENV: Taro.getEnv(),
       ENV_TYPE: Taro.ENV_TYPE
     });
@@ -83,37 +38,27 @@ export const componentWeb = {
       confirm();
     };
 
-    onMounted(() => {
-      if (props.visible) state.show = props.visible;
+    const columnStyle = computed(() => {
+      const styles: CSSProperties = {};
+      styles.height = `${+props.visibleOptionNum * +props.optionHeight}px`;
+      styles['--lineHeight'] = `${+props.optionHeight}px`;
+      return styles;
     });
 
-    onBeforeUnmount(() => {
-      if (props.visible) state.show = false;
-    });
-
-    watch(
-      () => props.visible,
-      (val) => {
-        state.show = val;
-        if (val) {
-          pickerColumn.value = [];
-        }
-      }
-    );
-
     return {
       classes,
       ...toRefs(state),
       column,
       columnsType,
       columnsList,
-      close,
+      cancel,
       changeHandler,
       confirmHandler,
       defaultValues,
       pickerColumn,
       swipeRef,
-      translate
+      translate,
+      columnStyle
     };
   }
 };
@@ -122,58 +67,13 @@ export const componentWeapp = {
   components: {
     [column.name]: column
   },
-  props: {
-    ...popupProps,
-    modelValue: {
-      type: Array as PropType<(string | number)[]>,
-      default: []
-    },
-    title: {
-      type: String,
-      default: ''
-    },
-    cancelText: {
-      type: String,
-      default: ''
-    },
-    okText: {
-      type: String,
-      default: ''
-    },
-    columns: {
-      type: Array,
-      default: () => {
-        return [];
-      }
-    },
-    readonly: {
-      type: Boolean,
-      default: false
-    },
-    // 是否开启3D效果
-    threeDimensional: {
-      type: Boolean,
-      default: true
-    },
-    // 惯性滚动 时长
-    swipeDuration: {
-      type: [Number, String],
-      default: 1000
-    }
-  },
-  emits: ['close', 'change', 'confirm', 'update:visible', 'update:modelValue'],
+  props: baseProps,
+  emits: ['cancel', 'change', 'confirm', 'update:modelValue'],
   setup(props: any, { emit }: any) {
-    const {
-      changeHandler,
-      confirm,
-      defaultValues,
-      columnsList,
-      selectedOptions,
-      isSameValue,
-      columnsType,
-      classes,
-      close
-    } = usePicker(props, emit);
+    const { changeHandler, confirm, defaultValues, columnsList, isSameValue, columnsType, classes, cancel } = usePicker(
+      props,
+      emit
+    );
     const state = reactive({
       show: false,
       picking: false,
@@ -184,6 +84,13 @@ export const componentWeapp = {
     // 选中项的位置  taro
     let defaultIndexes = ref<number[]>([]);
 
+    const pickerViewStyles = computed(() => {
+      const styles: CSSProperties = {};
+      styles.height = `${+props.visibleOptionNum * +props.optionHeight}px`;
+      styles['--lineHeight'] = `${+props.optionHeight}px`;
+      return styles;
+    });
+
     const defaultValuesConvert = () => {
       let defaultIndexs: number[] = [];
       if (defaultValues.value.length > 0) {
@@ -214,29 +121,22 @@ export const componentWeapp = {
         if (prevDefaultValue[index] != col) changeIndex = index;
       });
 
-      if (state.show) {
-        defaultIndexes.value = data.detail.value;
-        // 选择的是哪个 option
-        changeHandler(changeIndex, columnsList.value[changeIndex][data.detail.value[changeIndex]]);
-      }
+      defaultIndexes.value = data.detail.value;
+      // 选择的是哪个 option
+      changeHandler(changeIndex, columnsList.value[changeIndex][data.detail.value[changeIndex]]);
     };
 
     // 确定
     const confirmHandler = () => {
       if (state.picking) {
         setTimeout(() => {
-          confirmHandlerAwit();
+          confirm();
         }, 0);
       } else {
-        confirmHandlerAwit();
+        confirm();
       }
     };
 
-    const confirmHandlerAwit = () => {
-      confirm();
-      state.show = false;
-    };
-
     // 开始滚动
     const handlePickstart = () => {
       state.picking = true;
@@ -247,43 +147,30 @@ export const componentWeapp = {
     };
 
     onMounted(() => {
-      if (props.visible) {
+      if (defaultValues.value.length > 0) {
         defaultIndexes.value = defaultValuesConvert();
-        state.show = props.visible;
       }
     });
 
-    onBeforeUnmount(() => {
-      if (props.visible) state.show = false;
-    });
-
     watch(
       () => props.modelValue,
       (newValues) => {
         if (!isSameValue(newValues, defaultValues.value)) {
-          defaultIndexes.value = defaultValuesConvert();
+          setTimeout(() => {
+            defaultIndexes.value = defaultValuesConvert();
+          }, 100);
         }
       },
       { deep: true }
     );
 
-    watch(
-      () => props.visible,
-      (val) => {
-        state.show = val;
-        if (val) {
-          defaultIndexes.value = defaultValuesConvert();
-        }
-      }
-    );
-
     return {
       classes,
       ...toRefs(state),
       column,
       columnsType,
       columnsList,
-      close,
+      cancel,
       changeHandler,
       confirmHandler,
       defaultValues,
@@ -291,7 +178,8 @@ export const componentWeapp = {
       tileChange,
       handlePickstart,
       translate,
-      handlePickend
+      handlePickend,
+      pickerViewStyles
     };
   }
 };

+ 17 - 26
src/packages/__VUE/picker/demo.vue

@@ -1,27 +1,24 @@
 <template>
   <div class="demo">
     <h2>{{ translate('basic') }}</h2>
-    <nut-picker
-      :columns="columns"
-      :title="translate('chooseCity')"
-      @confirm="(options) => confirm('index', options)"
-    ></nut-picker>
+    <nut-picker :columns="columns" :title="translate('chooseCity')" @confirm="confirm"></nut-picker>
 
     <h2>{{ translate('popupDesc') }}</h2>
     <nut-cell :title="translate('chooseCity')" :desc="popupDesc" @click="show = true"></nut-cell>
     <nut-popup position="bottom" v-model:visible="show">
-      <nut-picker :columns="columns" :title="translate('chooseCity')" @confirm="popupConfirm" @cancel="show = false">
+      <nut-picker
+        v-model="popupValue"
+        :columns="columns"
+        :title="translate('chooseCity')"
+        @confirm="popupConfirm"
+        @cancel="show = false"
+      >
         <nut-button block type="primary">{{ translate('always') }}</nut-button>
       </nut-picker>
     </nut-popup>
 
     <h2>{{ translate('defaultSelected') }}</h2>
-    <nut-picker
-      v-model="selectedValue"
-      :columns="columns"
-      :title="translate('chooseCity')"
-      @confirm="(options) => confirm('defult', options)"
-    >
+    <nut-picker v-model="selectedValue" :columns="columns" :title="translate('chooseCity')" @confirm="confirm">
     </nut-picker>
 
     <h2>{{ translate('tileDesc') }}</h2>
@@ -30,17 +27,12 @@
       :columns="columns"
       :title="translate('chooseCity')"
       :threeDimensional="false"
-      @confirm="(options) => confirm('tile', options)"
+      @confirm="confirm"
     >
     </nut-picker>
 
     <h2>{{ translate('multipleColumns') }}</h2>
-    <nut-picker
-      v-model="selectedTime"
-      :columns="multipleColumns"
-      :title="translate('chooseTime')"
-      @confirm="(options) => confirm('multiple', options)"
-    >
+    <nut-picker v-model="selectedTime" :columns="multipleColumns" :title="translate('chooseTime')" @confirm="confirm">
     </nut-picker>
 
     <h2>{{ translate('cascade') }}</h2>
@@ -48,7 +40,7 @@
       v-model="selectedCascader"
       :columns="cascaderColumns"
       :title="translate('chooseCity')"
-      @confirm="(options) => confirm('cascader', options)"
+      @confirm="confirm"
     ></nut-picker>
 
     <h2>{{ translate('async') }}</h2>
@@ -56,7 +48,7 @@
       v-model="asyncValue"
       :columns="asyncColumns"
       :title="translate('chooseCity')"
-      @confirm="(options) => confirm('async', options)"
+      @confirm="confirm"
     ></nut-picker>
   </div>
 </template>
@@ -78,6 +70,7 @@ export default createDemo({
     const selectedTime = ref(['Wednesday', 'Afternoon']);
     const selectedCascader = ref(['FuJian', 'FuZhou', 'TaiJiang']);
     const asyncValue = ref<string[]>([]);
+    const popupValue = ref();
     const columns = computed(() => [
       { text: translate('nanJing'), value: 'NanJing' },
       { text: translate('wuXi'), value: 'WuXi' },
@@ -184,10 +177,7 @@ export default createDemo({
       }, 500);
     });
 
-    const confirm = (
-      tag: string,
-      { selectedValue, selectedOptions }: { selectedValue: string[]; selectedOptions: any }
-    ) => {
+    const confirm = ({ selectedValue, selectedOptions }: { selectedValue: string[]; selectedOptions: any }) => {
       Toast.text(selectedOptions.map((val: any) => val.text).join(','));
     };
 
@@ -211,7 +201,8 @@ export default createDemo({
       selectedCascader,
       selectedTileValue,
       popupConfirm,
-      popupDesc
+      popupDesc,
+      popupValue
     };
   }
 });

+ 51 - 63
src/packages/__VUE/picker/index.taro.vue

@@ -1,71 +1,59 @@
 <template>
   <view :class="classes">
-    <nut-popup
-      position="bottom"
-      v-model:visible="show"
-      :teleport="teleport"
-      :lock-scroll="lockScroll"
-      :close-on-click-overlay="closeOnClickOverlay"
-      @close="close"
-      :round="true"
-      :safeAreaInsetBottom="safeAreaInsetBottom"
-      :destroyOnClose="destroyOnClose"
-    >
-      <view class="nut-picker__bar">
-        <view class="nut-picker__cancel nut-picker__left nut-picker__button" @click="close">{{
-          cancelText || translate('cancel')
-        }}</view>
-        <view class="nut-picker__title"> {{ title }}</view>
-        <view class="nut-picker__confirm nut-picker__right nut-picker__button" @click="confirmHandler()">{{
-          okText || translate('confirm')
-        }}</view>
-      </view>
-      <slot name="top"></slot>
-
-      <!-- Taro 下转换成 微信小程序 -->
-      <picker-view
-        v-if="ENV != ENV_TYPE.WEB"
-        indicator-style="height: 34px;"
-        :value="defaultIndexes"
-        style="width: 100%; height: 252px"
-        :immediate-change="true"
-        @change="tileChange"
-        @pickstart="handlePickstart"
-        @pickend="handlePickend"
-      >
-        <picker-view-column v-for="(column, columnIndex) in columnsList" :key="columnIndex">
-          <view
-            class="nut-picker-roller-item-tarotile"
-            v-for="(item, index) in column"
-            :key="item.value ? item.value : index"
-          >
-            {{ item.text }}
-          </view>
-        </picker-view-column>
-      </picker-view>
+    <view class="nut-picker__bar" v-if="showToolbar">
+      <view class="nut-picker__cancel nut-picker__left nut-picker__button" @click="cancel">{{
+        cancelText || translate('cancel')
+      }}</view>
+      <view class="nut-picker__title"> {{ title }}</view>
+      <view class="nut-picker__confirm nut-picker__right nut-picker__button" @click="confirmHandler()">{{
+        okText || translate('confirm')
+      }}</view>
+    </view>
+    <slot name="top"></slot>
 
-      <!-- Taro 下转换成 H5 -->
-      <view class="nut-picker__column" v-if="ENV == ENV_TYPE.WEB">
-        <view class="nut-picker__columnitem" v-for="(column, columnIndex) in columnsList" :key="columnIndex">
-          <nut-picker-column
-            :ref="swipeRef"
-            :itemShow="show"
-            :column="column"
-            :readonly="readonly"
-            :columnsType="columnsType"
-            :value="defaultValues[columnIndex]"
-            :threeDimensional="false"
-            :swipeDuration="swipeDuration"
-            @change="
-              (option) => {
-                changeHandler(columnIndex, option);
-              }
-            "
-          ></nut-picker-column>
+    <!-- Taro 下转换成 微信小程序 -->
+    <picker-view
+      v-if="ENV != ENV_TYPE.WEB"
+      :indicatorStyle="`height:${optionHeight}px`"
+      :value="defaultIndexes"
+      :style="pickerViewStyles"
+      :immediate-change="true"
+      @change="tileChange"
+      @pickstart="handlePickstart"
+      @pickend="handlePickend"
+    >
+      <picker-view-column v-for="(column, columnIndex) in columnsList" :key="columnIndex">
+        <view
+          class="nut-picker-roller-item-tarotile"
+          v-for="(item, index) in column"
+          :key="item.value ? item.value : index"
+        >
+          {{ item.text }}
         </view>
+      </picker-view-column>
+    </picker-view>
+
+    <!-- Taro 下转换成 H5 -->
+    <view class="nut-picker__column" :style="columnStyle" v-if="ENV == ENV_TYPE.WEB">
+      <view class="nut-picker__columnitem" v-for="(column, columnIndex) in columnsList" :key="columnIndex">
+        <nut-picker-column
+          :ref="swipeRef"
+          :column="column"
+          :columnsType="columnsType"
+          :value="defaultValues[columnIndex]"
+          :threeDimensional="false"
+          :swipeDuration="swipeDuration"
+          :visibleOptionNum="visibleOptionNum"
+          :optionHeight="optionHeight"
+          @change="
+            (option) => {
+              changeHandler(columnIndex, option);
+            }
+          "
+        ></nut-picker-column>
       </view>
-      <slot name="default"></slot>
-    </nut-popup>
+    </view>
+    <slot name="default"></slot>
   </view>
 </template>
 <script lang="ts">

+ 7 - 223
src/packages/__VUE/picker/index.vue

@@ -12,9 +12,7 @@
       <view class="nut-picker__columnitem" v-for="(column, columnIndex) in columnsList" :key="columnIndex">
         <nut-picker-column
           :ref="swipeRef"
-          :itemShow="show"
           :column="column"
-          :readonly="readonly"
           :columnsType="columnsType"
           :value="defaultValues && defaultValues[columnIndex]"
           :threeDimensional="threeDimensional"
@@ -34,83 +32,21 @@
   </div>
 </template>
 <script lang="ts">
-import { ref, reactive, watch, computed, toRefs, PropType, CSSProperties } from 'vue';
+import { ref, computed, PropType, CSSProperties } from 'vue';
 import { createComponent } from '@/packages/utils/create';
-
+import { usePicker } from './usePicker';
 import column from './Column.vue';
+import baseProps from './baseProps';
 const { componentName, create, translate } = createComponent('picker');
 
-export interface PickerOption {
-  text: string | number;
-  value: string | number;
-  disabled?: string;
-  children?: PickerOption[];
-  className?: string | number;
-}
-
 export default create({
   components: {
     [column.name]: column
   },
-  props: {
-    modelValue: {
-      type: Array as PropType<(string | number)[]>,
-      default: () => []
-    },
-    title: {
-      type: String,
-      default: ''
-    },
-    cancelText: {
-      type: String,
-      default: ''
-    },
-    okText: {
-      type: String,
-      default: ''
-    },
-    columns: {
-      type: Array as PropType<(PickerOption | PickerOption[])[]>,
-      default: () => {
-        return [];
-      }
-    },
-    readonly: {
-      type: Boolean,
-      default: false
-    },
-    threeDimensional: {
-      type: Boolean,
-      default: true
-    },
-    swipeDuration: {
-      type: [Number, String],
-      default: 1000
-    },
-    showToolbar: {
-      type: Boolean,
-      default: true
-    },
-    visibleOptionNum: {
-      type: [Number, String],
-      default: 7
-    },
-    optionHeight: {
-      type: [Number, String],
-      default: 36
-    }
-  },
-  emits: ['cancel', 'change', 'confirm', 'update:visible', 'update:modelValue'],
+  props: baseProps,
+  emits: ['cancel', 'change', 'confirm', 'update:modelValue'],
   setup(props, { emit }) {
-    const state = reactive({
-      show: false,
-      formattedColumns: props.columns
-    });
-
-    // 选中项
-    let defaultValues = ref<(number | string)[]>(
-      Array.isArray(props.modelValue) && props.modelValue.length > 0 ? props.modelValue : []
-    );
+    const { changeHandler, confirm, defaultValues, columnsList, columnsType, classes, cancel } = usePicker(props, emit);
 
     const pickerColumn = ref<any[]>([]);
 
@@ -119,14 +55,6 @@ export default create({
         pickerColumn.value.push(el);
       }
     };
-
-    const classes = computed(() => {
-      const prefixCls = componentName;
-      return {
-        [prefixCls]: true
-      };
-    });
-
     const columnStyle = computed(() => {
       const styles: CSSProperties = {};
       styles.height = `${+props.visibleOptionNum * +props.optionHeight}px`;
@@ -134,161 +62,17 @@ export default create({
       return styles;
     });
 
-    const selectedOptions = computed(() => {
-      let optins: PickerOption[] = [];
-      (columnsList.value as PickerOption[][]).map((column: PickerOption[], index: number) => {
-        let currOptions = [];
-        currOptions = column.filter((item) => item.value == defaultValues.value[index]);
-        optins.push(currOptions[0]);
-      });
-
-      return optins;
-    });
-    // 当前类型
-    const columnsType = computed(() => {
-      const firstColumn: PickerOption | PickerOption[] = state.formattedColumns[0];
-      if (firstColumn) {
-        if (Array.isArray(firstColumn)) {
-          return 'multiple';
-        }
-        if ('children' in firstColumn) {
-          return 'cascade';
-        }
-      }
-      return 'single';
-    });
-    // 将传入的 columns 格式化
-    const columnsList = computed(() => {
-      switch (columnsType.value) {
-        case 'multiple':
-          return state.formattedColumns as PickerOption[][];
-        case 'cascade':
-          // 级联数据处理
-
-          return formatCascade(
-            state.formattedColumns as PickerOption[],
-            defaultValues.value ? defaultValues.value : []
-          );
-        default:
-          return [state.formattedColumns] as PickerOption[][];
-      }
-    });
-
-    // 级联数据格式化
-    const formatCascade = (columns: PickerOption[], defaultValues: (number | string)[]) => {
-      const formatted: PickerOption[][] = [];
-      let cursor: PickerOption = {
-        text: '',
-        value: '',
-        children: columns
-      };
-
-      let columnIndex = 0;
-
-      while (cursor && cursor.children) {
-        const options: PickerOption[] = cursor.children;
-        const value = defaultValues[columnIndex];
-        let index = options.findIndex((columnItem) => columnItem.value == value);
-        if (index == -1) index = 0;
-        cursor = cursor.children[index];
-
-        columnIndex++;
-        formatted.push(options);
-      }
-
-      return formatted;
-    };
-
-    const cancel = () => {
-      emit('cancel', {
-        selectedValue: defaultValues.value,
-        selectedOptions: selectedOptions.value
-      });
-      emit('update:visible', false);
-    };
-
-    const changeHandler = (columnIndex: number, option: PickerOption) => {
-      if (option && Object.keys(option).length) {
-        defaultValues.value = defaultValues.value ? defaultValues.value : [];
-
-        if (columnsType.value === 'cascade') {
-          defaultValues.value[columnIndex] = option.value ? option.value : '';
-          let index = columnIndex;
-          let cursor = option;
-          while (cursor && cursor.children && cursor.children[0]) {
-            defaultValues.value[index + 1] = cursor.children[0].value;
-            index++;
-            cursor = cursor.children[0];
-          }
-
-          // 当前改变列 的 下一列 children 值为空
-          if (cursor && cursor.children && cursor.children.length == 0) {
-            defaultValues.value = defaultValues.value.slice(0, index + 1);
-          }
-        } else {
-          defaultValues.value[columnIndex] = option.hasOwnProperty('value') ? option.value : '';
-        }
-
-        emit('change', {
-          columnIndex: columnIndex,
-          selectedValue: defaultValues.value,
-          selectedOptions: selectedOptions.value
-        });
-      }
-    };
-
     const confirmHandler = () => {
       pickerColumn.value.length > 0 &&
         pickerColumn.value.forEach((column) => {
           column.stopMomentum();
         });
 
-      if (defaultValues.value && !defaultValues.value.length) {
-        columnsList.value.forEach((columns) => {
-          defaultValues.value.push(columns[0].value);
-          selectedOptions.value.push(columns[0]);
-        });
-      }
-
-      emit('confirm', {
-        selectedValue: defaultValues.value,
-        selectedOptions: selectedOptions.value
-      });
-      emit('update:visible', false);
+      confirm();
     };
 
-    const isSameValue = (valA: any, valB: any) => JSON.stringify(valA) === JSON.stringify(valB);
-
-    watch(
-      () => props.modelValue,
-      (newValues) => {
-        if (!isSameValue(newValues, defaultValues.value)) {
-          defaultValues.value = newValues;
-        }
-      },
-      { deep: true }
-    );
-
-    watch(
-      defaultValues,
-      (newValues) => {
-        if (!isSameValue(newValues, props.modelValue)) {
-          emit('update:modelValue', newValues);
-        }
-      },
-      { deep: true }
-    );
-
-    watch(
-      () => props.columns,
-      (val) => {
-        if (val.length) state.formattedColumns = val as PickerOption[];
-      }
-    );
-
     return {
       classes,
-      ...toRefs(state),
       column,
       columnsType,
       columnsList,

+ 13 - 19
src/packages/__VUE/picker/usePicker.ts

@@ -1,11 +1,7 @@
-import { ref, reactive, watch, computed, toRaw, toRefs, PropType } from 'vue';
-interface PickerOption {
-  text: string | number;
-  value: string | number;
-  disabled?: string;
-  children?: PickerOption[];
-  className?: string | number;
-}
+import { ref, reactive, watch, computed, toRefs, PropType } from 'vue';
+import { createComponent } from '@/packages/utils/create';
+const { componentName } = createComponent('picker');
+import { PickerOption } from './types';
 
 export const usePicker = (props: any, emit: any) => {
   const state = reactive({
@@ -13,9 +9,7 @@ export const usePicker = (props: any, emit: any) => {
   });
 
   // 选中项
-  let defaultValues = ref<(number | string)[]>(
-    Array.isArray(props.modelValue) && props.modelValue.length > 0 ? props.modelValue : []
-  );
+  let defaultValues = ref<(number | string)[]>([]);
 
   const pickerColumn = ref<any[]>([]);
 
@@ -26,13 +20,14 @@ export const usePicker = (props: any, emit: any) => {
   };
 
   const classes = computed(() => {
-    const prefixCls = 'nut-picker';
+    const prefixCls = componentName;
     return {
       [prefixCls]: true
     };
   });
 
   const selectedOptions = computed(() => {
+    console.log(23);
     let optins: PickerOption[] = [];
     (columnsList.value as PickerOption[][]).map((column: PickerOption[], index: number) => {
       let currOptions = [];
@@ -42,6 +37,7 @@ export const usePicker = (props: any, emit: any) => {
 
     return optins;
   });
+
   // 当前类型
   const columnsType = computed(() => {
     const firstColumn: PickerOption | PickerOption[] = state.formattedColumns[0];
@@ -93,12 +89,11 @@ export const usePicker = (props: any, emit: any) => {
     return formatted;
   };
 
-  const close = () => {
-    emit('close', {
+  const cancel = () => {
+    emit('cancel', {
       selectedValue: defaultValues.value,
       selectedOptions: selectedOptions.value
     });
-    emit('update:visible', false);
   };
 
   const changeHandler = (columnIndex: number, option: PickerOption) => {
@@ -135,7 +130,6 @@ export const usePicker = (props: any, emit: any) => {
     if (defaultValues.value && !defaultValues.value.length) {
       columnsList.value.forEach((columns) => {
         defaultValues.value.push(columns[0].value);
-        selectedOptions.value.push(columns[0]);
       });
     }
 
@@ -143,7 +137,6 @@ export const usePicker = (props: any, emit: any) => {
       selectedValue: defaultValues.value,
       selectedOptions: selectedOptions.value
     });
-    emit('update:visible', false);
   };
 
   const isSameValue = (valA: any, valB: any) => JSON.stringify(valA) === JSON.stringify(valB);
@@ -155,7 +148,7 @@ export const usePicker = (props: any, emit: any) => {
         defaultValues.value = newValues;
       }
     },
-    { deep: true }
+    { deep: true, immediate: true }
   );
 
   watch(
@@ -171,6 +164,7 @@ export const usePicker = (props: any, emit: any) => {
   watch(
     () => props.columns,
     (val) => {
+      console.log('同意');
       if (val.length) state.formattedColumns = val as PickerOption[];
     }
   );
@@ -180,7 +174,7 @@ export const usePicker = (props: any, emit: any) => {
     ...toRefs(state),
     columnsType,
     columnsList,
-    close,
+    cancel,
     changeHandler,
     confirm,
     defaultValues,

+ 1 - 1
src/packages/styles/variables.scss

@@ -173,7 +173,7 @@ $picker-item-height: 36px !default;
 $picker-item-text-color: $title-color !default;
 $picker-item-active-text-color: inherit !default;
 $picker-item-text-font-size: 14px !default;
-$picker-item-active-line-border: 1px solid #f7f8fa !default;
+$picker-item-active-line-border: 1px solid #eae7e7 !default;
 $picker-columns-item-color: $title-color !default;
 
 //input

+ 4 - 0
src/sites/mobile-taro/vue/config/index.js

@@ -55,6 +55,10 @@ const config = {
         enable: true,
         config: {}
       },
+      pxtransform: {
+        enable: true,
+        config: { selectorBlackList: ['nut-'] }
+      },
       cssModules: {
         enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
         config: {

+ 32 - 188
src/sites/mobile-taro/vue/src/dentry/pages/picker/index.vue

@@ -1,121 +1,39 @@
 <template>
   <div class="demo">
     <h2>基础用法</h2>
-    <nut-cell
-      title="请选择城市"
-      :desc="index"
-      @click="
-        () => {
-          show = true;
-        }
-      "
-    ></nut-cell>
-
     <nut-picker
-      v-model:visible="show"
       :columns="columns"
       title="城市选择"
       :safeAreaInsetBottom="true"
       @change="change"
-      @confirm="(options) => confirm('index', options)"
+      @confirm="confirm"
     ></nut-picker>
 
+    <h2>搭配 Popup 使用</h2>
+    <nut-cell title="城市选择" :desc="popupDesc" @click="show = true"></nut-cell>
+    <nut-popup position="bottom" v-model:visible="show" :safeAreaInsetBottom="true">
+      <nut-picker :columns="columns" title="城市选择" @confirm="popupConfirm" @cancel="show = false">
+        <nut-button block type="primary" style="margin-bottom: 20px">永远有效</nut-button>
+      </nut-picker>
+    </nut-popup>
+
     <h2>默认选中项</h2>
-    <nut-cell
-      title="请选择城市"
-      :desc="defult"
-      @click="
-        () => {
-          showDefult = true;
-        }
-      "
-    ></nut-cell>
-    <nut-picker
-      v-model="selectedValue"
-      v-model:visible="showDefult"
-      :columns="columns"
-      title="城市选择"
-      @confirm="(options) => confirm('defult', options)"
-    >
-    </nut-picker>
+    <nut-picker v-model="selectedValue" :columns="columns" title="城市选择" @confirm="confirm"> </nut-picker>
 
     <h2>多列样式</h2>
-    <nut-cell
-      title="请选择时间"
-      :desc="multiple"
-      @click="
-        () => {
-          showMultiple = true;
-        }
-      "
-    ></nut-cell>
-    <nut-picker
-      v-model="selectedTime"
-      v-model:visible="showMultiple"
-      :columns="multipleColumns"
-      title="城市选择"
-      @confirm="(options) => confirm('multiple', options)"
-    >
-    </nut-picker>
+    <nut-picker v-model="selectedTime" :columns="multipleColumns" title="城市选择" @confirm="confirm"> </nut-picker>
 
     <h2>多级联动</h2>
-    <nut-cell
-      title="请选择地址"
-      :desc="cascader"
-      @click="
-        () => {
-          showCascader = true;
-        }
-      "
-    ></nut-cell>
-    <nut-picker
-      v-model="selectedCascader"
-      v-model:visible="showCascader"
-      :columns="cascaderColumns"
-      title="城市选择"
-      @confirm="(options) => confirm('cascader', options)"
-    ></nut-picker>
+    <nut-picker v-model="selectedCascader" :columns="cascaderColumns" title="城市选择" @confirm="confirm"></nut-picker>
 
     <h2>异步获取</h2>
-    <nut-cell
-      title="请选择地址"
-      :desc="async"
-      @click="
-        () => {
-          showAsync = true;
-        }
-      "
-    ></nut-cell>
-    <nut-picker
-      v-model="asyncValue"
-      v-model:visible="showAsync"
-      :columns="asyncColumns"
-      title="城市选择"
-      @confirm="(options) => confirm('async', options)"
-    ></nut-picker>
+    <nut-picker v-model="asyncValue" :columns="asyncColumns" title="城市选择" @confirm="confirm"></nut-picker>
 
-    <h2>自定义按钮</h2>
-    <nut-cell
-      title="请选择有效日期"
-      :desc="effect"
-      @click="
-        () => {
-          showEffect = true;
-        }
-      "
-    ></nut-cell>
-    <nut-picker
-      v-model:visible="showEffect"
-      :columns="effectColumns"
-      title="日期选择"
-      @confirm="(options) => confirm('effect', options)"
-    >
-      <nut-button block type="primary" @click="alwaysFun">永远有效</nut-button></nut-picker
-    >
+    <nut-toast :msg="msg" v-model:visible="showToast" type="text" />
   </div>
 </template>
 <script lang="ts">
-import { reactive, onMounted, ref, toRefs } from 'vue';
+import { onMounted, ref } from 'vue';
 import { PickerOption } from '../../../../../../../packages/__VUE/picker/types';
 export default {
   props: {},
@@ -123,8 +41,10 @@ export default {
     const selectedValue = ref(['ZheJiang']);
     const selectedTime = ref(['Wednesday', 'Afternoon']);
     const selectedCascader = ref(['FuJian', 'FuZhou', 'TaiJiang']);
-    const asyncValue = ref<string[]>([]);
-    const columsNum = ref([]);
+    const asyncValue = ref<string[]>();
+    const msg = ref();
+    const showToast = ref(false);
+
     const columns = ref([
       { text: '南京市', value: 'NanJing' },
       { text: '无锡市', value: 'WuXi' },
@@ -227,51 +147,9 @@ export default {
     const asyncColumns = ref<PickerOption[]>([]);
 
     const show = ref(false);
-    const showDefult = ref(false);
-    const showMultiple = ref(false);
-    const showCascader = ref(false);
-    const showAsync = ref(false);
-    const showEffect = ref(false);
-    const showPort = ref(false);
-    const showTitle = ref(false);
-
-    const desc = reactive({
-      index: '',
-      defult: '',
-      multiple: '',
-      cascader: '',
-      async: '',
-      effect: '',
-      title: ''
-    });
-
-    const open = (index: number) => {
-      switch (index) {
-        case 0:
-          show.value = true;
-          break;
-        case 1:
-          showDefult.value = true;
-          break;
-        case 2:
-          showMultiple.value = true;
-          break;
-        case 3:
-          showCascader.value = true;
-          break;
-        case 4:
-          showAsync.value = true;
-          break;
-        default:
-          showCascader.value = true;
-      }
-    };
+    const popupDesc = ref();
 
     onMounted(() => {
-      for (let i = 1; i < 60; i++) {
-        columsNum.value.push({ text: i, value: i });
-      }
-
       setTimeout(() => {
         asyncColumns.value = [
           { text: '南京市', value: 'NanJing' },
@@ -284,49 +162,23 @@ export default {
         ];
 
         asyncValue.value = ['ZangZu'];
-      }, 500);
+      }, 1000);
     });
 
-    const confirm = (tag: string, { selectedValue }: { selectedValue: string[] }) => {
-      (desc as any)[tag] = selectedValue.join(',');
+    const confirm = ({ selectedValue, selectedOptions }: { selectedValue: string[]; selectedOptions: any }) => {
+      showToast.value = true;
+      msg.value = selectedOptions.map((val: any) => val.text).join(',');
     };
+
     const change = ({ selectedValue }: { selectedValue: string[] }) => {
       console.log(selectedValue);
     };
 
-    const portChange = (chooseDate: any) => {
-      const { columnIndex, selectedOptions, selectedValue } = chooseDate;
-      console.log(chooseDate);
-      if (columnIndex == 0) {
-        //  if(portColumns.value[0].children.length == 0){
-
-        //  }
-        console.log('选择后更新');
-        portColumns.value[0].children = ([] as any).concat([
-          {
-            text: '杭州',
-            value: 'HangZhou',
-            children: [
-              { text: '西湖区', value: 'XiHu' },
-              { text: '余杭区', value: 'YuHang' }
-            ]
-          },
-          {
-            text: '温州',
-            value: 'WenZhou',
-            children: [
-              { text: '鹿城区', value: 'LuCheng' },
-              { text: '瓯海区', value: 'OuHai' }
-            ]
-          }
-        ]);
-      }
+    const popupConfirm = ({ selectedValue, selectedOptions }: { selectedValue: string[]; selectedOptions: any }) => {
+      popupDesc.value = selectedOptions.map((val: any) => val.text).join(',');
+      show.value = false;
     };
 
-    const alwaysFun = () => {
-      showEffect.value = false;
-      desc.effect = '永远有效';
-    };
     return {
       selectedValue,
       selectedTime,
@@ -334,25 +186,17 @@ export default {
       asyncValue,
       columns,
       show,
-      showDefult,
-      showAsync,
-      ...toRefs(desc),
-      showMultiple,
-      showCascader,
-      open,
       multipleColumns,
       cascaderColumns,
       confirm,
       change,
       asyncColumns,
       effectColumns,
-      showEffect,
-      alwaysFun,
-      columsNum,
-      showPort,
-      showTitle,
+      showToast,
       portColumns,
-      portChange
+      popupConfirm,
+      popupDesc,
+      msg
     };
   }
 };