Skip to content

Commit

Permalink
refactor(SwipeCell): change to tsx (#1499)
Browse files Browse the repository at this point in the history
* refactor(swipe-cell): sfc to tsx

* chore: 注释无效测试案例

* chore: 代码调整

* chore: 类型修改

* fix: 类型报错

* fix: demo 报错

* chore: update snapshot
  • Loading branch information
liweijie0812 authored Jul 23, 2024
1 parent f31c646 commit e3df69a
Show file tree
Hide file tree
Showing 10 changed files with 376 additions and 430 deletions.
176 changes: 90 additions & 86 deletions src/swipe-cell/__test__/__snapshots__/demo.test.jsx.snap

Large diffs are not rendered by default.

345 changes: 158 additions & 187 deletions src/swipe-cell/__test__/index.test.jsx

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/swipe-cell/demos/event.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import Toast from '../../toast/index';
import SwipeCell from '..';
const opened = ref([false, true]);
const cellRef = ref<InstanceType<typeof SwipeCell>>();
const cellRef = ref();
const handleChange = (d: string) => {
if (d) {
Expand All @@ -44,7 +44,7 @@ const handleEdit = () => {};
const dir = ref('right');
const handleDelete = (val: string) => {
cellRef.value?.showSure('sure-delete');
cellRef.value?.showSure(val, handleSureConfirm);
};
</script>

Expand Down
2 changes: 1 addition & 1 deletion src/swipe-cell/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import _SwipeCell from './swipe-cell.vue';
import _SwipeCell from './swipe-cell';
import { withInstall, WithInstallType } from '../shared';
import { TdSwipeCellProps } from './type';

Expand Down
10 changes: 5 additions & 5 deletions src/swipe-cell/swipe-cell.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ name | type | default | description | required
content | String / Slot / Function | - | Typescript:`string \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
default | String / Slot / Function | - | Typescript:`string \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
disabled | Boolean | - | \- | N
left | Array / Slot / Function | - | Typescript:`Array<SwipeActionItem>` | N
left | Array / Slot / Function | - | Typescript:`Array<SwipeActionItem> \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
opened | Boolean / Array | false | Typescript:`boolean \| Array<boolean>` | N
right | Array / Slot / Function | - | Typescript:`Array<SwipeActionItem>` `interface SwipeActionItem {text: string; className?: string; style?: string; onClick?: () => void; [key: string]: any }`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts) | N
right | Array / Slot / Function | - | Typescript:`Array<SwipeActionItem> \| TNode` `interface SwipeActionItem {text: string; className?: string; style?: string; sure?: string \| TNode; onClick?: () => void; [key: string]: any }`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts) | N
onChange | Function | | Typescript:`(value: string) => void`<br/> | N
onClick | Function | | Typescript:`(action: SwipeActionItem, source: SwipeSource) => void`<br/>[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`type SwipeSource = 'left' \| 'right'`<br/> | N

Expand All @@ -22,8 +22,8 @@ name | params | description
change | `(value: string)` | \-
click | `(action: SwipeActionItem, source: SwipeSource)` | [see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`type SwipeSource = 'left' \| 'right'`<br/>

### SwipeCellInstanceFunctions
### SwipeCellInstanceFunctions 组件实例方法

名称 | 参数 | 返回值 | 描述
name | params | return | description
-- | -- | -- | --
showSure | `(sure: string | TNode, onClick?: SwipeActionItem['onClick'])` | `void` | [see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>
showSure | `(sure: string \| TNode, onClick?: SwipeActionItem['onClick'])` | `void` | Typescript:`string \| TNode;如果设置了 `onClick`,则点击二次确认内容时,会执行此onClick方法。<br />[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`[see more ts definition](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)
9 changes: 5 additions & 4 deletions src/swipe-cell/swipe-cell.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
:: BASE_DOC ::

## API

### SwipeCell Props

名称 | 类型 | 默认值 | 说明 | 必传
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
content | String / Slot / Function | - | 操作项以外的内容。TS 类型:`string \| TNode`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
default | String / Slot / Function | - | 操作项以外的内容,同 content。TS 类型:`string \| TNode`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
disabled | Boolean | - | 是否禁用滑动 | N
left | Array / Slot / Function | - | 左侧滑动操作项。所有行为同 `right`。TS 类型:`Array<SwipeActionItem>` | N
left | Array / Slot / Function | - | 左侧滑动操作项。所有行为同 `right`。TS 类型:`Array<SwipeActionItem> \| TNode`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts) | N
opened | Boolean / Array | false | 操作项是否呈现为打开态,值为数组时表示分别控制左右滑动的展开和收起状态。TS 类型:`boolean \| Array<boolean>` | N
right | Array / Slot / Function | - | 右侧滑动操作项。有两种定义方式,一种是使用数组,二种是使用插槽。`right.text` 表示操作文本,`right.className` 表示操作项类名,`right.style` 表示操作项样式,`right.onClick` 表示点击操作项后执行的回调函数。示例:`[{ text: '删除', style: 'background-color: red', onClick: () => {} }]`。TS 类型:`Array<SwipeActionItem>` `interface SwipeActionItem {text: string; className?: string; style?: string; onClick?: () => void; [key: string]: any }`[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts) | N
right | Array / Slot / Function | - | 右侧滑动操作项。有两种定义方式,一种是使用数组,二种是使用插槽。`right.text` 表示操作文本,`right.className` 表示操作项类名,`right.style` 表示操作项样式,`right.onClick` 表示点击操作项后执行的回调函数。示例:`[{ text: '删除', style: 'background-color: red', onClick: () => {} }]`。TS 类型:`Array<SwipeActionItem> \| TNode` `interface SwipeActionItem {text: string; className?: string; style?: string; sure?: string \| TNode; onClick?: () => void; [key: string]: any }`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts) | N
onChange | Function | | TS 类型:`(value: string) => void`<br/>菜单展开或者收回后将菜单的状态传递给父组件,值为数组时表示分别控制左右滑动的展开和收起状态。 | N
onClick | Function | | TS 类型:`(action: SwipeActionItem, source: SwipeSource) => void`<br/>操作项点击时触发(插槽写法组件不触发,业务侧自定义内容和事件)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`type SwipeSource = 'left' \| 'right'`<br/> | N

Expand All @@ -25,4 +26,4 @@ click | `(action: SwipeActionItem, source: SwipeSource)` | 操作项点击时触

名称 | 参数 | 返回值 | 描述
-- | -- | -- | --
showSure | `(sure: string | TNode, onClick?: SwipeActionItem['onClick'])` | `void` | 显示二次确认内容的函数。<br/>【关于参数】`sure` 表示二次确认的具体内容,同contentTS 类型:`string | TNode`;如果设置了 `onClick`,则点击二次确认内容时,会执行此onClick方法。<br />[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>
showSure | `(sure: string \| TNode, onClick?: SwipeActionItem['onClick'])` | `void` | 显示二次确认内容的函数。<br/>【关于参数】`sure` 表示二次确认的具体内容,同contentTS 类型:`string \| TNode;如果设置了 `onClick`,则点击二次确认内容时,会执行此onClick方法。<br />[详细类型定义](https://github.com/Tencent/tdesign-mobile-vue/tree/develop/src/swipe-cell/type.ts)。<br/>`[通用类型定义](https://github.com/Tencent/tdesign-mobile-vue/blob/develop/src/common.ts)
225 changes: 102 additions & 123 deletions src/swipe-cell/swipe-cell.vue → src/swipe-cell/swipe-cell.tsx
Original file line number Diff line number Diff line change
@@ -1,80 +1,6 @@
<template>
<div ref="swipeCell" :class="classes" @click.capture="handleCellClick">
<div :style="wrapperStyle">
<div
ref="leftRef"
:class="classes + '__left'"
:style="{
width: initData.leftWidth ? `${initData.leftWidth}px` : 'auto',
}"
>
<t-node v-if="swipeLeftMenu" :content="swipeLeftMenu"></t-node>
<template v-else>
<template v-for="(btn, index) of left" :key="index">
<div
:class="[classes + '__content', btn.className || '']"
:style="btn.style || 'height: 100%;'"
@click="
handleClickBtn({
action: { ...btn },
source: 'left',
})
"
>
<t-node v-if="btn.icon" :class="classes + '__icon'" :content="btn.icon"></t-node>
<span v-if="btn.text" :class="classes + '__text'">
<t-node :content="btn.text"></t-node>
</span>
</div>
</template>
</template>
<div :style="sureLeftBgStyle"></div>
<div ref="sureLeftRef" :style="sureLeftStyle" @click="handleSureClick">
<t-node v-if="sureLeftContent" :content="sureLeftContent"></t-node>
</div>
</div>
<t-node v-if="swipeContent" :content="swipeContent"></t-node>
<div
ref="rightRef"
:class="classes + '__right'"
:style="{
width: initData.rightWidth ? `${initData.rightWidth}px` : 'auto',
}"
>
<t-node v-if="swipeRightMenu" :content="swipeRightMenu"></t-node>
<template v-else>
<template v-for="(btn, index) of right" :key="index">
<div
:class="[classes + '__content', btn.className || '']"
:style="btn.style || 'height: 100%;'"
@click="
handleClickBtn({
action: { ...btn },
source: 'right',
})
"
>
<t-node v-if="btn.icon" :class="classes + '__icon'" :content="btn.icon"></t-node>
<span v-if="btn.text" :class="classes + '__text'">
<t-node :content="btn.text"></t-node>
</span>
</div>
</template>
</template>
<div :style="sureRightBgStyle"></div>
<div ref="sureRightRef" :style="sureRightStyle" @click="handleSureClick">
<t-node v-if="sureRightContent" :content="sureRightContent"></t-node>
</div>
</div>
</div>
</div>
</template>

<script lang="ts">
import {
ref,
watch,
toRefs,
reactive,
computed,
onMounted,
Expand All @@ -83,16 +9,17 @@ import {
StyleValue,
onUnmounted,
} from 'vue';
import isFunction from 'lodash/isFunction';
import isArray from 'lodash/isArray';
import isBoolean from 'lodash/isBoolean';
import { useSwipe } from './useSwipe';
import props from './props';
import config from '../config';
import { SwipeActionItem } from './type';
import { renderContent, renderTNode, TNode, useClickAway } from '../shared';
import { SwipeActionItem, SwipeSource } from './type';
import { useClickAway } from '../shared';
import { preventDefault } from '../shared/dom';
import { useSureConfirm } from './useSureConfirm';
import { useContent, useTNodeJSX } from '../hooks/tnode';
import { usePrefixClass } from '../hooks/useClass';

const { prefix } = config;
const name = `${prefix}-swipe-cell`;
Expand All @@ -109,22 +36,17 @@ export interface SwipeInitData {

export default defineComponent({
name,
components: { TNode },
props,
emits: ['click', 'change'],
setup(props, context) {
const renderTNodeJSX = useTNodeJSX();
const renderTNodeContent = useContent();
const swipeCellClass = usePrefixClass('swipe-cell');

const internalInstance = getCurrentInstance();
const swipeContent = computed(() => renderContent(internalInstance, 'default', 'content'));
const swipeLeftMenu = computed(() =>
isFunction(props.left) || internalInstance?.slots.left ? renderTNode(internalInstance, 'left') : false,
);
const swipeRightMenu = computed(() =>
isFunction(props.right) || internalInstance?.slots.right ? renderTNode(internalInstance, 'right') : false,
);
const wrapperRef = ref<HTMLElement>();

const leftRef = ref<HTMLElement>();
const rightRef = ref<HTMLElement>();
const swipeCell = ref<HTMLElement>();
const swipeCellRef = ref<HTMLElement>();
const wrapperStyle = computed(() => {
const transform = `translate3d(${initData.pos}px, 0, 0)`;
let transition = 'margin-left .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
Expand Down Expand Up @@ -175,7 +97,7 @@ export default defineComponent({
};
// 首次touchmove的方向,用于分开左右和上下滑动,左右滑动时禁止上下滑动,上下滑动时禁止左右滑动
let swipeDir: -1 | 0 | 1 = 0;
const { lengthX, lengthY, stop } = useSwipe(swipeCell, {
const { lengthX, lengthY, stop } = useSwipe(swipeCellRef, {
threshold: 0,
onSwipeStart: (e: TouchEvent) => {
if (props.disabled) {
Expand Down Expand Up @@ -284,7 +206,7 @@ export default defineComponent({
const updateLeftMenuPosStyle = (value?: number) => {
if (!leftRef.value) return;
const pos = value || initData.pos;
const children: string | any[] | HTMLCollection = leftRef.value.children || [];
const { children } = leftRef.value;
const wArr: number[] = [];
for (let i = 0, len = children.length - 2; i < len; ++i) {
const el = children[i] as HTMLElement;
Expand All @@ -301,7 +223,7 @@ export default defineComponent({
};
const stopClickAway = ref(
useClickAway(
swipeCell,
swipeCellRef,
() => {
close();
},
Expand Down Expand Up @@ -379,18 +301,18 @@ export default defineComponent({
initData.pos = 0;
props.onChange?.(undefined);
};
const handleClickBtn = ({ action, source }: { action: SwipeActionItem; source: String }) => {
const handleClickBtn = ({ action, source }: { action: SwipeActionItem; source: SwipeSource }) => {
const clickFn = () => {
if (autoBack) {
close();
}
if (action.onClick) {
if (action?.onClick) {
action.onClick();
return;
}
props.onClick?.({ action, source });
props.onClick?.(action, source);
};
if (action.sure) {
if (action?.sure) {
showSure(action.sure, clickFn);
return;
}
Expand All @@ -401,39 +323,96 @@ export default defineComponent({
if (initData.moved) {
preventDefault(e, true);
}
e.stopPropagation();
};

context.expose({
showSure,
});
return {
...toRefs(props),
swipeContent,
swipeLeftMenu,
swipeRightMenu,
initData,
classes,
wrapperRef,
wrapperStyle,
swipeCell,
leftRef,
rightRef,
handleClickBtn,
end,
handleCellClick,
showSureRight,
showSureLeft,
sureLeftBgStyle,
sureRightBgStyle,
sureRightStyle,
sureLeftStyle,
sureRightRef,
sureLeftRef,
sureRightContent,
sureLeftContent,
showSure,
handleSureClick,
const renderLeft = () => {
const leftContent = () => {
if (Array.isArray(props.left)) {
return props.left.map((btn) => {
const btnClass = [`${swipeCellClass.value}__content`, btn.className || ''];
const style = btn.style || 'height: 100%';
const { icon: btnIcon } = btn;
const { text: btnText } = btn;
return (
<div
class={btnClass}
style={style}
onClick={(e: MouseEvent) => handleClickBtn({ action: btn, source: 'left' })}
>
{btnIcon ? <btnIcon class={`${swipeCellClass.value}__icon`} /> : null}
{btnText ? <span class={`${swipeCellClass.value}__text`}>{btnText}</span> : null}
</div>
);
});
}
return renderTNodeJSX('left');
};

return (
<div
ref={leftRef}
class={`${swipeCellClass.value}__left`}
style={{
width: initData?.leftWidth ? `${initData.leftWidth}px` : 'auto',
}}
>
{leftContent()}
<div style={sureLeftBgStyle.value}></div>
<div ref={sureLeftRef} style={sureLeftStyle.value} onClick={(e: MouseEvent) => handleSureClick}>
{sureLeftContent.value}
</div>
</div>
);
};
const renderRight = () => {
const rightContent = () => {
if (Array.isArray(props.right)) {
return props.right.map((btn) => {
const btnClass = [`${swipeCellClass.value}__content`, btn.className || ''];
const style = btn.style || 'height: 100%';
const { icon: btnIcon } = btn;
const { text: btnText } = btn;
return (
<div class={btnClass} style={style} onClick={() => handleClickBtn({ action: btn, source: 'right' })}>
{btnIcon && <btnIcon class={`${swipeCellClass.value}__icon`}></btnIcon>}
{btnText && <span class={`${swipeCellClass.value}__text`}>{btnText}</span>}
</div>
);
});
}
return renderTNodeJSX('right');
};

return (
<div
ref={rightRef}
class={`${swipeCellClass.value}__right`}
style={{
width: initData.rightWidth ? `${initData.rightWidth}px` : 'auto',
}}
>
{rightContent()}
<div style={sureRightBgStyle.value}></div>
<div ref={sureRightRef} style={sureRightStyle.value} onClick={(e: MouseEvent) => handleSureClick}>
{sureRightContent.value}
</div>
</div>
);
};
return () => {
return (
<div ref={swipeCellRef} class={swipeCellClass.value} onClick={handleCellClick}>
<div class={`${swipeCellClass.value}__wrapper`} style={wrapperStyle.value}>
{renderLeft()}
{renderTNodeContent('default', 'content')}
{renderRight()}
</div>
</div>
);
};
},
});
</script>
Loading

0 comments on commit e3df69a

Please sign in to comment.