diff --git a/compiled/alipay/src/Form/FormPicker/props.ts b/compiled/alipay/src/Form/FormPicker/props.ts index c062f4cee..858ab1531 100644 --- a/compiled/alipay/src/Form/FormPicker/props.ts +++ b/compiled/alipay/src/Form/FormPicker/props.ts @@ -1,4 +1,4 @@ -import { IPickerProps, PickerFunctionalProps } from '../../Picker/props'; +import { IPickerProps, PickerDefaultProps } from '../../Picker/props'; import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; export interface FormPickerProps extends IPickerProps, FormItemProps { @@ -10,6 +10,6 @@ export interface FormPickerProps extends IPickerProps, FormItemProps { export const FormPickerDefaultProps: Partial = { ...FormItemDefaultProps, - ...PickerFunctionalProps, + ...PickerDefaultProps, arrow: false, }; diff --git a/compiled/alipay/src/Picker/index.axml b/compiled/alipay/src/Picker/index.axml index 8f795ba1e..5d01e2c43 100644 --- a/compiled/alipay/src/Picker/index.axml +++ b/compiled/alipay/src/Picker/index.axml @@ -31,7 +31,7 @@ animationType="{{ animationType }}" destroyOnClose onClose="onMaskDismiss" - visible="{{ state.visible }}"> + visible="{{ visible }}"> { - const [value, { isControlled: isValueControlled, update: updateValue }] = - useMixState(props.defaultValue ?? [], { - value: props.value, - }); - - const { triggerEvent, triggerEventOnly, triggerEventValues } = - useComponentEvent(props); - - const [visible, { update: updateVisible }] = useMixState( - props.defaultVisible, - { - value: props.visible, - } - ); - const singleRef = useRef(false); - const selectIndexRef = useRef(null); - - function triggerPicker(newVisibleValue: boolean) { - updateVisible(newVisibleValue); - triggerEvent('visibleChange', newVisibleValue); - } - - const [selectedIndex, setSelectedIndex] = useState([]); - - const columns = useMemo(() => { - return getterColumns(props.options, singleRef); - }, [props.options]); - - useEffect(() => { - selectIndexRef.current = null; - setSelectedIndex(getterSelectedIndex(columns, value, singleRef)); - }, [columns, value]); - - const formatValue = useMemo(() => { - if (typeof props.formattedValueText === 'string') { - return props.formattedValueText; - } - const formatValue = getterFormatText( - columns, - value, - props.onFormat, - singleRef - ); - return formatValue; - }, [props.formattedValueText, visible, columns, value, props.onFormat]); +Component( + PickerDefaultProps, + { + // visible受控判断 + isVisibleControlled() { + return 'visible' in getValueFromProps(this); + }, + initData() { + const [options, visible, defaultVisible] = getValueFromProps(this, [ + 'options', + 'visible', + 'defaultVisible', + ]); + const columns = this.getterColumns(options); + this.setData( + { + columns, + }, + () => { + const formatValue = this.getterFormatText(); + const selectedIndex = this.getterSelectedIndex(); + this.setData({ + formatValue, + selectedIndex, + visible: this.isVisibleControlled() ? visible : defaultVisible, + }); + } + ); + }, + getterColumns(options) { + let columns = []; + if (options.length > 0) { + if (options.every((item) => Array.isArray(item))) { + this.single = false; + columns = options.slice(); + } else { + this.single = true; + columns = [options]; + } + } + return columns; + }, + defaultFormat(value, column) { + if (Array.isArray(column)) { + return column + .filter((c) => c !== undefined) + .map(function (c) { + if (typeof c === 'object') { + return c.label; + } + return c; + }) + .join('-'); + } + return (column && column.label) || column || ''; + }, + getterFormatText() { + const [onFormat, formattedValueText] = getValueFromProps(this, [ + 'onFormat', + 'formattedValueText', + ]); + if (typeof formattedValueText === 'string') { + return formattedValueText; + } + const { columns } = this.data; + const realValue = this.getValue(); + const { matchedColumn } = getStrictMatchedItemByValue( + columns, + realValue, + this.single + ); + const formatValueByProps = onFormat && onFormat(realValue, matchedColumn); + if (formatValueByProps !== undefined && formatValueByProps !== null) { + return formatValueByProps; + } + return this.defaultFormat(realValue, matchedColumn); + }, + getterSelectedIndex() { + const selectedIndex = []; + const columns = this.data.columns; + const realValue = this.getValue(); + let value = realValue || []; + if (this.single) { + value = [realValue]; + } + for (let i = 0; i < columns.length; i++) { + const column = columns[i]; + const compareValue = value[i]; + if (compareValue === undefined || compareValue === null) { + selectedIndex[i] = 0; + } + let index = column.findIndex((c) => { + return c === compareValue || c.value === compareValue; + }); + if (index === -1) { + index = 0; + } + selectedIndex[i] = index; + } + return selectedIndex; + }, - useEvent('onOpen', () => { - if (props.disabled) { - return; - } - selectIndexRef.current = null; - const selectedIndex = getterSelectedIndex(columns, value, singleRef); - setSelectedIndex(selectedIndex); - triggerPicker(true); - }); + onOpen() { + const disabled = getValueFromProps(this, 'disabled'); + if (!disabled) { + this.tempSelectedIndex = null; + const selectedIndex = this.getterSelectedIndex(); + this.setData({ + selectedIndex, + }); + this.triggerPicker(true); + } + }, - useEvent('onCancel', () => { - triggerPicker(false); - triggerEventOnly('cancel', { detail: { type: 'cancel' } }); - }); + triggerPicker(visible) { + this.setData({ + visible, + }); + triggerEvent(this, 'visibleChange', visible); + }, - useEvent('onMaskDismiss', () => { - if (!props.maskClosable) { - return; - } - triggerPicker(false); - triggerEventOnly('cancel', { detail: { type: 'mask' } }); - }); + onMaskDismiss() { + const maskClosable = getValueFromProps(this, 'maskClosable'); + if (!maskClosable) { + return; + } + this.triggerPicker(false); + triggerEventOnly(this, 'cancel', { detail: { type: 'mask' } }); + }, - useEvent('onChange', (e) => { - const { value: selectedIndex } = e.detail; - const { matchedColumn, matchedValues } = getMatchedItemByIndex( - columns, - selectedIndex, - singleRef - ); - selectIndexRef.current = selectedIndex; - setSelectedIndex(selectedIndex); - triggerEventValues('change', [matchedValues, matchedColumn], e); - }); + onCancel() { + this.triggerPicker(false); + triggerEventOnly(this, 'cancel', { detail: { type: 'cancel' } }); + }, - useEvent('onOk', () => { - let result; - if (selectIndexRef.current) { - result = getMatchedItemByIndex( - columns, - selectIndexRef.current, - singleRef + onChange(e) { + const { value: selectedIndex } = e.detail; + this.tempSelectedIndex = selectedIndex; + this.isChangingPickerView = true; + const { matchedColumn, matchedValues } = getMatchedItemByIndex( + this.data.columns, + this.tempSelectedIndex, + this.single ); - } else { - result = getMatchedItemByValue(columns, value, singleRef); - } - - const { matchedColumn, matchedValues } = result; - - triggerPicker(false); - if (!isValueControlled) { - updateValue(matchedValues); - } - triggerEventValues('ok', [matchedValues, matchedColumn]); - }); + this.setData({ + selectedIndex, + }); + triggerEventValues(this, 'change', [matchedValues, matchedColumn], e); + }, - return { - formatValue, - selectedIndex, - columns, - state: { - visible, + async onOk() { + let result; + if (this.tempSelectedIndex) { + result = getMatchedItemByIndex( + this.data.columns, + this.tempSelectedIndex, + this.single + ); + } else { + result = getMatchedItemByValue( + this.data.columns, + this.getValue(), + this.single + ); + } + const { matchedColumn, matchedValues } = result; + this.triggerPicker(false); + if (!this.isControlled()) { + this.update(matchedValues); + } + triggerEventValues(this, 'ok', [matchedValues, matchedColumn]); }, - mixin: { - value, + }, + { + formatValue: '', + columns: [], + visible: null, + selectedIndex: [], + }, + [ + mixinValue({ + transformValue(value) { + return { + needUpdate: true, + value: value === undefined ? [] : value, + }; + }, + }), + ], + { + tempSelectedIndex: null, + single: false, + isChangingPickerView: false, + onInit() { + this.initData(); }, - }; -}; - -mountComponent(Picker, PickerFunctionalProps); + didUpdate(prevProps) { + const options = getValueFromProps(this, 'options'); + if (!equal(options, prevProps.options)) { + const newColums = this.getterColumns(options); + this.setData( + { + columns: newColums, + }, + () => { + // 如果是在滚动过程中columns发生变化,以onChange里抛出的selectedIndex为准 + if (!this.isChangingPickerView) { + this.tempSelectedIndex = null; + const selectedIndex = this.getterSelectedIndex(); + this.setData({ + selectedIndex, + }); + } + } + ); + } + const value = getValueFromProps(this, 'value'); + if (!equal(prevProps.value, value)) { + const selectedIndex = this.getterSelectedIndex(); + this.tempSelectedIndex = null; + this.setData({ + selectedIndex, + }); + } + const visible = getValueFromProps(this, 'visible'); + if (!equal(prevProps.visible, visible)) { + this.setData({ visible }); + } + const formatValue = this.getterFormatText(); + const formattedValueText = getValueFromProps(this, 'formattedValueText'); + if ( + formatValue !== this.data.formatValue || + prevProps.formattedValueText !== formattedValueText + ) { + this.setData({ + formatValue, + }); + } + this.isChangingPickerView = false; + }, + } +); diff --git a/compiled/alipay/src/Picker/props.ts b/compiled/alipay/src/Picker/props.ts index e5c75a091..3d2eab5a1 100644 --- a/compiled/alipay/src/Picker/props.ts +++ b/compiled/alipay/src/Picker/props.ts @@ -54,7 +54,7 @@ export interface IPickerProps extends IBaseProps { * @default '请选择' */ placeholder: string; - /** + /** * @description 空状态提示文案 * @default '暂无数据' */ @@ -131,17 +131,6 @@ export interface IPickerProps extends IBaseProps { } export const PickerDefaultProps: Partial = { - okText: '确定', - cancelText: '取消', - disabled: false, - maskClosable: false, - options: [], - placeholder: '请选择', - defaultValue: [], - emptyText: '暂无数据' -}; - -export const PickerFunctionalProps: Partial = { formattedValueText: null, visible: null, defaultVisible: null, @@ -158,5 +147,5 @@ export const PickerFunctionalProps: Partial = { popStyle: '', maskClosable: true, onFormat: null, - emptyText: '暂无数据' + emptyText: '暂无数据', }; diff --git a/compiled/alipay/src/Picker/utils.ts b/compiled/alipay/src/Picker/utils.ts index 9ec50878d..e3a9a1eb0 100644 --- a/compiled/alipay/src/Picker/utils.ts +++ b/compiled/alipay/src/Picker/utils.ts @@ -1,5 +1,3 @@ -import { PickerValue } from './props'; - function getColumnValue(columnItem) { if (typeof columnItem === 'object') return columnItem.value; return columnItem; @@ -14,7 +12,7 @@ export function getStrictMatchedItemByValue(columns, value, single) { let index = null; for (let i = 0; i < columns.length; i++) { const column = columns[i]; - const compareValue = value[i]; + const compareValue = (value || [])[i]; index = column.findIndex((c) => { const columnValue = getColumnValue(c); return columnValue === compareValue; @@ -29,8 +27,8 @@ export function getStrictMatchedItemByValue(columns, value, single) { } // 如果找不到value对应的item项目,返回第一项 -export function getMatchedItemByValue(columns, value, singleRef) { - if (singleRef.current) { +export function getMatchedItemByValue(columns, value, single) { + if (single) { value = [value]; } const matchedValues = []; @@ -38,7 +36,7 @@ export function getMatchedItemByValue(columns, value, singleRef) { let index = null; for (let i = 0; i < columns.length; i++) { const column = columns[i]; - const compareValue = value[i]; + const compareValue = (value || [])[i]; if (compareValue === undefined || compareValue === null) { index = 0; } else { @@ -54,8 +52,8 @@ export function getMatchedItemByValue(columns, value, singleRef) { matchedValues[i] = getColumnValue(column[index]); } return { - matchedColumn: singleRef.current ? matchedColumn[0] : matchedColumn, - matchedValues: singleRef.current ? matchedValues[0] : matchedValues, + matchedColumn: single ? matchedColumn[0] : matchedColumn, + matchedValues: single ? matchedValues[0] : matchedValues, }; } @@ -84,75 +82,7 @@ export function getMatchedItemByIndex(columns, selectedIndex, single) { } return { - matchedColumn: single.current ? matchedColumn[0] : matchedColumn, - matchedValues: single.current ? matchedValues[0] : matchedValues, + matchedColumn: single ? matchedColumn[0] : matchedColumn, + matchedValues: single ? matchedValues[0] : matchedValues, }; } - -export function getterColumns(options: PickerValue[], singleRef) { - let columns = []; - if (options.length > 0) { - if (options.every((item) => Array.isArray(item))) { - singleRef.current = false; - columns = options.slice(); - } else { - singleRef.current = true; - columns = [options]; - } - } - return columns; -} - -export function defaultFormat(value, column) { - if (Array.isArray(column)) { - return column - .filter((c) => c !== undefined) - .map(function (c) { - if (typeof c === 'object') { - return c.label; - } - return c; - }) - .join('-'); - } - return (column && column.label) || column || ''; -} - -export function getterFormatText(columns, realValue, onFormat, singleRef) { - const { matchedColumn } = getStrictMatchedItemByValue( - columns, - realValue, - singleRef.current - ); - - if (typeof onFormat === 'function') { - const formatValueByProps = onFormat(realValue, matchedColumn); - if (formatValueByProps !== undefined) { - return formatValueByProps; - } - } - return defaultFormat(realValue, matchedColumn); -} - -export function getterSelectedIndex(columns, realValue, sinefileRef) { - const selectedIndex = []; - let value = realValue || []; - if (sinefileRef.current) { - value = [realValue]; - } - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - const compareValue = value[i]; - if (compareValue === undefined || compareValue === null) { - selectedIndex[i] = 0; - } - let index = column.findIndex((c) => { - return c === compareValue || c.value === compareValue; - }); - if (index === -1) { - index = 0; - } - selectedIndex[i] = index; - } - return selectedIndex; -} diff --git a/compiled/wechat/src/Form/FormPicker/props.js b/compiled/wechat/src/Form/FormPicker/props.js index e6487f9c7..d071071d5 100644 --- a/compiled/wechat/src/Form/FormPicker/props.js +++ b/compiled/wechat/src/Form/FormPicker/props.js @@ -9,6 +9,6 @@ var __assign = (this && this.__assign) || function () { }; return __assign.apply(this, arguments); }; -import { PickerFunctionalProps } from '../../Picker/props'; +import { PickerDefaultProps } from '../../Picker/props'; import { FormItemDefaultProps } from '../FormItem/props'; -export var FormPickerDefaultProps = __assign(__assign(__assign({}, FormItemDefaultProps), PickerFunctionalProps), { arrow: false }); +export var FormPickerDefaultProps = __assign(__assign(__assign({}, FormItemDefaultProps), PickerDefaultProps), { arrow: false }); diff --git a/compiled/wechat/src/Picker/index.js b/compiled/wechat/src/Picker/index.js index 690a2527f..595121e25 100644 --- a/compiled/wechat/src/Picker/index.js +++ b/compiled/wechat/src/Picker/index.js @@ -1,92 +1,267 @@ -import { useEvent, useRef, useState, useEffect, useMemo, } from 'functional-mini/component'; -import '../_util/assert-component2'; -import { mountComponent } from '../_util/component'; -import { useComponentEvent } from '../_util/hooks/useComponentEvent'; -import { useMixState } from '../_util/hooks/useMixState'; -import { PickerFunctionalProps } from './props'; -import { getMatchedItemByIndex, getMatchedItemByValue, getterColumns, getterFormatText, getterSelectedIndex, } from './utils'; -var Picker = function (props) { - var _a; - var _b = useMixState((_a = props.defaultValue) !== null && _a !== void 0 ? _a : [], { - value: props.value, - }), value = _b[0], _c = _b[1], isValueControlled = _c.isControlled, updateValue = _c.update; - var _d = useComponentEvent(props), triggerEvent = _d.triggerEvent, triggerEventOnly = _d.triggerEventOnly, triggerEventValues = _d.triggerEventValues; - var _e = useMixState(props.defaultVisible, { - value: props.visible, - }), visible = _e[0], updateVisible = _e[1].update; - var singleRef = useRef(false); - var selectIndexRef = useRef(null); - function triggerPicker(newVisibleValue) { - updateVisible(newVisibleValue); - triggerEvent('visibleChange', newVisibleValue); +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } - var _f = useState([]), selectedIndex = _f[0], setSelectedIndex = _f[1]; - var columns = useMemo(function () { - return getterColumns(props.options, singleRef); - }, [props.options]); - useEffect(function () { - selectIndexRef.current = null; - setSelectedIndex(getterSelectedIndex(columns, value, singleRef)); - }, [columns, value]); - var formatValue = useMemo(function () { - if (typeof props.formattedValueText === 'string') { - return props.formattedValueText; +}; +import { Component, triggerEvent, triggerEventOnly, triggerEventValues, getValueFromProps, } from '../_util/simply'; +import { PickerDefaultProps } from './props'; +import { getMatchedItemByValue, getMatchedItemByIndex, getStrictMatchedItemByValue, } from './utils'; +import mixinValue from '../mixins/value'; +Component(PickerDefaultProps, { + // visible受控判断 + isVisibleControlled: function () { + return getValueFromProps(this, 'visible') !== null; + }, + initData: function () { + var _this = this; + var _a = getValueFromProps(this, [ + 'options', + 'visible', + 'defaultVisible', + ]), options = _a[0], visible = _a[1], defaultVisible = _a[2]; + var columns = this.getterColumns(options); + this.setData({ + columns: columns, + }, function () { + var formatValue = _this.getterFormatText(); + var selectedIndex = _this.getterSelectedIndex(); + _this.setData({ + formatValue: formatValue, + selectedIndex: selectedIndex, + visible: _this.isVisibleControlled() ? visible : defaultVisible, + }); + }); + }, + getterColumns: function (options) { + var columns = []; + if (options.length > 0) { + if (options.every(function (item) { return Array.isArray(item); })) { + this.single = false; + columns = options.slice(); + } + else { + this.single = true; + columns = [options]; + } } - var formatValue = getterFormatText(columns, value, props.onFormat, singleRef); - return formatValue; - }, [props.formattedValueText, visible, columns, value, props.onFormat]); - useEvent('onOpen', function () { - if (props.disabled) { - return; + return columns; + }, + defaultFormat: function (value, column) { + if (Array.isArray(column)) { + return column + .filter(function (c) { return c !== undefined; }) + .map(function (c) { + if (typeof c === 'object') { + return c.label; + } + return c; + }) + .join('-'); } - selectIndexRef.current = null; - var selectedIndex = getterSelectedIndex(columns, value, singleRef); - setSelectedIndex(selectedIndex); - triggerPicker(true); - }); - useEvent('onCancel', function () { - triggerPicker(false); - triggerEventOnly('cancel', { detail: { type: 'cancel' } }); - }); - useEvent('onMaskDismiss', function () { - if (!props.maskClosable) { - return; + return (column && column.label) || column || ''; + }, + getterFormatText: function () { + var _a = getValueFromProps(this, [ + 'onFormat', + 'formattedValueText', + ]), onFormat = _a[0], formattedValueText = _a[1]; + if (typeof formattedValueText === 'string') { + return formattedValueText; } - triggerPicker(false); - triggerEventOnly('cancel', { detail: { type: 'mask' } }); - }); - useEvent('onChange', function (e) { - var selectedIndex = e.detail.value; - var _a = getMatchedItemByIndex(columns, selectedIndex, singleRef), matchedColumn = _a.matchedColumn, matchedValues = _a.matchedValues; - selectIndexRef.current = selectedIndex; - setSelectedIndex(selectedIndex); - triggerEventValues('change', [matchedValues, matchedColumn], e); - }); - useEvent('onOk', function () { - var result; - if (selectIndexRef.current) { - result = getMatchedItemByIndex(columns, selectIndexRef.current, singleRef); + var columns = this.data.columns; + var realValue = this.getValue(); + var matchedColumn = getStrictMatchedItemByValue(columns, realValue, this.single).matchedColumn; + var formatValueByProps = onFormat && onFormat(realValue, matchedColumn); + if (formatValueByProps !== undefined && formatValueByProps !== null) { + return formatValueByProps; } - else { - result = getMatchedItemByValue(columns, value, singleRef); + return this.defaultFormat(realValue, matchedColumn); + }, + getterSelectedIndex: function () { + var selectedIndex = []; + var columns = this.data.columns; + var realValue = this.getValue(); + var value = realValue || []; + if (this.single) { + value = [realValue]; } - var matchedColumn = result.matchedColumn, matchedValues = result.matchedValues; - triggerPicker(false); - if (!isValueControlled) { - updateValue(matchedValues); + var _loop_1 = function (i) { + var column = columns[i]; + var compareValue = value[i]; + if (compareValue === undefined || compareValue === null) { + selectedIndex[i] = 0; + } + var index = column.findIndex(function (c) { + return c === compareValue || c.value === compareValue; + }); + if (index === -1) { + index = 0; + } + selectedIndex[i] = index; + }; + for (var i = 0; i < columns.length; i++) { + _loop_1(i); } - triggerEventValues('ok', [matchedValues, matchedColumn]); - }); - return { - formatValue: formatValue, - selectedIndex: selectedIndex, - columns: columns, - state: { + return selectedIndex; + }, + onOpen: function () { + var disabled = getValueFromProps(this, 'disabled'); + if (!disabled) { + this.tempSelectedIndex = null; + var selectedIndex = this.getterSelectedIndex(); + this.setData({ + selectedIndex: selectedIndex, + }); + this.triggerPicker(true); + } + }, + triggerPicker: function (visible) { + this.setData({ visible: visible, + }); + triggerEvent(this, 'visibleChange', visible); + }, + onMaskDismiss: function () { + var maskClosable = getValueFromProps(this, 'maskClosable'); + if (!maskClosable) { + return; + } + this.triggerPicker(false); + triggerEventOnly(this, 'cancel', { detail: { type: 'mask' } }); + }, + onCancel: function () { + this.triggerPicker(false); + triggerEventOnly(this, 'cancel', { detail: { type: 'cancel' } }); + }, + onChange: function (e) { + var selectedIndex = e.detail.value; + this.tempSelectedIndex = selectedIndex; + this.isChangingPickerView = true; + var _a = getMatchedItemByIndex(this.data.columns, this.tempSelectedIndex, this.single), matchedColumn = _a.matchedColumn, matchedValues = _a.matchedValues; + this.setData({ + selectedIndex: selectedIndex, + }); + triggerEventValues(this, 'change', [matchedValues, matchedColumn], e); + }, + onOk: function () { + return __awaiter(this, void 0, void 0, function () { + var result, matchedColumn, matchedValues; + return __generator(this, function (_a) { + if (this.tempSelectedIndex) { + result = getMatchedItemByIndex(this.data.columns, this.tempSelectedIndex, this.single); + } + else { + result = getMatchedItemByValue(this.data.columns, this.getValue(), this.single); + } + matchedColumn = result.matchedColumn, matchedValues = result.matchedValues; + this.triggerPicker(false); + if (!this.isControlled()) { + this.update(matchedValues); + } + triggerEventValues(this, 'ok', [matchedValues, matchedColumn]); + return [2 /*return*/]; + }); + }); + }, +}, { + formatValue: '', + columns: [], + visible: null, + selectedIndex: [], +}, [ + mixinValue({ + transformValue: function (value) { + return { + needUpdate: true, + value: value === undefined ? [] : value, + }; }, - mixin: { - value: value, + }), +], { + tempSelectedIndex: null, + single: false, + isChangingPickerView: false, + created: function () { + this.initData(); + }, + observers: { + 'options': function () { + var _this = this; + var options = getValueFromProps(this, 'options'); + var newColums = this.getterColumns(options); + this.setData({ + columns: newColums, + }, function () { + // 如果是在滚动过程中columns发生变化,以onChange里抛出的selectedIndex为准 + if (!_this.isChangingPickerView) { + _this.tempSelectedIndex = null; + var selectedIndex = _this.getterSelectedIndex(); + _this.setData({ + selectedIndex: selectedIndex, + }); + } + _this.isChangingPickerView = false; + }); }, - }; -}; -mountComponent(Picker, PickerFunctionalProps); + 'value': function () { + var selectedIndex = this.getterSelectedIndex(); + this.tempSelectedIndex = null; + this.setData({ + selectedIndex: selectedIndex, + }); + }, + 'visible': function () { + var visible = getValueFromProps(this, 'visible'); + if (this.data.visible !== visible) { + this.setData({ + visible: visible, + }); + } + }, + 'formattedValueText': function () { + var formattedValueText = getValueFromProps(this, 'formattedValueText'); + this.setData({ + formatValue: formattedValueText, + }); + }, + '**': function () { + var formatValue = this.getterFormatText(); + if (formatValue !== this.data.formatValue) { + this.setData({ + formatValue: formatValue, + }); + } + }, + }, +}); diff --git a/compiled/wechat/src/Picker/index.wxml b/compiled/wechat/src/Picker/index.wxml index eb93daf3e..f6e2602d9 100644 --- a/compiled/wechat/src/Picker/index.wxml +++ b/compiled/wechat/src/Picker/index.wxml @@ -28,7 +28,7 @@ animationType="{{ animationType }}" destroyOnClose bind:close="onMaskDismiss" - visible="{{ state.visible }}"> + visible="{{ visible }}"> 0) { - if (options.every(function (item) { return Array.isArray(item); })) { - singleRef.current = false; - columns = options.slice(); - } - else { - singleRef.current = true; - columns = [options]; - } - } - return columns; -} -export function defaultFormat(value, column) { - if (Array.isArray(column)) { - return column - .filter(function (c) { return c !== undefined; }) - .map(function (c) { - if (typeof c === 'object') { - return c.label; - } - return c; - }) - .join('-'); - } - return (column && column.label) || column || ''; -} -export function getterFormatText(columns, realValue, onFormat, singleRef) { - var matchedColumn = getStrictMatchedItemByValue(columns, realValue, singleRef.current).matchedColumn; - if (typeof onFormat === 'function') { - var formatValueByProps = onFormat(realValue, matchedColumn); - if (formatValueByProps !== undefined) { - return formatValueByProps; - } - } - return defaultFormat(realValue, matchedColumn); -} -export function getterSelectedIndex(columns, realValue, sinefileRef) { - var selectedIndex = []; - var value = realValue || []; - if (sinefileRef.current) { - value = [realValue]; - } - var _loop_3 = function (i) { - var column = columns[i]; - var compareValue = value[i]; - if (compareValue === undefined || compareValue === null) { - selectedIndex[i] = 0; - } - var index = column.findIndex(function (c) { - return c === compareValue || c.value === compareValue; - }); - if (index === -1) { - index = 0; - } - selectedIndex[i] = index; - }; - for (var i = 0; i < columns.length; i++) { - _loop_3(i); - } - return selectedIndex; -} diff --git a/src/Form/FormPicker/props.ts b/src/Form/FormPicker/props.ts index c062f4cee..858ab1531 100644 --- a/src/Form/FormPicker/props.ts +++ b/src/Form/FormPicker/props.ts @@ -1,4 +1,4 @@ -import { IPickerProps, PickerFunctionalProps } from '../../Picker/props'; +import { IPickerProps, PickerDefaultProps } from '../../Picker/props'; import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; export interface FormPickerProps extends IPickerProps, FormItemProps { @@ -10,6 +10,6 @@ export interface FormPickerProps extends IPickerProps, FormItemProps { export const FormPickerDefaultProps: Partial = { ...FormItemDefaultProps, - ...PickerFunctionalProps, + ...PickerDefaultProps, arrow: false, }; diff --git a/src/Picker/index.axml.tsx b/src/Picker/index.axml.tsx index 3f2597bd2..fd5b435b2 100644 --- a/src/Picker/index.axml.tsx +++ b/src/Picker/index.axml.tsx @@ -30,9 +30,9 @@ export default ( indicatorStyle, indicatorClassName, options, - emptyText + emptyText, }: TSXMLProps, - { state, formatValue, selectedIndex, columns }: InternalData + { visible, formatValue, selectedIndex, columns }: InternalData ) => ( { - const [value, { isControlled: isValueControlled, update: updateValue }] = - useMixState(props.defaultValue ?? [], { - value: props.value, - }); - - const { triggerEvent, triggerEventOnly, triggerEventValues } = - useComponentEvent(props); - - const [visible, { update: updateVisible }] = useMixState( - props.defaultVisible, - { - value: props.visible, - } - ); - const singleRef = useRef(false); - const selectIndexRef = useRef(null); - - function triggerPicker(newVisibleValue: boolean) { - updateVisible(newVisibleValue); - triggerEvent('visibleChange', newVisibleValue); - } - - const [selectedIndex, setSelectedIndex] = useState([]); - - const columns = useMemo(() => { - return getterColumns(props.options, singleRef); - }, [props.options]); - - useEffect(() => { - selectIndexRef.current = null; - setSelectedIndex(getterSelectedIndex(columns, value, singleRef)); - }, [columns, value]); - - const formatValue = useMemo(() => { - if (typeof props.formattedValueText === 'string') { - return props.formattedValueText; - } - const formatValue = getterFormatText( - columns, - value, - props.onFormat, - singleRef - ); - return formatValue; - }, [props.formattedValueText, visible, columns, value, props.onFormat]); +Component( + PickerDefaultProps, + { + // visible受控判断 + isVisibleControlled() { + /// #if ALIPAY + return 'visible' in getValueFromProps(this); + /// #endif + /// #if WECHAT + return getValueFromProps(this, 'visible') !== null; + /// #endif + }, + initData() { + const [options, visible, defaultVisible] = getValueFromProps(this, [ + 'options', + 'visible', + 'defaultVisible', + ]); + const columns = this.getterColumns(options); + this.setData( + { + columns, + }, + () => { + const formatValue = this.getterFormatText(); + const selectedIndex = this.getterSelectedIndex(); + this.setData({ + formatValue, + selectedIndex, + visible: this.isVisibleControlled() ? visible : defaultVisible, + }); + } + ); + }, + getterColumns(options) { + let columns = []; + if (options.length > 0) { + if (options.every((item) => Array.isArray(item))) { + this.single = false; + columns = options.slice(); + } else { + this.single = true; + columns = [options]; + } + } + return columns; + }, + defaultFormat(value, column) { + if (Array.isArray(column)) { + return column + .filter((c) => c !== undefined) + .map(function (c) { + if (typeof c === 'object') { + return c.label; + } + return c; + }) + .join('-'); + } + return (column && column.label) || column || ''; + }, + getterFormatText() { + const [onFormat, formattedValueText] = getValueFromProps(this, [ + 'onFormat', + 'formattedValueText', + ]); + if (typeof formattedValueText === 'string') { + return formattedValueText; + } + const { columns } = this.data; + const realValue = this.getValue(); + const { matchedColumn } = getStrictMatchedItemByValue( + columns, + realValue, + this.single + ); + const formatValueByProps = onFormat && onFormat(realValue, matchedColumn); + if (formatValueByProps !== undefined && formatValueByProps !== null) { + return formatValueByProps; + } + return this.defaultFormat(realValue, matchedColumn); + }, + getterSelectedIndex() { + const selectedIndex = []; + const columns = this.data.columns; + const realValue = this.getValue(); + let value = realValue || []; + if (this.single) { + value = [realValue]; + } + for (let i = 0; i < columns.length; i++) { + const column = columns[i]; + const compareValue = value[i]; + if (compareValue === undefined || compareValue === null) { + selectedIndex[i] = 0; + } + let index = column.findIndex((c) => { + return c === compareValue || c.value === compareValue; + }); + if (index === -1) { + index = 0; + } + selectedIndex[i] = index; + } + return selectedIndex; + }, - useEvent('onOpen', () => { - if (props.disabled) { - return; - } - selectIndexRef.current = null; - const selectedIndex = getterSelectedIndex(columns, value, singleRef); - setSelectedIndex(selectedIndex); - triggerPicker(true); - }); + onOpen() { + const disabled = getValueFromProps(this, 'disabled'); + if (!disabled) { + this.tempSelectedIndex = null; + const selectedIndex = this.getterSelectedIndex(); + this.setData({ + selectedIndex, + }); + this.triggerPicker(true); + } + }, - useEvent('onCancel', () => { - triggerPicker(false); - triggerEventOnly('cancel', { detail: { type: 'cancel' } }); - }); + triggerPicker(visible) { + this.setData({ + visible, + }); + triggerEvent(this, 'visibleChange', visible); + }, - useEvent('onMaskDismiss', () => { - if (!props.maskClosable) { - return; - } - triggerPicker(false); - triggerEventOnly('cancel', { detail: { type: 'mask' } }); - }); + onMaskDismiss() { + const maskClosable = getValueFromProps(this, 'maskClosable'); + if (!maskClosable) { + return; + } + this.triggerPicker(false); + triggerEventOnly(this, 'cancel', { detail: { type: 'mask' } }); + }, - useEvent('onChange', (e) => { - const { value: selectedIndex } = e.detail; - const { matchedColumn, matchedValues } = getMatchedItemByIndex( - columns, - selectedIndex, - singleRef - ); - selectIndexRef.current = selectedIndex; - setSelectedIndex(selectedIndex); - triggerEventValues('change', [matchedValues, matchedColumn], e); - }); + onCancel() { + this.triggerPicker(false); + triggerEventOnly(this, 'cancel', { detail: { type: 'cancel' } }); + }, - useEvent('onOk', () => { - let result; - if (selectIndexRef.current) { - result = getMatchedItemByIndex( - columns, - selectIndexRef.current, - singleRef + onChange(e) { + const { value: selectedIndex } = e.detail; + this.tempSelectedIndex = selectedIndex; + this.isChangingPickerView = true; + const { matchedColumn, matchedValues } = getMatchedItemByIndex( + this.data.columns, + this.tempSelectedIndex, + this.single ); - } else { - result = getMatchedItemByValue(columns, value, singleRef); - } - - const { matchedColumn, matchedValues } = result; - - triggerPicker(false); - if (!isValueControlled) { - updateValue(matchedValues); - } - triggerEventValues('ok', [matchedValues, matchedColumn]); - }); - - return { - formatValue, - selectedIndex, - columns, - state: { - visible, - }, - mixin: { - value, - }, - }; -}; + this.setData({ + selectedIndex, + }); + triggerEventValues(this, 'change', [matchedValues, matchedColumn], e); + }, -mountComponent(Picker, PickerFunctionalProps); + async onOk() { + let result; + if (this.tempSelectedIndex) { + result = getMatchedItemByIndex( + this.data.columns, + this.tempSelectedIndex, + this.single + ); + } else { + result = getMatchedItemByValue( + this.data.columns, + this.getValue(), + this.single + ); + } + const { matchedColumn, matchedValues } = result; + this.triggerPicker(false); + if (!this.isControlled()) { + this.update(matchedValues); + } + triggerEventValues(this, 'ok', [matchedValues, matchedColumn]); + }, + }, + { + formatValue: '', + columns: [], + visible: null, + selectedIndex: [], + }, + [ + mixinValue({ + transformValue(value) { + return { + needUpdate: true, + value: value === undefined ? [] : value, + }; + }, + }), + ], + { + tempSelectedIndex: null, + single: false, + isChangingPickerView: false, + /// #if ALIPAY + onInit() { + this.initData(); + }, + didUpdate(prevProps) { + const options = getValueFromProps(this, 'options'); + if (!equal(options, prevProps.options)) { + const newColums = this.getterColumns(options); + this.setData( + { + columns: newColums, + }, + () => { + // 如果是在滚动过程中columns发生变化,以onChange里抛出的selectedIndex为准 + if (!this.isChangingPickerView) { + this.tempSelectedIndex = null; + const selectedIndex = this.getterSelectedIndex(); + this.setData({ + selectedIndex, + }); + } + } + ); + } + const value = getValueFromProps(this, 'value'); + if (!equal(prevProps.value, value)) { + const selectedIndex = this.getterSelectedIndex(); + this.tempSelectedIndex = null; + this.setData({ + selectedIndex, + }); + } + const visible = getValueFromProps(this, 'visible'); + if (!equal(prevProps.visible, visible)) { + this.setData({ visible }); + } + const formatValue = this.getterFormatText(); + const formattedValueText = getValueFromProps(this, 'formattedValueText'); + if ( + formatValue !== this.data.formatValue || + prevProps.formattedValueText !== formattedValueText + ) { + this.setData({ + formatValue, + }); + } + this.isChangingPickerView = false; + }, + /// #endif + /// #if WECHAT + created() { + this.initData(); + }, + observers: { + 'options': function () { + const options = getValueFromProps(this, 'options'); + const newColums = this.getterColumns(options); + this.setData( + { + columns: newColums, + }, + () => { + // 如果是在滚动过程中columns发生变化,以onChange里抛出的selectedIndex为准 + if (!this.isChangingPickerView) { + this.tempSelectedIndex = null; + const selectedIndex = this.getterSelectedIndex(); + this.setData({ + selectedIndex, + }); + } + this.isChangingPickerView = false; + } + ); + }, + 'value': function () { + const selectedIndex = this.getterSelectedIndex(); + this.tempSelectedIndex = null; + this.setData({ + selectedIndex, + }); + }, + 'visible': function () { + const visible = getValueFromProps(this, 'visible'); + if (this.data.visible !== visible) { + this.setData({ + visible, + }); + } + }, + 'formattedValueText': function () { + const formattedValueText = getValueFromProps( + this, + 'formattedValueText' + ); + this.setData({ + formatValue: formattedValueText, + }); + }, + '**': function () { + const formatValue = this.getterFormatText(); + if (formatValue !== this.data.formatValue) { + this.setData({ + formatValue, + }); + } + }, + }, + /// #endif + } +); diff --git a/src/Picker/props.ts b/src/Picker/props.ts index e5c75a091..3d2eab5a1 100644 --- a/src/Picker/props.ts +++ b/src/Picker/props.ts @@ -54,7 +54,7 @@ export interface IPickerProps extends IBaseProps { * @default '请选择' */ placeholder: string; - /** + /** * @description 空状态提示文案 * @default '暂无数据' */ @@ -131,17 +131,6 @@ export interface IPickerProps extends IBaseProps { } export const PickerDefaultProps: Partial = { - okText: '确定', - cancelText: '取消', - disabled: false, - maskClosable: false, - options: [], - placeholder: '请选择', - defaultValue: [], - emptyText: '暂无数据' -}; - -export const PickerFunctionalProps: Partial = { formattedValueText: null, visible: null, defaultVisible: null, @@ -158,5 +147,5 @@ export const PickerFunctionalProps: Partial = { popStyle: '', maskClosable: true, onFormat: null, - emptyText: '暂无数据' + emptyText: '暂无数据', }; diff --git a/src/Picker/utils.ts b/src/Picker/utils.ts index 9ec50878d..e3a9a1eb0 100644 --- a/src/Picker/utils.ts +++ b/src/Picker/utils.ts @@ -1,5 +1,3 @@ -import { PickerValue } from './props'; - function getColumnValue(columnItem) { if (typeof columnItem === 'object') return columnItem.value; return columnItem; @@ -14,7 +12,7 @@ export function getStrictMatchedItemByValue(columns, value, single) { let index = null; for (let i = 0; i < columns.length; i++) { const column = columns[i]; - const compareValue = value[i]; + const compareValue = (value || [])[i]; index = column.findIndex((c) => { const columnValue = getColumnValue(c); return columnValue === compareValue; @@ -29,8 +27,8 @@ export function getStrictMatchedItemByValue(columns, value, single) { } // 如果找不到value对应的item项目,返回第一项 -export function getMatchedItemByValue(columns, value, singleRef) { - if (singleRef.current) { +export function getMatchedItemByValue(columns, value, single) { + if (single) { value = [value]; } const matchedValues = []; @@ -38,7 +36,7 @@ export function getMatchedItemByValue(columns, value, singleRef) { let index = null; for (let i = 0; i < columns.length; i++) { const column = columns[i]; - const compareValue = value[i]; + const compareValue = (value || [])[i]; if (compareValue === undefined || compareValue === null) { index = 0; } else { @@ -54,8 +52,8 @@ export function getMatchedItemByValue(columns, value, singleRef) { matchedValues[i] = getColumnValue(column[index]); } return { - matchedColumn: singleRef.current ? matchedColumn[0] : matchedColumn, - matchedValues: singleRef.current ? matchedValues[0] : matchedValues, + matchedColumn: single ? matchedColumn[0] : matchedColumn, + matchedValues: single ? matchedValues[0] : matchedValues, }; } @@ -84,75 +82,7 @@ export function getMatchedItemByIndex(columns, selectedIndex, single) { } return { - matchedColumn: single.current ? matchedColumn[0] : matchedColumn, - matchedValues: single.current ? matchedValues[0] : matchedValues, + matchedColumn: single ? matchedColumn[0] : matchedColumn, + matchedValues: single ? matchedValues[0] : matchedValues, }; } - -export function getterColumns(options: PickerValue[], singleRef) { - let columns = []; - if (options.length > 0) { - if (options.every((item) => Array.isArray(item))) { - singleRef.current = false; - columns = options.slice(); - } else { - singleRef.current = true; - columns = [options]; - } - } - return columns; -} - -export function defaultFormat(value, column) { - if (Array.isArray(column)) { - return column - .filter((c) => c !== undefined) - .map(function (c) { - if (typeof c === 'object') { - return c.label; - } - return c; - }) - .join('-'); - } - return (column && column.label) || column || ''; -} - -export function getterFormatText(columns, realValue, onFormat, singleRef) { - const { matchedColumn } = getStrictMatchedItemByValue( - columns, - realValue, - singleRef.current - ); - - if (typeof onFormat === 'function') { - const formatValueByProps = onFormat(realValue, matchedColumn); - if (formatValueByProps !== undefined) { - return formatValueByProps; - } - } - return defaultFormat(realValue, matchedColumn); -} - -export function getterSelectedIndex(columns, realValue, sinefileRef) { - const selectedIndex = []; - let value = realValue || []; - if (sinefileRef.current) { - value = [realValue]; - } - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - const compareValue = value[i]; - if (compareValue === undefined || compareValue === null) { - selectedIndex[i] = 0; - } - let index = column.findIndex((c) => { - return c === compareValue || c.value === compareValue; - }); - if (index === -1) { - index = 0; - } - selectedIndex[i] = index; - } - return selectedIndex; -} diff --git a/tests/alipay/Picker/__tests__/index.test.ts b/tests/alipay/Picker/__tests__/index.test.ts index 0af8acb06..00de50d84 100644 --- a/tests/alipay/Picker/__tests__/index.test.ts +++ b/tests/alipay/Picker/__tests__/index.test.ts @@ -19,11 +19,11 @@ describe('picker onVisibleChange', () => { instance.callMethod('onOpen'); await sleep(20); - expect(instance.getData().state.visible).toBeTruthy(); + expect(instance.getData().visible).toBeTruthy(); instance.setProps({ maskClosable: false }); instance.callMethod('onMaskDismiss'); await sleep(20); - expect(instance.getData().state.visible).toBeTruthy(); + expect(instance.getData().visible).toBeTruthy(); }); it('onCancel', () => { @@ -237,19 +237,19 @@ it('假设在滚动的时候, value 变化', async () => { it('多次开启关闭, visible 状态应该正确', async () => { const { instance, callMethod } = createPicker(); await callMethod('onOpen'); - expect(instance.getData().state.visible).toBe(true); + expect(instance.getData().visible).toBe(true); await callMethod('onOk'); - expect(instance.getData().state.visible).toBe(false); + expect(instance.getData().visible).toBe(false); await callMethod('onOpen'); - expect(instance.getData().state.visible).toBe(true); + expect(instance.getData().visible).toBe(true); await callMethod('onOk'); - expect(instance.getData().state.visible).toBe(false); + expect(instance.getData().visible).toBe(false); }); it('如果 disabled, 则无法打开', async () => { const { instance, callMethod } = createPicker({ disabled: true }); await callMethod('onOpen'); - expect(instance.getData().state.visible).toBe(undefined); + expect(instance.getData().visible).toBe(undefined); }); describe('非受控模式', () => { @@ -259,12 +259,12 @@ describe('非受控模式', () => { options, }); await callMethod('onOpen'); - expect(instance.getData().state.visible).toBe(true); + expect(instance.getData().visible).toBe(true); await callMethod('onChange', { detail: { value: [1] } }); expect(instance.getData().selectedIndex).toStrictEqual([1]); expect(instance.getData().mixin.value).toStrictEqual([]); await callMethod('onOk'); - expect(instance.getData().state.visible).toBe(false); + expect(instance.getData().visible).toBe(false); expect(instance.getData().mixin.value).toStrictEqual(['上海']); }); @@ -276,10 +276,10 @@ describe('非受控模式', () => { defaultVisible: true, 'data-1': 2, }); - expect(instance.getData().state.visible).toBe(true); + expect(instance.getData().visible).toBe(true); expect(instance.getData().selectedIndex).toEqual([1]); await callMethod('onOk'); - expect(instance.getData().state.visible).toBe(false); + expect(instance.getData().visible).toBe(false); expect(onOk).toBeCalledWith( ['上海'], ['上海'], @@ -298,9 +298,9 @@ describe('visible 受控模式', () => { visible: false, defaultVisible: true, }); - expect(instance.getData().state.visible).toEqual(false); + expect(instance.getData().visible).toEqual(false); await callMethod('onOpen'); - expect(instance.getData().state.visible).toEqual(false); + expect(instance.getData().visible).toEqual(true); expect(onVisibleChange).toBeCalledWith(true, fmtEvent({})); }); });