refactor: carousel by ts

pull/2992/head
tangjinzhou 4 years ago
parent 93b64061db
commit 90059e6b45

@ -1,17 +1,17 @@
import { inject } from 'vue';
import { App, defineComponent, inject } from 'vue';
import PropTypes from '../_util/vue-types';
import debounce from 'lodash-es/debounce';
import hasProp, { initDefaultProps, getComponent } from '../_util/props-util';
import hasProp, { getComponent } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider';
import warning from '../_util/warning';
import classNames from '../_util/classNames';
import SlickCarousel from '../vc-slick/src';
import { tuple } from '../_util/type';
export const CarouselEffect = PropTypes.oneOf(['scrollx', 'fade']);
// Carousel
export const CarouselProps = {
effect: CarouselEffect,
dots: PropTypes.looseBool,
effect: PropTypes.oneOf(tuple('scrollx', 'fade')),
dots: PropTypes.looseBool.def(true),
vertical: PropTypes.looseBool,
autoplay: PropTypes.looseBool,
easing: PropTypes.string,
@ -20,18 +20,18 @@ export const CarouselProps = {
// style: PropTypes.React.CSSProperties,
prefixCls: PropTypes.string,
accessibility: PropTypes.looseBool,
nextArrow: PropTypes.any,
prevArrow: PropTypes.any,
nextArrow: PropTypes.VNodeChild,
prevArrow: PropTypes.VNodeChild,
pauseOnHover: PropTypes.looseBool,
// className: PropTypes.string,
adaptiveHeight: PropTypes.looseBool,
arrows: PropTypes.looseBool,
arrows: PropTypes.looseBool.def(false),
autoplaySpeed: PropTypes.number,
centerMode: PropTypes.looseBool,
centerPadding: PropTypes.string,
cssEase: PropTypes.string,
dotsClass: PropTypes.string,
draggable: PropTypes.looseBool,
draggable: PropTypes.looseBool.def(false),
fade: PropTypes.looseBool,
focusOnSelect: PropTypes.looseBool,
infinite: PropTypes.looseBool,
@ -50,20 +50,18 @@ export const CarouselProps = {
useCSS: PropTypes.looseBool,
slickGoTo: PropTypes.number,
responsive: PropTypes.array,
dotPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
dotPosition: PropTypes.oneOf(tuple('top', 'bottom', 'left', 'right')),
};
const Carousel = {
const Carousel = defineComponent({
name: 'ACarousel',
inheritAttrs: false,
props: initDefaultProps(CarouselProps, {
dots: true,
arrows: false,
draggable: false,
}),
props: CarouselProps,
setup() {
return {
configProvider: inject('configProvider', defaultConfigProvider),
slick: undefined,
innerSlider: undefined,
};
},
beforeMount() {
@ -90,7 +88,7 @@ const Carousel = {
const { autoplay } = this;
if (autoplay) {
window.removeEventListener('resize', this.onWindowResized);
this.onWindowResized.cancel();
(this.onWindowResized as any).cancel();
}
},
methods: {
@ -103,7 +101,7 @@ const Carousel = {
}
return 'bottom';
},
saveSlick(node) {
saveSlick(node: HTMLElement) {
this.slick = node;
},
onWindowResized() {
@ -122,7 +120,7 @@ const Carousel = {
this.slick.slickPrev();
},
goTo(slide, dontAnimate = false) {
goTo(slide: number, dontAnimate = false) {
this.slick.slickGoTo(slide, dontAnimate);
},
},
@ -134,7 +132,7 @@ const Carousel = {
if (props.effect === 'fade') {
props.fade = true;
}
const { class: cls, style, ...restAttrs } = this.$attrs;
const { class: cls, style, ...restAttrs } = this.$attrs as any;
const getPrefixCls = this.configProvider.getPrefixCls;
let className = getPrefixCls('carousel', props.prefixCls);
const dotsClass = 'slick-dots';
@ -156,14 +154,18 @@ const Carousel = {
};
return (
<div class={className} style={style}>
<SlickCarousel ref={this.saveSlick} {...SlickCarouselProps} vSlots={$slots}></SlickCarousel>
<SlickCarousel
ref={this.saveSlick}
{...SlickCarouselProps}
v-slots={$slots}
></SlickCarousel>
</div>
);
},
};
});
/* istanbul ignore next */
Carousel.install = function(app) {
Carousel.install = function(app: App) {
app.component(Carousel.name, Carousel);
return app;
};

@ -1,4 +1,4 @@
import { inject, provide } from 'vue';
import { App, defineComponent, inject, provide, PropType } from 'vue';
import PropTypes, { withUndefined } from '../_util/vue-types';
import VcCascader from '../vc-cascader';
import arrayTreeFilter from 'array-tree-filter';
@ -23,35 +23,74 @@ import BaseMixin from '../_util/BaseMixin';
import { cloneElement } from '../_util/vnode';
import warning from '../_util/warning';
import { defaultConfigProvider } from '../config-provider';
import { tuple, VueNode } from 'components/_util/type';
export interface CascaderOptionType {
value?: string | number;
label?: VueNode;
disabled?: boolean;
isLeaf?: boolean;
loading?: boolean;
children?: Array<CascaderOptionType>;
[key: string]: any;
}
export interface FieldNamesType {
value?: string;
label?: string;
children?: string;
}
export interface FilledFieldNamesType {
value: string;
label: string;
children: string;
}
const CascaderOptionType = PropTypes.shape({
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
label: PropTypes.any,
disabled: PropTypes.looseBool,
children: PropTypes.array,
key: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
}).loose;
const FieldNamesType = PropTypes.shape({
value: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
children: PropTypes.string,
}).loose;
const CascaderExpandTrigger = PropTypes.oneOf(['click', 'hover']);
const ShowSearchType = PropTypes.shape({
filter: PropTypes.func,
render: PropTypes.func,
sort: PropTypes.func,
matchInputWidth: PropTypes.looseBool,
limit: withUndefined(PropTypes.oneOfType([Boolean, Number])),
}).loose;
// const CascaderOptionType = PropTypes.shape({
// value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
// label: PropTypes.any,
// disabled: PropTypes.looseBool,
// children: PropTypes.array,
// key: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
// }).loose;
// const FieldNamesType = PropTypes.shape({
// value: PropTypes.string.isRequired,
// label: PropTypes.string.isRequired,
// children: PropTypes.string,
// }).loose;
export interface ShowSearchType {
filter?: (inputValue: string, path: CascaderOptionType[], names: FilledFieldNamesType) => boolean;
render?: (
inputValue: string,
path: CascaderOptionType[],
prefixCls: string | undefined,
names: FilledFieldNamesType,
) => VueNode;
sort?: (
a: CascaderOptionType[],
b: CascaderOptionType[],
inputValue: string,
names: FilledFieldNamesType,
) => number;
matchInputWidth?: boolean;
limit?: number | false;
}
// const ShowSearchType = PropTypes.shape({
// filter: PropTypes.func,
// render: PropTypes.func,
// sort: PropTypes.func,
// matchInputWidth: PropTypes.looseBool,
// limit: withUndefined(PropTypes.oneOfType([Boolean, Number])),
// }).loose;
function noop() {}
const CascaderProps = {
/** 可选项数据源 */
options: PropTypes.arrayOf(CascaderOptionType).def([]),
options: { type: Array as PropType<CascaderOptionType>, default: [] },
/** 默认的选中项 */
defaultValue: PropTypes.array,
/** 指定选中项 */
@ -65,22 +104,25 @@ const CascaderProps = {
/** 自定义浮层类名 */
popupClassName: PropTypes.string,
/** 浮层预设位置:`bottomLeft` `bottomRight` `topLeft` `topRight` */
popupPlacement: PropTypes.oneOf(['bottomLeft', 'bottomRight', 'topLeft', 'topRight']).def(
popupPlacement: PropTypes.oneOf(tuple('bottomLeft', 'bottomRight', 'topLeft', 'topRight')).def(
'bottomLeft',
),
/** 输入框占位文本*/
placeholder: PropTypes.string.def('Please select'),
/** 输入框大小,可选 `large` `default` `small` */
size: PropTypes.oneOf(['large', 'default', 'small']),
size: PropTypes.oneOf(tuple('large', 'default', 'small')),
/** 禁用*/
disabled: PropTypes.looseBool.def(false),
/** 是否支持清除*/
allowClear: PropTypes.looseBool.def(true),
showSearch: withUndefined(PropTypes.oneOfType([Boolean, ShowSearchType])),
notFoundContent: PropTypes.any,
showSearch: {
type: [Boolean, Object] as PropType<ShowSearchType>,
default: undefined,
},
notFoundContent: PropTypes.VNodeChild,
loadData: PropTypes.func,
/** 次级菜单的展开方式,可选 'click' 和 'hover' */
expandTrigger: CascaderExpandTrigger,
expandTrigger: PropTypes.oneOf(tuple('click', 'hover')),
/** 当此项为 true 时,点选每级菜单选项值都会发生变化 */
changeOnSelect: PropTypes.looseBool,
/** 浮层可见变化时回调 */
@ -89,9 +131,9 @@ const CascaderProps = {
inputPrefixCls: PropTypes.string,
getPopupContainer: PropTypes.func,
popupVisible: PropTypes.looseBool,
fieldNames: FieldNamesType,
fieldNames: { type: Object as PropType<FieldNamesType> },
autofocus: PropTypes.looseBool,
suffixIcon: PropTypes.any,
suffixIcon: PropTypes.VNodeChild,
showSearchRender: PropTypes.any,
onChange: PropTypes.func,
onPopupVisibleChange: PropTypes.func,
@ -101,14 +143,25 @@ const CascaderProps = {
'onUpdate:value': PropTypes.func,
};
type CascaderPropsTypes = typeof CascaderProps;
// We limit the filtered item count by default
const defaultLimit = 50;
function defaultFilterOption(inputValue, path, names) {
function defaultFilterOption(
inputValue: string,
path: CascaderOptionType[],
names: FilledFieldNamesType,
) {
return path.some(option => option[names.label].indexOf(inputValue) > -1);
}
function defaultSortFilteredOption(a, b, inputValue, names) {
function defaultSortFilteredOption(
a: CascaderOptionType[],
b: CascaderOptionType[],
inputValue: string,
names: FilledFieldNamesType,
) {
function callback(elem) {
return elem[names.label].indexOf(inputValue) > -1;
}
@ -116,8 +169,9 @@ function defaultSortFilteredOption(a, b, inputValue, names) {
return a.findIndex(callback) - b.findIndex(callback);
}
function getFilledFieldNames({ fieldNames = {} }) {
const names = {
function getFilledFieldNames(props: CascaderPropsTypes) {
const fieldNames = (props.fieldNames || {}) as FieldNamesType;
const names: FilledFieldNamesType = {
children: fieldNames.children || 'children',
label: fieldNames.label || 'label',
value: fieldNames.value || 'value',
@ -125,8 +179,12 @@ function getFilledFieldNames({ fieldNames = {} }) {
return names;
}
function flattenTree(options = [], props, ancestor = []) {
const names = getFilledFieldNames(props);
function flattenTree(
options: CascaderOptionType[],
props: CascaderPropsTypes,
ancestor: CascaderOptionType[] = [],
) {
const names: FilledFieldNamesType = getFilledFieldNames(props);
let flattenOptions = [];
const childrenName = names.children;
options.forEach(option => {
@ -163,7 +221,7 @@ const Cascader = {
},
data() {
this.cachedOptions = [];
const { value, defaultValue, popupVisible, showSearch, options } = this;
const { value, defaultValue, popupVisible, showSearch, options } = this.$props;
return {
sValue: value || defaultValue || [],
inputValue: '',
@ -553,7 +611,7 @@ const Cascader = {
},
};
Cascader.install = function(app) {
Cascader.install = function(app: App) {
app.component(Cascader.name, Cascader);
return app;
};
Loading…
Cancel
Save