mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-21 04:50:14 +08:00
feat(tabs): add on-before-leave prop (#1394)
* feat(tabs): add on-before-leave prop * feat: demo引入属性优化 * feat: 优化tab加载 * feat: 优化tab加载 * feat: 处理新tab打开中断旧导航 Co-authored-by: unknown <liyang@xiaoyouzi.com>
This commit is contained in:
parent
7686b69e2a
commit
2c530b56da
@ -1,5 +1,11 @@
|
||||
# CHANGELOG
|
||||
|
||||
## Pending
|
||||
|
||||
### Feats
|
||||
|
||||
- `n-tabs` add `on-before-leave` prop, closes [#1337](https://github.com/TuSimple/naive-ui/issues/1337).
|
||||
|
||||
## 2.19.9 (2021-10-18)
|
||||
|
||||
### Fixes
|
||||
|
@ -1,5 +1,11 @@
|
||||
# CHANGELOG
|
||||
|
||||
## Pending
|
||||
|
||||
### Feats
|
||||
|
||||
- `n-tabs` 新增 `on-before-leave` 属性,关闭 [#1337](https://github.com/TuSimple/naive-ui/issues/1337)
|
||||
|
||||
## 2.19.9 (2021-10-18)
|
||||
|
||||
### Fixes
|
||||
|
33
src/tabs/demos/enUS/before-leave.demo.md
Normal file
33
src/tabs/demos/enUS/before-leave.demo.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Hook function before switching tab
|
||||
|
||||
```html
|
||||
<n-tabs
|
||||
type="line"
|
||||
@before-leave="handleBeforeLeave"
|
||||
@update:value="handleUpdateValue"
|
||||
>
|
||||
<n-tab-pane name="oasis" tab="Oasis">Wonderwall</n-tab-pane>
|
||||
<n-tab-pane name="the beatles" tab="the Beatles">Hey Jude</n-tab-pane>
|
||||
<n-tab-pane name="jay chou" tab="My Favour">My faviur</n-tab-pane>
|
||||
</n-tabs>
|
||||
```
|
||||
|
||||
```js
|
||||
import { defineComponent } from 'vue'
|
||||
import { useMessage } from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
setup () {
|
||||
const message = useMessage()
|
||||
return {
|
||||
handleBeforeLeave: (tab, oldTab) => {
|
||||
if (tab === 'jay chou') message.info('Can not leave!')
|
||||
return tab !== 'jay chou'
|
||||
},
|
||||
handleUpdateValue: (activeName) => {
|
||||
message.info(activeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
@ -14,6 +14,7 @@ prefix
|
||||
display-directive
|
||||
addable
|
||||
line-debug
|
||||
before-leave
|
||||
```
|
||||
|
||||
## API
|
||||
@ -33,6 +34,7 @@ line-debug
|
||||
| type | `'bar' \| 'line' \| 'card' \| 'segment'` | `'bar'` | Tabs type. |
|
||||
| value | `string \| number` | `undefined` | Value in controlled mode. |
|
||||
| on-add | `() => void` | `undefined` | Callback function triggered when add tag. |
|
||||
| on-before-leave | `(activeName: string \| number, oldActiveName: string \| number \| null) => boolean \| Promise<boolean>` | `undefined` | hook function before switching tab. |
|
||||
| on-close | `(name: string \| number) => void` | `undefined` | Callback function triggered when close tag. |
|
||||
| on-update:value | `(value: string \| number) => void` | `undefined` | Callback function triggered when the value changes. |
|
||||
|
||||
|
36
src/tabs/demos/zhCN/before-leave.demo.md
Normal file
36
src/tabs/demos/zhCN/before-leave.demo.md
Normal file
@ -0,0 +1,36 @@
|
||||
# 切换标签前的钩子函数
|
||||
|
||||
```html
|
||||
<n-tabs
|
||||
type="line"
|
||||
@before-leave="handleBeforeLeave"
|
||||
@update:value="handleUpdateValue"
|
||||
>
|
||||
<n-tab-pane name="oasis" tab="Oasis"> Oasis </n-tab-pane>
|
||||
<n-tab-pane name="oasi11s" tab="Oasis111"> Oasis </n-tab-pane>
|
||||
<n-tab-pane name="the beatles" tab="the Beatles">the beatles</n-tab-pane>
|
||||
<n-tab-pane name="jay chou" tab="My Favour">My faviur</n-tab-pane>
|
||||
</n-tabs>
|
||||
```
|
||||
|
||||
```js
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import { useMessage } from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
setup () {
|
||||
const message = useMessage()
|
||||
const OasisRef = ref('正在加载中...')
|
||||
return {
|
||||
Oasis: OasisRef,
|
||||
handleBeforeLeave: (tab, oldTab) => {
|
||||
if (tab === 'jay chou') message.info('Can not leave!')
|
||||
return tab !== 'jay chou'
|
||||
},
|
||||
handleUpdateValue: (activeName) => {
|
||||
message.info(activeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
@ -16,6 +16,7 @@ addable
|
||||
line-debug
|
||||
style-inherit-debug
|
||||
shadow-debug
|
||||
before-leave
|
||||
```
|
||||
|
||||
## API
|
||||
@ -35,6 +36,7 @@ shadow-debug
|
||||
| type | `'bar' \| 'line' \| 'card' \| 'segment'` | `'bar'` | 标签类型 |
|
||||
| value | `string \| number` | `undefined` | 受控模式下的值 |
|
||||
| on-add | `() => void` | `undefined` | 添加标签的回调函数 |
|
||||
| on-before-leave | `(activeName: string \| number, oldActiveName: string \| number \| null) => boolean \| Promise<boolean>` | `undefined` | 切换标签之前的钩子函数 |
|
||||
| on-close | `(name: string \| number) => void` | `undefined` | 关闭标签的回调函数 |
|
||||
| on-update:value | `(value: string \| number) => void` | `undefined` | 选中发生改变时的回调函数 |
|
||||
|
||||
|
@ -21,8 +21,11 @@ export default defineComponent({
|
||||
typeRef,
|
||||
closableRef,
|
||||
tabStyleRef,
|
||||
tabIdRef,
|
||||
handleAdd,
|
||||
handleBeforeLeave,
|
||||
handleTabClick,
|
||||
setTabId,
|
||||
handleClose
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
} = inject(tabsInjectionKey)!
|
||||
@ -48,7 +51,28 @@ export default defineComponent({
|
||||
handleAdd()
|
||||
return
|
||||
}
|
||||
handleTabClick(props.name)
|
||||
const id = tabIdRef.value ? tabIdRef.value.id + 1 : 1
|
||||
setTabId(props.name, id)
|
||||
if (props.name !== valueRef.value) {
|
||||
const result = handleBeforeLeave(props.name, valueRef.value)
|
||||
if (typeof result === 'boolean') {
|
||||
if (result) handleTabClick(props.name)
|
||||
} else {
|
||||
result.then(
|
||||
() => {
|
||||
if (
|
||||
tabIdRef.value.tab === props.name &&
|
||||
tabIdRef.value.id === id
|
||||
) {
|
||||
handleTabClick(props.name)
|
||||
}
|
||||
},
|
||||
() => {
|
||||
// not allowed to change tab
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -28,6 +28,8 @@ import {
|
||||
Addable,
|
||||
OnClose,
|
||||
OnCloseImpl,
|
||||
BeforeLeave,
|
||||
BeforeLeaveImpl,
|
||||
tabsInjectionKey,
|
||||
TabsType
|
||||
} from './interface'
|
||||
@ -58,6 +60,7 @@ const tabsProps = {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
onBeforeLeave: [Function, Array] as PropType<MaybeArray<BeforeLeave>>,
|
||||
onAdd: Function as PropType<() => void>,
|
||||
'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
|
||||
onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
|
||||
@ -135,6 +138,10 @@ export default defineComponent({
|
||||
compitableValueRef,
|
||||
uncontrolledValueRef
|
||||
)
|
||||
const tabIdRef = ref<{ tab: string | number | null, id: number }>({
|
||||
tab: mergedValueRef.value,
|
||||
id: 0
|
||||
})
|
||||
|
||||
const tabWrapperStyleRef = computed(() => {
|
||||
if (!props.justifyContent || props.type === 'card') return undefined
|
||||
@ -177,9 +184,20 @@ export default defineComponent({
|
||||
updateBarStyle(tabEl)
|
||||
}
|
||||
}
|
||||
function handleBeforeLeave (
|
||||
activeName: string | number,
|
||||
oldActiveName: string | number | null
|
||||
): boolean | Promise<boolean> {
|
||||
const { onBeforeLeave } = props
|
||||
if (!onBeforeLeave) return true
|
||||
return (onBeforeLeave as BeforeLeaveImpl)(activeName, oldActiveName)
|
||||
}
|
||||
function handleTabClick (panelName: string | number): void {
|
||||
doUpdateValue(panelName)
|
||||
}
|
||||
function setTabId (tab: string | number, id: number): void {
|
||||
tabIdRef.value = { tab, id }
|
||||
}
|
||||
function doUpdateValue (panelName: string | number): void {
|
||||
const {
|
||||
onActiveNameChange,
|
||||
@ -275,7 +293,10 @@ export default defineComponent({
|
||||
typeRef: toRef(props, 'type'),
|
||||
closableRef: toRef(props, 'closable'),
|
||||
valueRef: mergedValueRef,
|
||||
tabIdRef,
|
||||
handleBeforeLeave,
|
||||
handleTabClick,
|
||||
setTabId,
|
||||
handleClose,
|
||||
handleAdd
|
||||
})
|
||||
|
@ -8,6 +8,15 @@ export type OnUpdateValueImpl = (value: string | number) => void
|
||||
export type OnClose = (name: string & number) => void
|
||||
export type OnCloseImpl = (name: string | number) => void
|
||||
|
||||
export type BeforeLeave = (
|
||||
activeName: string & number,
|
||||
oldActiveName: string & number & null
|
||||
) => boolean | Promise<boolean>
|
||||
export type BeforeLeaveImpl = (
|
||||
activeName: string | number,
|
||||
oldActiveName: string | number | null
|
||||
) => boolean | Promise<boolean>
|
||||
|
||||
export interface TabsInjection {
|
||||
mergedClsPrefixRef: Ref<string>
|
||||
valueRef: Ref<string | number | null>
|
||||
@ -15,7 +24,10 @@ export interface TabsInjection {
|
||||
closableRef: Ref<boolean>
|
||||
tabStyleRef: Ref<string | CSSProperties | undefined>
|
||||
paneStyleRef: Ref<string | CSSProperties | undefined>
|
||||
tabIdRef: Ref<{ tab: string | number | null, id: number }>
|
||||
handleBeforeLeave: BeforeLeaveImpl
|
||||
handleTabClick: (panelName: string | number) => void
|
||||
setTabId: (tab: string | number, id: number) => void
|
||||
handleClose: (panelName: string | number) => void
|
||||
handleAdd: () => void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user