介绍
可以左右滑动来展示操作按钮。
代码演示
基础使用
使用 left、right 插槽向左右两边添加操作按钮。
插槽接收 hide 方法来隐藏操作按钮。
vue
<template>
<s-list card>
<s-list-item style="padding: 1px 0 0 0">
<s-swipe-action>
<s-list-item title="右边插槽" value="内容" />
<template #right="{ hide }">
<s-button color="danger" square auto-height @click="onClick('删除', hide)">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消', hide)">
取消
</s-button>
</template>
</s-swipe-action>
</s-list-item>
<s-list-item style="padding: 1px 0 0">
<s-swipe-action>
<s-list-item title="左边插槽" value="内容" />
<template #left="{ hide }">
<s-button color="danger" square auto-height @click="onClick('点赞', hide)">点赞</s-button>
<s-button color="primary" square auto-height @click="onClick('分享', hide)">
分享
</s-button>
<s-button color="warning" square auto-height @click="onClick('收藏', hide)">
收藏
</s-button>
</template>
</s-swipe-action>
</s-list-item>
<s-list-item style="padding: 1px 0 0">
<s-swipe-action>
<s-list-item title="两边插槽" value="内容" />
<template #left="{ hide }">
<s-button color="danger" square auto-height @click="onClick('点赞', hide)">点赞</s-button>
<s-button color="primary" square auto-height @click="onClick('分享', hide)">
分享
</s-button>
<s-button color="warning" square auto-height @click="onClick('收藏', hide)">
收藏
</s-button>
</template>
<template #right="{ hide }">
<s-button color="danger" square auto-height @click="onClick('删除', hide)">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消', hide)">
取消
</s-button>
</template>
</s-swipe-action>
</s-list-item>
</s-list>
</template>
<script setup lang="ts">
import { toast } from 'sard'
const onClick = (content: string, hide: () => void) => {
toast(`点击了${content}`)
hide()
}
</script>vue
<template>
<s-list card>
<s-list-item style="padding: 1px 0 0 0">
<s-swipe-action>
<s-list-item title="右边插槽" value="内容" />
<template #right="{ hide }">
<s-button color="danger" square auto-height @click="onClick('删除', hide)">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消', hide)">
取消
</s-button>
</template>
</s-swipe-action>
</s-list-item>
<s-list-item style="padding: 1px 0 0">
<s-swipe-action>
<s-list-item title="左边插槽" value="内容" />
<template #left="{ hide }">
<s-button color="danger" square auto-height @click="onClick('点赞', hide)">点赞</s-button>
<s-button color="primary" square auto-height @click="onClick('分享', hide)">
分享
</s-button>
<s-button color="warning" square auto-height @click="onClick('收藏', hide)">
收藏
</s-button>
</template>
</s-swipe-action>
</s-list-item>
<s-list-item style="padding: 1px 0 0">
<s-swipe-action>
<s-list-item title="两边插槽" value="内容" />
<template #left="{ hide }">
<s-button color="danger" square auto-height @click="onClick('点赞', hide)">点赞</s-button>
<s-button color="primary" square auto-height @click="onClick('分享', hide)">
分享
</s-button>
<s-button color="warning" square auto-height @click="onClick('收藏', hide)">
收藏
</s-button>
</template>
<template #right="{ hide }">
<s-button color="danger" square auto-height @click="onClick('删除', hide)">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消', hide)">
取消
</s-button>
</template>
</s-swipe-action>
</s-list-item>
</s-list>
</template>
<script setup lang="js">
import { toast } from 'sard'
const onClick = (content, hide) => {
toast(`点击了${content}`)
hide()
}
</script>控制显隐
使用 v-model:visible 属性控制显隐。
vue
<template>
<s-list card>
<s-list-item>
<s-segmented v-model="visible" :options="options" />
</s-list-item>
<s-list-item style="padding: 1px 0 0 0">
<s-swipe-action v-model:visible="visible" :outside-closable="false">
<s-list-item title="两边插槽" value="内容" />
<template #left="{ hide }">
<s-button color="danger" square auto-height @click="onClick('点赞', hide)">点赞</s-button>
<s-button color="primary" square auto-height @click="onClick('分享', hide)">
分享
</s-button>
<s-button color="warning" square auto-height @click="onClick('收藏', hide)">
收藏
</s-button>
</template>
<template #right="{ hide }">
<s-button color="danger" square auto-height @click="onClick('删除', hide)">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消', hide)">
取消
</s-button>
</template>
</s-swipe-action>
</s-list-item>
</s-list>
</template>
<script setup lang="ts">
import { type SwipeActionVisible, toast } from 'sard'
import { ref } from 'vue'
const visible = ref<SwipeActionVisible>(false)
const options = [
{ label: 'left', value: 'left' },
{ label: 'false', value: false },
{ label: 'right', value: 'right' },
]
const onClick = (content: string, hide: () => void) => {
toast(`点击了${content}`)
hide()
}
</script>vue
<template>
<s-list card>
<s-list-item>
<s-segmented v-model="visible" :options="options" />
</s-list-item>
<s-list-item style="padding: 1px 0 0 0">
<s-swipe-action v-model:visible="visible" :outside-closable="false">
<s-list-item title="两边插槽" value="内容" />
<template #left="{ hide }">
<s-button color="danger" square auto-height @click="onClick('点赞', hide)">点赞</s-button>
<s-button color="primary" square auto-height @click="onClick('分享', hide)">
分享
</s-button>
<s-button color="warning" square auto-height @click="onClick('收藏', hide)">
收藏
</s-button>
</template>
<template #right="{ hide }">
<s-button color="danger" square auto-height @click="onClick('删除', hide)">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消', hide)">
取消
</s-button>
</template>
</s-swipe-action>
</s-list-item>
</s-list>
</template>
<script setup lang="js">
import { toast } from 'sard'
import { ref } from 'vue'
const visible = ref(false)
const options = [
{
label: 'left',
value: 'left',
},
{
label: 'false',
value: false,
},
{
label: 'right',
value: 'right',
},
]
const onClick = (content, hide) => {
toast(`点击了${content}`)
hide()
}
</script>禁止滑动
使用 disabled 属性来禁用滑动,同时也会禁用点击内容区域隐藏。
vue
<template>
<s-list card>
<s-list-item style="padding: 1px 0 0 0">
<s-swipe-action disabled>
<s-list-item title="两边插槽" value="内容" />
<template #right>
<s-button color="danger" square auto-height @click="onClick('删除')">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消')">取消</s-button>
</template>
</s-swipe-action>
</s-list-item>
<s-list-item style="padding: 1px 0 0 0">
<s-swipe-action disabled visible="right" :outside-closable="false">
<s-list-item title="两边插槽" value="内容" />
<template #right>
<s-button color="danger" square auto-height @click="onClick('删除')">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消')">取消</s-button>
</template>
</s-swipe-action>
</s-list-item>
</s-list>
</template>
<script setup lang="ts">
import { toast } from 'sard'
const onClick = (content: string) => {
toast(`点击了${content}`)
}
</script>vue
<template>
<s-list card>
<s-list-item style="padding: 1px 0 0 0">
<s-swipe-action disabled>
<s-list-item title="两边插槽" value="内容" />
<template #right>
<s-button color="danger" square auto-height @click="onClick('删除')">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消')">取消</s-button>
</template>
</s-swipe-action>
</s-list-item>
<s-list-item style="padding: 1px 0 0 0">
<s-swipe-action disabled visible="right" :outside-closable="false">
<s-list-item title="两边插槽" value="内容" />
<template #right>
<s-button color="danger" square auto-height @click="onClick('删除')">删除</s-button>
<s-button color="primary" square auto-height @click="onClick('取消')">取消</s-button>
</template>
</s-swipe-action>
</s-list-item>
</s-list>
</template>
<script setup lang="js">
import { toast } from 'sard'
const onClick = (content) => {
toast(`点击了${content}`)
}
</script>异步关闭
插槽按钮可任意定制;利用好 hide 方法和 disabled 属性,可实现复杂的效果。
vue
<template>
<s-list card>
<s-list-item style="padding: 0">
<s-swipe-action>
<s-list-item title="右边插槽" value="内容" />
<template #right="{ hide, asyncHide }">
<s-button color="danger" square auto-height @click="onDelete(asyncHide)">删除</s-button>
<s-button color="primary" square auto-height @click="hide">取消</s-button>
</template>
</s-swipe-action>
</s-list-item>
</s-list>
</template>
<script setup lang="ts">
import { dialog, type SwipeActionAsyncHide } from 'sard'
const asyncFetch = () => {
return new Promise((resolve) => {
setTimeout(resolve, 1000)
})
}
const onDelete = (asyncHide: SwipeActionAsyncHide) => {
asyncHide((resolve, reject) => {
dialog.confirm('确定删除?', {
beforeClose(type) {
if (type === 'confirm') {
return asyncFetch().then(resolve).catch(reject)
}
reject()
return true
},
})
})
}
</script>vue
<template>
<s-list card>
<s-list-item style="padding: 0">
<s-swipe-action>
<s-list-item title="右边插槽" value="内容" />
<template #right="{ hide, asyncHide }">
<s-button color="danger" square auto-height @click="onDelete(asyncHide)">删除</s-button>
<s-button color="primary" square auto-height @click="hide">取消</s-button>
</template>
</s-swipe-action>
</s-list-item>
</s-list>
</template>
<script setup lang="js">
import { dialog } from 'sard'
const asyncFetch = () => {
return new Promise((resolve) => {
setTimeout(resolve, 1e3)
})
}
const onDelete = (asyncHide) => {
asyncHide((resolve, reject) => {
dialog.confirm('确定删除?', {
beforeClose(type) {
if (type === 'confirm') {
return asyncFetch().then(resolve).catch(reject)
}
reject()
return true
},
})
})
}
</script>结合表单使用
下面演示了滑动操作组件如何与表单组件一起使用。
vue
<template>
<s-form ref="formRef" :model="dynamicValidateForm" card>
<s-form-item
v-for="(user, index) in dynamicValidateForm.users"
:key="user.id"
style="padding: 1px 0 0"
>
<s-swipe-action>
<s-form-item>
<s-flex align="center" gap="medium">
<s-form-item
:name="['users', index, 'first']"
:rules="{
required: true,
message: 'Missing first name',
}"
inlaid
>
<s-input inlaid v-model="user.first" placeholder="First Name" />
</s-form-item>
<s-form-item
:name="['users', index, 'last']"
:rules="{
required: true,
message: 'Missing last name',
}"
inlaid
>
<s-input inlaid v-model="user.last" placeholder="Last Name" />
</s-form-item>
</s-flex>
</s-form-item>
<template #right>
<s-button color="danger" square auto-height @click="removeUser(user)">删除</s-button>
</template>
</s-swipe-action>
</s-form-item>
<s-form-item>
<s-button variant="outlined" @click="addUser()">
<template #icon>
<Plus />
</template>
Add user
</s-button>
</s-form-item>
<s-form-item>
<s-button @click="onSubmit">Submit</s-button>
</s-form-item>
</s-form>
</template>
<script setup lang="ts">
import { toRaw, reactive, ref } from 'vue'
import { toast, type FormExpose } from 'sard'
import { Plus } from '@sard/icons'
interface User {
first: string
last: string
id: number
}
const formRef = ref<FormExpose>()
const dynamicValidateForm = reactive<{ users: User[] }>({
users: [
{
first: '',
last: '',
id: 1,
},
],
})
const removeUser = (item: User) => {
const index = dynamicValidateForm.users.indexOf(item)
if (index !== -1) {
dynamicValidateForm.users.splice(index, 1)
}
}
const addUser = () => {
dynamicValidateForm.users.push({
first: '',
last: '',
id: Date.now(),
})
}
const onSubmit = () => {
formRef.value
?.validate()
.then(() => {
toast('Success')
console.log('Received values of form:', toRaw(dynamicValidateForm))
})
.catch(() => {
console.log('fail')
})
}
</script>vue
<template>
<s-form ref="formRef" :model="dynamicValidateForm" card>
<s-form-item
v-for="(user, index) in dynamicValidateForm.users"
:key="user.id"
style="padding: 1px 0 0"
>
<s-swipe-action>
<s-form-item>
<s-flex align="center" gap="medium">
<s-form-item
:name="['users', index, 'first']"
:rules="{
required: true,
message: 'Missing first name',
}"
inlaid
>
<s-input inlaid v-model="user.first" placeholder="First Name" />
</s-form-item>
<s-form-item
:name="['users', index, 'last']"
:rules="{
required: true,
message: 'Missing last name',
}"
inlaid
>
<s-input inlaid v-model="user.last" placeholder="Last Name" />
</s-form-item>
</s-flex>
</s-form-item>
<template #right>
<s-button color="danger" square auto-height @click="removeUser(user)">删除</s-button>
</template>
</s-swipe-action>
</s-form-item>
<s-form-item>
<s-button variant="outlined" @click="addUser()">
<template #icon>
<Plus />
</template>
Add user
</s-button>
</s-form-item>
<s-form-item>
<s-button @click="onSubmit">Submit</s-button>
</s-form-item>
</s-form>
</template>
<script setup lang="js">
import { toRaw, reactive, ref } from 'vue'
import { toast } from 'sard'
import { Plus } from '@sard/icons'
const formRef = ref()
const dynamicValidateForm = reactive({
users: [
{
first: '',
last: '',
id: 1,
},
],
})
const removeUser = (item) => {
const index = dynamicValidateForm.users.indexOf(item)
if (index !== -1) {
dynamicValidateForm.users.splice(index, 1)
}
}
const addUser = () => {
dynamicValidateForm.users.push({
first: '',
last: '',
id: Date.now(),
})
}
const onSubmit = () => {
formRef.value
?.validate()
.then(() => {
toast('Success')
console.log('Received values of form:', toRaw(dynamicValidateForm))
})
.catch(() => {
console.log('fail')
})
}
</script>API
SwipeActionProps
| 属性 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| disabled | 是否禁用滑动 | boolean | false |
| visible | 控制显隐 | 'left' | 'right' | false | false |
| outside-closable | 点击外部时是否隐藏操作按钮 | boolean | true |
SwipeActionSlots
| 插槽 | 描述 | 属性 |
|---|---|---|
| default | 自定义默认内容 | - |
| left | 自定义左边操作按钮 | { hide: () => void; asyncHide: SwipeActionAsyncHide } |
| right | 自定义右边操作按钮 | { hide: () => void; asyncHide: SwipeActionAsyncHide } |
SwipeActionEmits
| 事件 | 描述 | 类型 |
|---|---|---|
| update:visible | 操作按钮显隐时触发 | (visible: 'left' | 'right' | false) => void |
SwipeActionExpose
| 属性 | 描述 | 类型 |
|---|---|---|
| hide | 隐藏操作按钮 | () => void |
SwipeActionAsyncHide
ts
type SwipeActionAsyncHide = (callback: (resolve: () => void, reject: () => void) => void) => void