Browse Source
perf: improve modal and drawer component documentation and fix known problems (#4264)
perf: improve modal and drawer component documentation and fix known problems (#4264)
* feat: improve modal and drawer component documentation and fix known problems * chore: update cipull/4267/head
Vben
3 weeks ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
54 changed files with 884 additions and 178 deletions
-
16.github/labeler.yml
-
2.github/release-drafter.yml
-
6.github/workflows/ci.yml
-
26.github/workflows/deploy.yml
-
21.github/workflows/labeler.yml
-
6docs/.vitepress/config/zh.mts
-
108docs/src/components/common-ui/vben-drawer.md
-
117docs/src/components/common-ui/vben-modal.md
-
2docs/src/components/introduction.md
-
45docs/src/demos/vben-drawer/auto-height/drawer.vue
-
21docs/src/demos/vben-drawer/auto-height/index.vue
-
11docs/src/demos/vben-drawer/basic/index.vue
-
26docs/src/demos/vben-drawer/dynamic/drawer.vue
-
30docs/src/demos/vben-drawer/dynamic/index.vue
-
8docs/src/demos/vben-drawer/extra/drawer.vue
-
21docs/src/demos/vben-drawer/extra/index.vue
-
26docs/src/demos/vben-drawer/shared-data/drawer.vue
-
26docs/src/demos/vben-drawer/shared-data/index.vue
-
21docs/src/demos/vben-modal/auto-height/index.vue
-
45docs/src/demos/vben-modal/auto-height/modal.vue
-
4docs/src/demos/vben-modal/basic/index.vue
-
21docs/src/demos/vben-modal/draggable/index.vue
-
10docs/src/demos/vben-modal/draggable/modal.vue
-
30docs/src/demos/vben-modal/dynamic/index.vue
-
38docs/src/demos/vben-modal/dynamic/modal.vue
-
5docs/src/demos/vben-modal/extra/index.vue
-
2docs/src/demos/vben-modal/extra/modal.vue
-
26docs/src/demos/vben-modal/shared-data/index.vue
-
26docs/src/demos/vben-modal/shared-data/modal.vue
-
18docs/src/guide/introduction/quick-start.md
-
18docs/src/guide/introduction/vben.md
-
16docs/src/guide/introduction/why.md
-
4internal/lint-configs/eslint-config/src/configs/vue.ts
-
2packages/@core/base/design/src/design-tokens/default/index.css
-
7packages/@core/ui-kit/popup-ui/src/drawer/drawer-api.ts
-
21packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue
-
2packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts
-
6packages/@core/ui-kit/popup-ui/src/modal/modal.ts
-
85packages/@core/ui-kit/popup-ui/src/modal/modal.vue
-
32packages/@core/ui-kit/popup-ui/src/modal/use-modal-draggable.ts
-
2packages/@core/ui-kit/shadcn-ui/src/components/spinner/loading.vue
-
2packages/@core/ui-kit/shadcn-ui/src/components/ui/dialog/DialogContent.vue
-
2packages/effects/common-ui/src/components/page/page.vue
-
2packages/effects/common-ui/src/ui/authentication/login-expired-modal.vue
-
2packages/stores/shim-pinia.d.ts
-
1packages/stores/src/modules/tabbar.ts
-
2packages/utils/src/helpers/generate-routes-backend.ts
-
16playground/src/views/examples/doc-button.vue
-
21playground/src/views/examples/drawer/auto-height-demo.vue
-
8playground/src/views/examples/drawer/base-demo.vue
-
7playground/src/views/examples/drawer/index.vue
-
24playground/src/views/examples/modal/auto-height-demo.vue
-
8playground/src/views/examples/modal/base-demo.vue
-
8playground/src/views/examples/modal/index.vue
@ -0,0 +1,16 @@ |
|||
# Add 'feature' label to any PR where the head branch name starts with `feature` or has a `feature` section in the name |
|||
feature: |
|||
- head-branch: ["^feat", "feat"] |
|||
|
|||
bug: |
|||
- head-branch: ["^fix", "fix"] |
|||
|
|||
chore: |
|||
- head-branch: ["^chore", "chore"] |
|||
|
|||
perf: |
|||
- head-branch: ["^perf", "perf"] |
|||
|
|||
documentation: |
|||
- changed-files: |
|||
- any-glob-to-any-file: ["**/*.md", "docs/**"] |
@ -0,0 +1,21 @@ |
|||
name: PR Labeler |
|||
|
|||
on: |
|||
pull_request: |
|||
types: [opened, edited, synchronize] |
|||
|
|||
jobs: |
|||
label: |
|||
permissions: |
|||
contents: read |
|||
pull-requests: write |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v4 |
|||
|
|||
- name: Label PR based on title or file changes |
|||
uses: actions/labeler@v5 |
|||
with: |
|||
repo-token: ${{ secrets.GITHUB_TOKEN }} |
|||
configuration-path: .github/labeler.yml |
@ -0,0 +1,108 @@ |
|||
--- |
|||
outline: deep |
|||
--- |
|||
|
|||
# Vben Drawer 抽屉 |
|||
|
|||
框架提供的抽屉组件,支持`自动高度`、`loading`等功能。 |
|||
|
|||
## 基础用法 |
|||
|
|||
使用 `useVbenDrawer` 创建最基础的模态框。 |
|||
|
|||
<DemoPreview dir="demos/vben-drawer/basic" /> |
|||
|
|||
## 组件抽离 |
|||
|
|||
Drawer 内的内容一般业务中,会比较复杂,所以我们可以将 drawer 内的内容抽离出来,也方便复用。通过 `connectedComponent` 参数,可以将内外组件进行连接,而不用其他任何操作。 |
|||
|
|||
<DemoPreview dir="demos/vben-drawer/extra" /> |
|||
|
|||
## 自动计算高度 |
|||
|
|||
弹窗会自动计算内容高度,超过一定高度会出现滚动条,同时结合 `loading` 效果以及使用 `prepend-footer` 插槽。 |
|||
|
|||
<DemoPreview dir="demos/vben-drawer/auto-height" /> |
|||
|
|||
## 使用 Api |
|||
|
|||
通过 `drawerApi` 可以调用 drawer 的方法以及使用 `setState` 更新 drawer 的状态。 |
|||
|
|||
<DemoPreview dir="demos/vben-drawer/dynamic" /> |
|||
|
|||
## 数据共享 |
|||
|
|||
如果你使用了 `connectedComponent` 参数,那么内外组件会共享数据,比如一些表单回填等操作。可以用 `drawerApi` 来获取数据和设置数据,配合 `onOpenChange`,可以满足大部分的需求。 |
|||
|
|||
<DemoPreview dir="demos/vben-drawer/shared-data" /> |
|||
|
|||
::: info 注意 |
|||
|
|||
- `VbenDrawer` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenDrawer参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。 |
|||
- 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenDrawer`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onComfirm`,那么以内部的 `onComfirm` 为准。`onOpenChange`事件除外,内外都会触发。 |
|||
|
|||
::: |
|||
|
|||
## API |
|||
|
|||
```ts |
|||
// Drawer 为弹窗组件 |
|||
// drawerApi 为弹窗的方法 |
|||
const [Drawer, drawerApi] = useVbenDrawer({ |
|||
// 属性 |
|||
// 事件 |
|||
}); |
|||
``` |
|||
|
|||
### Props |
|||
|
|||
所有属性都可以传入 `useVbenDrawer` 的第一个参数中。 |
|||
|
|||
| 属性名 | 描述 | 类型 | 默认值 | |
|||
| ------------------ | ------------------- | --------------- | ------- | |
|||
| title | 标题 | `string\|slot` | - | |
|||
| titleTooltip | 标题提示信息 | `string\|slot` | - | |
|||
| description | 描述信息 | `string\|slot` | - | |
|||
| isOpen | 弹窗打开状态 | `boolean` | `false` | |
|||
| loading | 弹窗加载状态 | `boolean` | `false` | |
|||
| closable | 显示关闭按钮 | `boolean` | `true` | |
|||
| modal | 显示遮罩 | `boolean` | `true` | |
|||
| header | 显示header | `boolean` | `true` | |
|||
| footer | 显示footer | `boolean\|slot` | `true` | |
|||
| confirmLoading | 确认按钮loading状态 | `boolean` | `false` | |
|||
| closeOnClickModal | 点击遮罩关闭弹窗 | `boolean` | `true` | |
|||
| closeOnPressEscape | esc 关闭弹窗 | `boolean` | `true` | |
|||
| confirmText | 确认按钮文本 | `boolean\|slot` | `确认` | |
|||
| cancelText | 取消按钮文本 | `boolean\|slot` | `取消` | |
|||
|
|||
### Event |
|||
|
|||
以下事件,只有在 `useVbenDrawer({onCancel:()=>{}})` 中传入才会生效。 |
|||
|
|||
| 事件名 | 描述 | 类型 | |
|||
| --- | --- | --- | |
|||
| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | |
|||
| onCancel | 点击取消按钮触发 | `()=>void` | |
|||
| onConfirm | 点击确认按钮触发 | `()=>void` | |
|||
| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` | |
|||
|
|||
### Slots |
|||
|
|||
除了上面的属性类型包含`slot`,还可以通过插槽来自定义弹窗的内容。 |
|||
|
|||
| 插槽名 | 描述 | |
|||
| -------------- | ------------------- | |
|||
| default | 默认插槽 - 弹窗内容 | |
|||
| prepend-footer | 取消按钮左侧 | |
|||
| append-footer | 取消按钮右侧 | |
|||
|
|||
### modalApi |
|||
|
|||
| 事件名 | 描述 | 类型 | |
|||
| --- | --- | --- | |
|||
| setState | 动态设置弹窗状态属性 | `setState(props) \| setState((prev)=>(props))` | |
|||
| open | 打开弹窗 | `()=>void` | |
|||
| close | 关闭弹窗 | `()=>void` | |
|||
| setData | 设置共享数据 | `<T>(data:T)=>void` | |
|||
| getData | 获取共享数据 | `<T>()=>T` | |
|||
| useStore | 获取可响应式状态 | - | |
@ -0,0 +1,45 @@ |
|||
<script lang="ts" setup> |
|||
import { ref } from 'vue'; |
|||
|
|||
import { useVbenDrawer, VbenButton } from '@vben/common-ui'; |
|||
|
|||
const list = ref<number[]>([]); |
|||
|
|||
const [Drawer, drawerApi] = useVbenDrawer({ |
|||
onCancel() { |
|||
drawerApi.close(); |
|||
}, |
|||
onConfirm() { |
|||
console.log('onConfirm'); |
|||
}, |
|||
onOpenChange(isOpen) { |
|||
if (isOpen) { |
|||
handleUpdate(10); |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
function handleUpdate(len: number) { |
|||
drawerApi.setState({ loading: true }); |
|||
setTimeout(() => { |
|||
list.value = Array.from({ length: len }, (_v, k) => k + 1); |
|||
drawerApi.setState({ loading: false }); |
|||
}, 2000); |
|||
} |
|||
</script> |
|||
<template> |
|||
<Drawer title="自动计算高度"> |
|||
<div |
|||
v-for="item in list" |
|||
:key="item" |
|||
class="even:bg-heavy bg-muted flex-center h-[220px] w-full" |
|||
> |
|||
{{ item }} |
|||
</div> |
|||
<template #prepend-footer> |
|||
<VbenButton type="link" @click="handleUpdate(6)"> |
|||
点击更新数据 |
|||
</VbenButton> |
|||
</template> |
|||
</Drawer> |
|||
</template> |
@ -0,0 +1,21 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenDrawer, VbenButton } from '@vben/common-ui'; |
|||
|
|||
import ExtraDrawer from './drawer.vue'; |
|||
|
|||
const [Drawer, drawerApi] = useVbenDrawer({ |
|||
// 连接抽离的组件 |
|||
connectedComponent: ExtraDrawer, |
|||
}); |
|||
|
|||
function open() { |
|||
drawerApi.open(); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<Drawer /> |
|||
<VbenButton @click="open">Open</VbenButton> |
|||
</div> |
|||
</template> |
@ -0,0 +1,11 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenDrawer, VbenButton } from '@vben/common-ui'; |
|||
|
|||
const [Drawer, drawerApi] = useVbenDrawer(); |
|||
</script> |
|||
<template> |
|||
<div> |
|||
<VbenButton @click="() => drawerApi.open()">Open</VbenButton> |
|||
<Drawer class="w-[600px]" title="基础示例"> drawer content </Drawer> |
|||
</div> |
|||
</template> |
@ -0,0 +1,26 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenDrawer, VbenButton } from '@vben/common-ui'; |
|||
|
|||
const [Drawer, drawerApi] = useVbenDrawer({ |
|||
onCancel() { |
|||
drawerApi.close(); |
|||
}, |
|||
onConfirm() { |
|||
console.info('onConfirm'); |
|||
}, |
|||
title: '动态修改配置示例', |
|||
}); |
|||
|
|||
function handleUpdateTitle() { |
|||
drawerApi.setState({ title: '内部动态标题' }); |
|||
} |
|||
</script> |
|||
<template> |
|||
<Drawer> |
|||
<div class="flex-col-center"> |
|||
<VbenButton class="mb-3" type="primary" @click="handleUpdateTitle()"> |
|||
内部动态修改标题 |
|||
</VbenButton> |
|||
</div> |
|||
</Drawer> |
|||
</template> |
@ -0,0 +1,30 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenDrawer, VbenButton } from '@vben/common-ui'; |
|||
|
|||
import ExtraDrawer from './drawer.vue'; |
|||
|
|||
const [Drawer, drawerApi] = useVbenDrawer({ |
|||
// 连接抽离的组件 |
|||
connectedComponent: ExtraDrawer, |
|||
}); |
|||
|
|||
function open() { |
|||
drawerApi.open(); |
|||
} |
|||
|
|||
function handleUpdateTitle() { |
|||
drawerApi.setState({ title: '外部动态标题' }); |
|||
drawerApi.open(); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<Drawer /> |
|||
|
|||
<VbenButton @click="open">Open</VbenButton> |
|||
<VbenButton class="ml-2" type="primary" @click="handleUpdateTitle"> |
|||
从外部修改标题并打开 |
|||
</VbenButton> |
|||
</div> |
|||
</template> |
@ -0,0 +1,8 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenDrawer } from '@vben/common-ui'; |
|||
|
|||
const [Drawer] = useVbenDrawer(); |
|||
</script> |
|||
<template> |
|||
<Drawer title="组件抽离示例"> extra drawer content </Drawer> |
|||
</template> |
@ -0,0 +1,21 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenDrawer, VbenButton } from '@vben/common-ui'; |
|||
|
|||
import ExtraDrawer from './drawer.vue'; |
|||
|
|||
const [Drawer, drawerApi] = useVbenDrawer({ |
|||
// 连接抽离的组件 |
|||
connectedComponent: ExtraDrawer, |
|||
}); |
|||
|
|||
function open() { |
|||
drawerApi.open(); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<Drawer /> |
|||
<VbenButton @click="open">Open</VbenButton> |
|||
</div> |
|||
</template> |
@ -0,0 +1,26 @@ |
|||
<script lang="ts" setup> |
|||
import { ref } from 'vue'; |
|||
|
|||
import { useVbenDrawer } from '@vben/common-ui'; |
|||
|
|||
const data = ref(); |
|||
|
|||
const [Drawer, drawerApi] = useVbenDrawer({ |
|||
onCancel() { |
|||
drawerApi.close(); |
|||
}, |
|||
onConfirm() { |
|||
console.info('onConfirm'); |
|||
}, |
|||
onOpenChange(isOpen: boolean) { |
|||
if (isOpen) { |
|||
data.value = drawerApi.getData<Record<string, any>>(); |
|||
} |
|||
}, |
|||
}); |
|||
</script> |
|||
<template> |
|||
<Drawer title="数据共享示例"> |
|||
<div class="flex-col-center">外部传递数据: {{ data }}</div> |
|||
</Drawer> |
|||
</template> |
@ -0,0 +1,26 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenDrawer, VbenButton } from '@vben/common-ui'; |
|||
|
|||
import ExtraDrawer from './drawer.vue'; |
|||
|
|||
const [Drawer, drawerApi] = useVbenDrawer({ |
|||
// 连接抽离的组件 |
|||
connectedComponent: ExtraDrawer, |
|||
}); |
|||
|
|||
function open() { |
|||
drawerApi.setData({ |
|||
content: '外部传递的数据 content', |
|||
payload: '外部传递的数据 payload', |
|||
}); |
|||
drawerApi.open(); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<Drawer /> |
|||
|
|||
<VbenButton @click="open">Open</VbenButton> |
|||
</div> |
|||
</template> |
@ -0,0 +1,21 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenModal, VbenButton } from '@vben/common-ui'; |
|||
|
|||
import ExtraModal from './modal.vue'; |
|||
|
|||
const [Modal, modalApi] = useVbenModal({ |
|||
// 连接抽离的组件 |
|||
connectedComponent: ExtraModal, |
|||
}); |
|||
|
|||
function openModal() { |
|||
modalApi.open(); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<Modal /> |
|||
<VbenButton @click="openModal">Open</VbenButton> |
|||
</div> |
|||
</template> |
@ -0,0 +1,45 @@ |
|||
<script lang="ts" setup> |
|||
import { ref } from 'vue'; |
|||
|
|||
import { useVbenModal, VbenButton } from '@vben/common-ui'; |
|||
|
|||
const list = ref<number[]>([]); |
|||
|
|||
const [Modal, modalApi] = useVbenModal({ |
|||
onCancel() { |
|||
modalApi.close(); |
|||
}, |
|||
onConfirm() { |
|||
console.log('onConfirm'); |
|||
}, |
|||
onOpenChange(isOpen) { |
|||
if (isOpen) { |
|||
handleUpdate(10); |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
function handleUpdate(len: number) { |
|||
modalApi.setState({ loading: true }); |
|||
setTimeout(() => { |
|||
list.value = Array.from({ length: len }, (_v, k) => k + 1); |
|||
modalApi.setState({ loading: false }); |
|||
}, 2000); |
|||
} |
|||
</script> |
|||
<template> |
|||
<Modal title="自动计算高度"> |
|||
<div |
|||
v-for="item in list" |
|||
:key="item" |
|||
class="even:bg-heavy bg-muted flex-center h-[220px] w-full" |
|||
> |
|||
{{ item }} |
|||
</div> |
|||
<template #prepend-footer> |
|||
<VbenButton type="link" @click="handleUpdate(6)"> |
|||
点击更新数据 |
|||
</VbenButton> |
|||
</template> |
|||
</Modal> |
|||
</template> |
@ -0,0 +1,21 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenModal, VbenButton } from '@vben/common-ui'; |
|||
|
|||
import ExtraModal from './modal.vue'; |
|||
|
|||
const [Modal, modalApi] = useVbenModal({ |
|||
// 连接抽离的组件 |
|||
connectedComponent: ExtraModal, |
|||
}); |
|||
|
|||
function openModal() { |
|||
modalApi.open(); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<Modal /> |
|||
<VbenButton @click="openModal">Open</VbenButton> |
|||
</div> |
|||
</template> |
@ -0,0 +1,10 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenModal } from '@vben/common-ui'; |
|||
|
|||
const [Modal] = useVbenModal({ |
|||
draggable: true, |
|||
}); |
|||
</script> |
|||
<template> |
|||
<Modal title="拖拽示例"> modal content </Modal> |
|||
</template> |
@ -0,0 +1,30 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenModal, VbenButton } from '@vben/common-ui'; |
|||
|
|||
import ExtraModal from './modal.vue'; |
|||
|
|||
const [Modal, modalApi] = useVbenModal({ |
|||
// 连接抽离的组件 |
|||
connectedComponent: ExtraModal, |
|||
}); |
|||
|
|||
function openModal() { |
|||
modalApi.open(); |
|||
} |
|||
|
|||
function handleUpdateTitle() { |
|||
modalApi.setState({ title: '外部动态标题' }); |
|||
modalApi.open(); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<Modal /> |
|||
|
|||
<VbenButton @click="openModal">Open</VbenButton> |
|||
<VbenButton class="ml-2" type="primary" @click="handleUpdateTitle"> |
|||
从外部修改标题并打开 |
|||
</VbenButton> |
|||
</div> |
|||
</template> |
@ -0,0 +1,38 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenModal, VbenButton } from '@vben/common-ui'; |
|||
|
|||
const [Modal, modalApi] = useVbenModal({ |
|||
draggable: true, |
|||
onCancel() { |
|||
modalApi.close(); |
|||
}, |
|||
onConfirm() { |
|||
console.info('onConfirm'); |
|||
}, |
|||
title: '动态修改配置示例', |
|||
}); |
|||
|
|||
const state = modalApi.useStore(); |
|||
|
|||
function handleUpdateTitle() { |
|||
modalApi.setState({ title: '内部动态标题' }); |
|||
} |
|||
|
|||
function handleToggleFullscreen() { |
|||
modalApi.setState((prev) => { |
|||
return { ...prev, fullscreen: !prev.fullscreen }; |
|||
}); |
|||
} |
|||
</script> |
|||
<template> |
|||
<Modal> |
|||
<div class="flex-col-center"> |
|||
<VbenButton class="mb-3" type="primary" @click="handleUpdateTitle()"> |
|||
内部动态修改标题 |
|||
</VbenButton> |
|||
<VbenButton class="mb-3" @click="handleToggleFullscreen()"> |
|||
{{ state.fullscreen ? '退出全屏' : '打开全屏' }} |
|||
</VbenButton> |
|||
</div> |
|||
</Modal> |
|||
</template> |
@ -0,0 +1,26 @@ |
|||
<script lang="ts" setup> |
|||
import { useVbenModal, VbenButton } from '@vben/common-ui'; |
|||
|
|||
import ExtraModal from './modal.vue'; |
|||
|
|||
const [Modal, modalApi] = useVbenModal({ |
|||
// 连接抽离的组件 |
|||
connectedComponent: ExtraModal, |
|||
}); |
|||
|
|||
function openModal() { |
|||
modalApi.setData({ |
|||
content: '外部传递的数据 content', |
|||
payload: '外部传递的数据 payload', |
|||
}); |
|||
modalApi.open(); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<Modal /> |
|||
|
|||
<VbenButton @click="openModal">Open</VbenButton> |
|||
</div> |
|||
</template> |
@ -0,0 +1,26 @@ |
|||
<script lang="ts" setup> |
|||
import { ref } from 'vue'; |
|||
|
|||
import { useVbenModal } from '@vben/common-ui'; |
|||
|
|||
const data = ref(); |
|||
|
|||
const [Modal, modalApi] = useVbenModal({ |
|||
onCancel() { |
|||
modalApi.close(); |
|||
}, |
|||
onConfirm() { |
|||
console.info('onConfirm'); |
|||
}, |
|||
onOpenChange(isOpen: boolean) { |
|||
if (isOpen) { |
|||
data.value = modalApi.getData<Record<string, any>>(); |
|||
} |
|||
}, |
|||
}); |
|||
</script> |
|||
<template> |
|||
<Modal title="数据共享示例"> |
|||
<div class="flex-col-center">外部传递数据: {{ data }}</div> |
|||
</Modal> |
|||
</template> |
@ -1,9 +1,23 @@ |
|||
# 为什么选择我们? |
|||
|
|||
首先,我们不会去和其他框架做比较。我们认为每个框架都有自己的特点,适合不同的场景。我们的目标是提供一个简单、易用的框架,让开发者可以快速上手,专注于业务逻辑的开发。所以我们只会不断完善和优化我们的框架,提供更好的体验。 |
|||
::: info 写在前面 |
|||
|
|||
我们不会去和其他框架做比较。我们认为每个框架都有自己的特点,适合不同的场景。我们的目标是提供一个简单、易用的框架,让开发者可以快速上手,专注于业务逻辑的开发。所以我们只会不断完善和优化我们的框架,提供更好的体验。 |
|||
|
|||
::: |
|||
|
|||
我们致力于为开发者提供一个高效、现代、易用的前端框架。我们的解决方案基于最新的技术栈,如 Vue3、Vite 和 TypeScript,确保您在构建项目时始终走在技术的前沿。同时,我们注重代码的质量与规范,通过严格的工具链保证代码的一致性和可维护性。无论是初创项目还是企业级应用,我们的框架都能帮助您快速构建、迭代和部署。 |
|||
|
|||
## 框架历程 |
|||
|
|||
从 Vue Vben Admin 1.x 版本开始,框架经历了许多迭代和优化。从一开始使用 `Vite 0.x` 版本,没有现成的插件,开发了很多自定义插件来弥合 Webpack 和 Vite 之间的差异。虽然很多现在已经被代替,但是我们的初衷一直没有变,就是提供一个简单、易用的框架。 |
|||
|
|||
虽然中间有段时间由社区维护,但我们一直密切关注 Vue Vben Admin 的发展。见证了许多开发者使用 Vben Admin,并提供了许多宝贵的建议和反馈。非常感谢大家的支持和贡献,这些都是我们持续改进 Vben Admin 的动力。新版本中,我们持续收集用户反馈,重新开始,不断优化框架,以提供更好的用户体验。我们的目标是让开发者能够快速上手,专注于业务逻辑的开发。 |
|||
|
|||
## 单元测试 |
|||
|
|||
单元测试是确保代码质量的基石。在开发过程中编写和执行单元测试,以捕捉潜在的错误并提升代码的可靠性。框架核心逻辑使用 `vitest` 做了单元测试,并在逐步增加覆盖率。通过单元测试,可以放心地进行代码重构,减少回归问题,从而提高整体开发效率。 |
|||
|
|||
## 质量与规范 |
|||
|
|||
我们始终高度重视代码的质量与规范。通过使用 ESLint、Prettier、Stylelint、Publint、CSpell 等工具来确保代码质量。我们的代码规范基于 Vue3、Vite、TypeScript 等现代前端技术制定,旨在提供一个简洁、易用的框架,使开发者能够快速上手并专注于业务逻辑的开发。 |
@ -0,0 +1,16 @@ |
|||
<script lang="ts" setup> |
|||
import { VBEN_DOC_URL } from '@vben/constants'; |
|||
import { openWindow } from '@vben/utils'; |
|||
|
|||
import { Button } from 'ant-design-vue'; |
|||
|
|||
const props = defineProps<{ path: string }>(); |
|||
|
|||
function handleClick() { |
|||
openWindow(VBEN_DOC_URL + props.path); |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<Button type="link" @click="handleClick">查看组件文档</Button> |
|||
</template> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue