mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
Compare commits
213 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b45b0b7608 | ||
|
c309ca2aaf | ||
|
66df033ec8 | ||
|
e2ea3be819 | ||
|
019c328975 | ||
|
9418fe371d | ||
|
5d8282ddae | ||
|
43ff890d79 | ||
|
98642589ee | ||
|
0aac165d4e | ||
|
f60a3b840d | ||
|
997f3e0acd | ||
|
e2fe50250c | ||
|
7d023fd6e4 | ||
|
1afe960f30 | ||
|
a677bee2b8 | ||
|
05544c109f | ||
|
21c57caa9b | ||
|
66aa2906e0 | ||
|
61ef6b9a98 | ||
|
c25acb8d46 | ||
|
8bcb34724f | ||
|
cf5e7e6629 | ||
|
50ee584953 | ||
|
889b28609a | ||
|
dcffa09812 | ||
|
0881de82af | ||
|
86adc66dd9 | ||
|
1d87343195 | ||
|
dfdc27a755 | ||
|
5c6992f97c | ||
|
292ac6b55e | ||
|
8ef197ea12 | ||
|
f61b00175e | ||
|
6a1516ca37 | ||
|
d3c679aa27 | ||
|
2f6ef7aed8 | ||
|
83a4e286bd | ||
|
178df39c44 | ||
|
627661e0ed | ||
|
b46b429682 | ||
|
15142770f2 | ||
|
aea97f90e6 | ||
|
a0bd47dd84 | ||
|
e998c1be95 | ||
|
1ce400bb7f | ||
|
5a3fe7ed0f | ||
|
1bc6cbdb69 | ||
|
5f526c9f0e | ||
|
ec78d5b1d9 | ||
|
e5e6e8aaa4 | ||
|
e27efdad0d | ||
|
154408fa8b | ||
|
20ee462cab | ||
|
2b77f96fc5 | ||
|
1d5cb1e051 | ||
|
5d81dcb549 | ||
|
63519433f1 | ||
|
1f19fb0d9f | ||
|
f13601cb9f | ||
|
5cd731594f | ||
|
582582e480 | ||
|
fe2115ee5c | ||
|
bc60f5116b | ||
|
b65396ef06 | ||
|
523d9ef400 | ||
|
912a5f17b1 | ||
|
ea57c9e9ff | ||
|
ac7d6dd542 | ||
|
a0389defcc | ||
|
26cbffe6c1 | ||
|
a541090f3a | ||
|
e08e9845a2 | ||
|
8e822a591d | ||
|
8e78b6d8ad | ||
|
5bff9e8c5f | ||
|
475d108ccb | ||
|
527bad9cc2 | ||
|
47a5151a20 | ||
|
dd724fde4d | ||
|
a584cc217b | ||
|
5b72c4005b | ||
|
d2f6a3c96f | ||
|
239be20cbf | ||
|
101dcc3ef2 | ||
|
8572393881 | ||
|
0d79eb244b | ||
|
db2e6ca12f | ||
|
992eea3eeb | ||
|
3a1e792e31 | ||
|
06199faf2c | ||
|
c206642d2d | ||
|
5bade79394 | ||
|
2ceb68e691 | ||
|
9cfef027aa | ||
|
0b4b04eefb | ||
|
0a7b535533 | ||
|
17c2022a6f | ||
|
cce3ceb5b6 | ||
|
fcd91cb0b0 | ||
|
3692014070 | ||
|
85c5ad6718 | ||
|
bef919c7f0 | ||
|
d39f6a898a | ||
|
43ae30026a | ||
|
27c46b01ae | ||
|
3979ddc40a | ||
|
967cb56c18 | ||
|
c65d4f9672 | ||
|
73788f9e88 | ||
|
2acd47b5ee | ||
|
b3cf1dfb54 | ||
|
35a50012c7 | ||
|
83295e655d | ||
|
e2790fe95d | ||
|
b608fb23f0 | ||
|
829db06d5b | ||
|
2e053ad76b | ||
|
c942efb76b | ||
|
fdcf9931be | ||
|
e61bd487fa | ||
|
7deba88b91 | ||
|
980f976011 | ||
|
c00fa4cd70 | ||
|
ef8e66a924 | ||
|
e8ffc80dc6 | ||
|
3920ebe25b | ||
|
5b407566db | ||
|
f327d5bbc2 | ||
|
2a8bb86fbb | ||
|
7dae50b0c9 | ||
|
d68053ea7f | ||
|
8ca9741845 | ||
|
c9c312c4ba | ||
|
5dca6fe2e2 | ||
|
fdc5436249 | ||
|
7d22cc2155 | ||
|
42d1dd836c | ||
|
15e7461a93 | ||
|
0fdaf133bb | ||
|
d4584aafda | ||
|
5b3c4f1546 | ||
|
25302fb333 | ||
|
2f02f19cec | ||
|
82e0e454d0 | ||
|
650bdd2294 | ||
|
cb2d99c8cf | ||
|
42f03fe1a2 | ||
|
fc2847fdb4 | ||
|
d6e80e8954 | ||
|
39b51d5dae | ||
|
8e98e97449 | ||
|
f5c32c29f1 | ||
|
98b999d911 | ||
|
0e8e3200a2 | ||
|
73322fd310 | ||
|
97b074ad0c | ||
|
541458c41b | ||
|
df24a3b683 | ||
|
966af9dd68 | ||
|
b6fcd32dcf | ||
|
35a990ed65 | ||
|
f9573402a7 | ||
|
437dcc6c41 | ||
|
5a15660c77 | ||
|
0706d464b6 | ||
|
8d49b88748 | ||
|
5900affe37 | ||
|
bda3617d14 | ||
|
bd24288a12 | ||
|
3b10d66bb9 | ||
|
41b1cd7185 | ||
|
eeb233bf99 | ||
|
8b95db1574 | ||
|
37e7c618b8 | ||
|
84b90b1f4c | ||
|
4e89e88845 | ||
|
d867710cc9 | ||
|
526f54595d | ||
|
3c3f58a7be | ||
|
e4ab2156f1 | ||
|
6bba2906bc | ||
|
95cf27745b | ||
|
a9baa3b2d1 | ||
|
0186219586 | ||
|
cca428aac6 | ||
|
113e1b7a62 | ||
|
ff69fdacc7 | ||
|
6c64bc33c1 | ||
|
fda3f1be94 | ||
|
e93ae7b430 | ||
|
4ee1a3d766 | ||
|
cc10eb1f2a | ||
|
d16075f39e | ||
|
f436b5ae09 | ||
|
ceaab349f1 | ||
|
22654bf518 | ||
|
c061412138 | ||
|
89b029aa42 | ||
|
2c7bafe3c1 | ||
|
bcb7eabff3 | ||
|
e63f471c77 | ||
|
1fc72c68dd | ||
|
1bd2ab00ac | ||
|
e713e8eade | ||
|
26fa234026 | ||
|
6c24fa728e | ||
|
0fedd1dbea | ||
|
722f73dfbe | ||
|
7d6916b946 | ||
|
ada5db011c | ||
|
099141f6c5 | ||
|
6a4033b6bc |
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,6 +1,6 @@
|
||||
### Before submitting a pull request, please make sure the following is done:
|
||||
|
||||
1. Read the [contributing guide](https://github.com/vant-ui/vant/blob/3.x/.github/CONTRIBUTING.md).
|
||||
1. Read the [contributing guide](https://github.com/vant-ui/vant/blob/dev/.github/CONTRIBUTING.md).
|
||||
2. If you've added code that should be tested, add tests.
|
||||
3. If you've changed APIs, update the documentation.
|
||||
4. Ensure the test suite passes (`npm test`).
|
||||
|
@ -1,8 +1,8 @@
|
||||
name: Deploy V3 Site
|
||||
name: Deploy V4 Site
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [3.x]
|
||||
branches: [dev]
|
||||
paths:
|
||||
- 'packages/vant/docs/**'
|
||||
|
||||
@ -15,7 +15,7 @@ jobs:
|
||||
- name: Checkout 🛎️
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: '3.x'
|
||||
ref: 'next'
|
||||
|
||||
- name: Install pnpm
|
||||
run: npm i pnpm@7 -g
|
||||
@ -32,17 +32,9 @@ jobs:
|
||||
run: npm run build:site
|
||||
|
||||
- name: Deploy 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.0
|
||||
uses: JamesIves/github-pages-deploy-action@4.1.1
|
||||
with:
|
||||
branch: gh-pages
|
||||
folder: packages/vant/site-dist
|
||||
target-folder: v3
|
||||
|
||||
- name: Deploy for GitHub 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.0
|
||||
with:
|
||||
branch: main
|
||||
folder: packages/vant/site-dist
|
||||
token: ${{ secrets.VANT_UI_TOKEN }}
|
||||
repository-name: vant-ui/vant-ui.github.io
|
||||
target-folder: vant/v3
|
||||
target-folder: v4
|
||||
clean: false
|
11
README.md
11
README.md
@ -37,7 +37,7 @@
|
||||
- 🍭 Support Tree Shaking
|
||||
- 🍭 Support Custom Theme
|
||||
- 🍭 Support Accessibility (still improving)
|
||||
- 🍭 Support Dark Mode
|
||||
- 🍭 Support Dark Mode (Requires upgrade to [Vant 4](https://vant-contrib.gitee.io/vant/v4/#/en-US/config-provider))
|
||||
- 🍭 Support SSR
|
||||
- 🌍 Support i18n, built-in 20+ languages
|
||||
|
||||
@ -92,15 +92,16 @@ Vant 3/4 supports modern browsers and Chrome >= 51、iOS >= 10.0 (same as Vue 3)
|
||||
| --- | --- |
|
||||
| [vant-weapp](https://github.com/vant-ui/vant-weapp) | WeChat MiniProgram UI |
|
||||
| [vant-demo](https://github.com/vant-ui/vant-demo) | Collection of Vant demos |
|
||||
| [vant-cli](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli) | Scaffold for UI library |
|
||||
| [vant-icons](https://github.com/vant-ui/vant/tree/3.x/packages/vant-icons) | Vant icons |
|
||||
| [vant-touch-emulator](https://github.com/vant-ui/vant/tree/3.x/packages/vant-touch-emulator) | Using vant in desktop browsers |
|
||||
| [vant-cli](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli) | Scaffold for UI library |
|
||||
| [vant-icons](https://github.com/vant-ui/vant/tree/dev/packages/vant-icons) | Vant icons |
|
||||
| [vant-touch-emulator](https://github.com/vant-ui/vant/tree/dev/packages/vant-touch-emulator) | Using vant in desktop browsers |
|
||||
|
||||
## Community Ecosystem
|
||||
|
||||
| Project | Description |
|
||||
| --- | --- |
|
||||
| [3lang3/react-vant](https://github.com/3lang3/react-vant) | React mobile UI Components based on Vant |
|
||||
| [rc-ui-lib](https://github.com/rancui/rc-ui-lib) | React mobile UI Components based on Vant |
|
||||
| [vant-aliapp](https://github.com/ant-move/Vant-Aliapp) | Alipay MiniProgram UI |
|
||||
| [taroify](https://gitee.com/mallfoundry/taroify) | Vant Taro |
|
||||
| [vant-theme](https://github.com/Aisen60/vant-theme) | Online theme preview built on Vant UI |
|
||||
@ -111,7 +112,7 @@ Vant 3/4 supports modern browsers and Chrome >= 51、iOS >= 10.0 (same as Vue 3)
|
||||
|
||||
- [Documentation](https://vant-ui.github.io/vant)
|
||||
- [Changelog](https://vant-ui.github.io/vant#/en-US/changelog)
|
||||
- [Discussions](https://github.com/vant-ui/vant/discussions)
|
||||
- [Gitter](https://gitter.im/vant-contrib/discuss?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
|
||||
|
||||
## Preview
|
||||
|
||||
|
@ -41,7 +41,7 @@ Vant 是一个**轻量、可靠的移动端组件库**,于 2017 年开源。
|
||||
- 🍭 支持主题定制,内置 700+ 个主题变量
|
||||
- 🍭 支持按需引入和 Tree Shaking
|
||||
- 🍭 支持无障碍访问(持续改进中)
|
||||
- 🍭 支持深色模式
|
||||
- 🍭 支持深色模式(从 [Vant 4](https://vant-contrib.gitee.io/vant/v4/#/zh-CN/config-provider) 开始支持)
|
||||
- 🍭 支持服务器端渲染
|
||||
- 🌍 支持国际化,内置 20+ 种语言包
|
||||
|
||||
@ -98,9 +98,9 @@ Vant 3/4 支持现代浏览器以及 Chrome >= 51、iOS >= 10.0(与 Vue 3 一
|
||||
| --- | --- |
|
||||
| [vant-weapp](https://github.com/vant-ui/vant-weapp) | Vant 微信小程序版 |
|
||||
| [vant-demo](https://github.com/vant-ui/vant-demo) | Vant 官方示例合集 |
|
||||
| [vant-cli](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli) | 开箱即用的组件库搭建工具 |
|
||||
| [vant-icons](https://github.com/vant-ui/vant/tree/3.x/packages/vant-icons) | Vant 图标库 |
|
||||
| [vant-touch-emulator](https://github.com/vant-ui/vant/tree/3.x/packages/vant-touch-emulator) | 在桌面端使用 Vant 的辅助库 |
|
||||
| [vant-cli](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli) | 开箱即用的组件库搭建工具 |
|
||||
| [vant-icons](https://github.com/vant-ui/vant/tree/dev/packages/vant-icons) | Vant 图标库 |
|
||||
| [vant-touch-emulator](https://github.com/vant-ui/vant/tree/dev/packages/vant-touch-emulator) | 在桌面端使用 Vant 的辅助库 |
|
||||
|
||||
## 社区生态
|
||||
|
||||
@ -109,6 +109,7 @@ Vant 3/4 支持现代浏览器以及 Chrome >= 51、iOS >= 10.0(与 Vue 3 一
|
||||
| 项目 | 描述 |
|
||||
| --- | --- |
|
||||
| [3lang3/react-vant](https://github.com/3lang3/react-vant) | 参照 Vant 打造的 React 框架移动端组件库 |
|
||||
| [rc-ui-lib](https://github.com/rancui/rc-ui-lib) | 参照 Vant 打造的 React 框架移动端组件库 |
|
||||
| [vant-aliapp](https://github.com/ant-move/Vant-Aliapp) | Vant 支付宝小程序版 |
|
||||
| [taroify](https://gitee.com/mallfoundry/taroify) | Vant Taro 版 |
|
||||
| [vant-theme](https://github.com/Aisen60/vant-theme) | Vant 在线主题预览工具 |
|
||||
@ -119,8 +120,7 @@ Vant 3/4 支持现代浏览器以及 Chrome >= 51、iOS >= 10.0(与 Vue 3 一
|
||||
|
||||
- [详细文档](https://vant-contrib.gitee.io/vant)
|
||||
- [更新日志](https://vant-contrib.gitee.io/vant#/zh-CN/changelog)
|
||||
- [码云镜像仓库](https://gitee.com/vant-contrib/vant)
|
||||
- [Discussions 讨论区](https://github.com/vant-ui/vant/discussions)
|
||||
- [Gitter 讨论组](https://gitter.im/vant-contrib/discuss?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
|
||||
|
||||
## 手机预览
|
||||
|
||||
|
@ -65,7 +65,7 @@ Please add the followed config to `package.json` file.
|
||||
|
||||
## More Details
|
||||
|
||||
- [cli](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/docs/commands.md)
|
||||
- [config](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/docs/config.md)
|
||||
- [directory structure](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/docs/directory.md)
|
||||
- [CHANGELOG](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/changelog.md)
|
||||
- [cli](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/docs/commands.md)
|
||||
- [config](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/docs/config.md)
|
||||
- [directory structure](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/docs/directory.md)
|
||||
- [CHANGELOG](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/changelog.md)
|
||||
|
@ -62,7 +62,7 @@ pnpm add @vant/cli -D
|
||||
|
||||
## 详细文档
|
||||
|
||||
- [命令](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/docs/commands.zh-CN.md)
|
||||
- [配置指南](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/docs/config.zh-CN.md)
|
||||
- [目录结构](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/docs/directory.zh-CN.md)
|
||||
- [更新日志](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/changelog.md)
|
||||
- [命令](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/docs/commands.zh-CN.md)
|
||||
- [配置指南](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/docs/config.zh-CN.md)
|
||||
- [目录结构](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/docs/directory.zh-CN.md)
|
||||
- [更新日志](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/changelog.md)
|
||||
|
@ -29,7 +29,7 @@ Start local dev server for browsering components and demo.
|
||||
|
||||
Build Vue component library.
|
||||
|
||||
Files will be output to `es` and `lib` directory. More details [directory structure](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/docs/directory.md)
|
||||
Files will be output to `es` and `lib` directory. More details [directory structure](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/docs/directory.md)
|
||||
|
||||
Please add the followed config to `package.json` when publish to npm.
|
||||
|
||||
|
@ -31,7 +31,7 @@ npx vant-cli dev
|
||||
|
||||
构建组件库。
|
||||
|
||||
运行 build 命令会在 `es` 和 `lib` 目录下生成可用于生产环境的组件代码,详见 [目录结构](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli/docs/directory.zh-CN.md)。
|
||||
运行 build 命令会在 `es` 和 `lib` 目录下生成可用于生产环境的组件代码,详见 [目录结构](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli/docs/directory.zh-CN.md)。
|
||||
|
||||
发布 npm 时,请将以下配置加入到 `package.json` 中,使 npm 包能被正确识别:
|
||||
|
||||
|
@ -1,7 +1,4 @@
|
||||
/**
|
||||
* 同步父窗口和 iframe 的 vue-router 状态
|
||||
*/
|
||||
|
||||
import { ref } from 'vue';
|
||||
import { config } from 'site-desktop-shared';
|
||||
|
||||
let queue = [];
|
||||
@ -62,6 +59,49 @@ export function syncPathToChild() {
|
||||
}
|
||||
}
|
||||
|
||||
export function syncThemeToChild(theme) {
|
||||
const iframe = document.querySelector('iframe');
|
||||
if (iframe) {
|
||||
iframeReady(() => {
|
||||
iframe.contentWindow.postMessage(
|
||||
{
|
||||
type: 'updateTheme',
|
||||
value: theme,
|
||||
},
|
||||
'*'
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getDefaultTheme() {
|
||||
const cache = window.localStorage.getItem('vantTheme');
|
||||
|
||||
if (cache) {
|
||||
return cache;
|
||||
}
|
||||
|
||||
const useDark =
|
||||
window.matchMedia &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
return useDark ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
export function useCurrentTheme() {
|
||||
const theme = ref(getDefaultTheme());
|
||||
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data?.type !== 'updateTheme') {
|
||||
return;
|
||||
}
|
||||
|
||||
const newTheme = event.data?.value || '';
|
||||
theme.value = newTheme;
|
||||
});
|
||||
|
||||
return theme;
|
||||
}
|
||||
|
||||
export function listenToSyncPath(router) {
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data?.type !== 'replacePath') {
|
@ -1,15 +1,15 @@
|
||||
@import './var';
|
||||
@import './vars.less';
|
||||
|
||||
body {
|
||||
min-width: 1100px;
|
||||
margin: 0;
|
||||
overflow-x: auto;
|
||||
color: @van-doc-black;
|
||||
color: var(--van-doc-text-color-2);
|
||||
font-size: 16px;
|
||||
font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Helvetica Neue',
|
||||
Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui',
|
||||
'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
|
||||
background-color: @van-doc-background-color;
|
||||
background-color: var(--van-doc-background);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
@ -41,8 +41,8 @@ a {
|
||||
.van-doc-row {
|
||||
width: 100%;
|
||||
|
||||
@media (min-width: @van-doc-row-max-width) {
|
||||
width: @van-doc-row-max-width;
|
||||
@media (min-width: var(--van-doc-row-max-width)) {
|
||||
width: var(--van-doc-row-max-width);
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,18 @@
|
||||
@import './var';
|
||||
|
||||
code {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 16px 20px;
|
||||
overflow-x: auto;
|
||||
color: @van-doc-code-color;
|
||||
color: var(--van-doc-code-color);
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
font-family: @van-doc-code-font-family;
|
||||
font-family: 'Source Code Pro', 'Monaco', 'Inconsolata', monospace;
|
||||
line-height: 26px;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
-webkit-font-smoothing: auto;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: @van-doc-border-radius;
|
||||
background-color: var(--van-doc-code-background);
|
||||
border-radius: var(--van-doc-border-radius);
|
||||
}
|
||||
|
||||
pre {
|
||||
@ -33,7 +31,7 @@ pre {
|
||||
}
|
||||
|
||||
.hljs-subst {
|
||||
color: @van-doc-code-color;
|
||||
color: var(--van-doc-code-color);
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
@ -42,18 +40,18 @@ pre {
|
||||
.hljs-template-tag,
|
||||
.hljs-template-variable,
|
||||
.hljs-addition {
|
||||
color: @van-doc-green;
|
||||
color: var(--van-doc-green);
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #999;
|
||||
color: var(--van-doc-code-comment-color);
|
||||
}
|
||||
|
||||
.hljs-params,
|
||||
.hljs-keyword,
|
||||
.hljs-attribute {
|
||||
color: @van-doc-purple;
|
||||
color: var(--van-doc-purple);
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
|
@ -1,27 +0,0 @@
|
||||
@van-doc-black: #323233;
|
||||
@van-doc-blue: #1989fa;
|
||||
@van-doc-purple: #8080ff;
|
||||
@van-doc-fuchsia: #a7419e;
|
||||
@van-doc-green: #4fc08d;
|
||||
@van-doc-text-color: #34495e;
|
||||
@van-doc-text-light-blue: rgba(69, 90, 100, 0.6);
|
||||
@van-doc-background-color: #f7f8fa;
|
||||
@van-doc-grey: #999;
|
||||
@van-doc-dark-grey: #666;
|
||||
@van-doc-light-grey: #ccc;
|
||||
@van-doc-border-color: #f1f4f8;
|
||||
@van-doc-code-color: #58727e;
|
||||
@van-doc-code-background-color: #f1f4f8;
|
||||
@van-doc-code-font-family: 'Source Code Pro', 'Monaco', 'Inconsolata', monospace;
|
||||
@van-doc-padding: 24px;
|
||||
@van-doc-row-max-width: 1680px;
|
||||
@van-doc-nav-width: 220px;
|
||||
@van-doc-border-radius: 20px;
|
||||
|
||||
// header
|
||||
@van-doc-header-top-height: 64px;
|
||||
@van-doc-header-bottom-height: 50px;
|
||||
|
||||
// simulator
|
||||
@van-doc-simulator-width: 360px;
|
||||
@van-doc-simulator-height: 620px;
|
74
packages/vant-cli/site/common/style/vars.less
Normal file
74
packages/vant-cli/site/common/style/vars.less
Normal file
@ -0,0 +1,74 @@
|
||||
body {
|
||||
// colors
|
||||
--van-doc-black: #000;
|
||||
--van-doc-white: #fff;
|
||||
--van-doc-gray-1: #f7f8fa;
|
||||
--van-doc-gray-2: #f2f3f5;
|
||||
--van-doc-gray-3: #ebedf0;
|
||||
--van-doc-gray-4: #dcdee0;
|
||||
--van-doc-gray-5: #c8c9cc;
|
||||
--van-doc-gray-6: #969799;
|
||||
--van-doc-gray-7: #646566;
|
||||
--van-doc-gray-8: #323233;
|
||||
--van-doc-blue: #1989fa;
|
||||
--van-doc-green: #07c160;
|
||||
|
||||
// sizes
|
||||
--van-doc-padding: 24px;
|
||||
--van-doc-row-max-width: 1680px;
|
||||
--van-doc-nav-width: 220px;
|
||||
--van-doc-border-radius: 20px;
|
||||
--van-doc-simulator-width: 360px;
|
||||
--van-doc-simulator-height: 620px;
|
||||
--van-doc-header-top-height: 64px;
|
||||
}
|
||||
|
||||
.van-doc-theme-light {
|
||||
// text
|
||||
--van-doc-text-color-1: var(--van-doc-black);
|
||||
--van-doc-text-color-2: var(--van-doc-gray-8);
|
||||
--van-doc-text-color-3: #34495e;
|
||||
--van-doc-text-color-4: var(--van-doc-gray-6);
|
||||
--van-doc-link-color: var(--van-doc-blue);
|
||||
|
||||
// background
|
||||
--van-doc-background: #eff2f5;
|
||||
--van-doc-background-2: var(--van-doc-white);
|
||||
--van-doc-background-3: var(--van-doc-white);
|
||||
--van-doc-header-background: #011f3c;
|
||||
--van-doc-border-color: var(--van-doc-gray-2);
|
||||
|
||||
// code
|
||||
--van-doc-code-color: #58727e;
|
||||
--van-doc-code-comment-color: var(--van-doc-gray-6);
|
||||
--van-doc-code-background: var(--van-doc-gray-1);
|
||||
|
||||
// blockquote
|
||||
--van-doc-blockquote-color: #4994df;
|
||||
--van-doc-blockquote-background: #ecf9ff;
|
||||
}
|
||||
|
||||
.van-doc-theme-dark {
|
||||
// text
|
||||
--van-doc-text-color-1: var(--van-doc-white);
|
||||
--van-doc-text-color-2: rgba(255, 255, 255, 0.9);
|
||||
--van-doc-text-color-3: rgba(255, 255, 255, 0.75);
|
||||
--van-doc-text-color-4: rgba(255, 255, 255, 0.6);
|
||||
--van-doc-link-color: #1bb5fe;
|
||||
|
||||
// background
|
||||
--van-doc-background: #202124;
|
||||
--van-doc-background-2: rgba(255, 255, 255, 0.06);
|
||||
--van-doc-background-3: rgba(255, 255, 255, 0.1);
|
||||
--van-doc-header-background: rgba(1, 31, 60, 0.3);
|
||||
--van-doc-border-color: #3a3a3c;
|
||||
|
||||
// code
|
||||
--van-doc-code-color: rgba(200, 200, 200, 0.85);
|
||||
--van-doc-code-comment-color: var(--van-doc-gray-7);
|
||||
--van-doc-code-background: rgba(0, 0, 0, 0.24);
|
||||
|
||||
// blockquote
|
||||
--van-doc-blockquote-color: #bae6fd;
|
||||
--van-doc-blockquote-background: rgba(7, 89, 133, 0.25);
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
:simulator="simulator"
|
||||
:has-simulator="hasSimulator"
|
||||
:lang-configs="langConfigs"
|
||||
:dark-mode-class="darkModeClass"
|
||||
>
|
||||
<router-view />
|
||||
</van-doc>
|
||||
@ -27,6 +28,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
hasSimulator: true,
|
||||
darkModeClass: config.site.darkModeClass,
|
||||
};
|
||||
},
|
||||
|
||||
@ -70,18 +72,18 @@ export default {
|
||||
watch: {
|
||||
// eslint-disable-next-line
|
||||
'$route.path'() {
|
||||
this.setTitleAndToogleSimulator();
|
||||
this.setTitleAndToggleSimulator();
|
||||
},
|
||||
|
||||
lang(val) {
|
||||
setLang(val);
|
||||
this.setTitleAndToogleSimulator();
|
||||
this.setTitleAndToggleSimulator();
|
||||
},
|
||||
|
||||
config: {
|
||||
handler(val) {
|
||||
if (val) {
|
||||
this.setTitleAndToogleSimulator();
|
||||
this.setTitleAndToggleSimulator();
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
@ -100,7 +102,7 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
setTitleAndToogleSimulator() {
|
||||
setTitleAndToggleSimulator() {
|
||||
let { title } = this.config;
|
||||
|
||||
const navItems = this.config.nav.reduce(
|
||||
|
@ -18,18 +18,18 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.van-doc-container {
|
||||
box-sizing: border-box;
|
||||
padding-left: @van-doc-nav-width;
|
||||
padding-left: var(--van-doc-nav-width);
|
||||
overflow: hidden;
|
||||
|
||||
&--with-simulator {
|
||||
padding-right: @van-doc-simulator-width + @van-doc-padding;
|
||||
padding-right: calc(
|
||||
var(--van-doc-simulator-width) + var(--van-doc-padding)
|
||||
);
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
padding-right: @van-doc-simulator-width - 8px;
|
||||
padding-right: calc(var(--van-doc-simulator-width) - 8px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,14 +82,11 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.van-doc-card {
|
||||
margin-bottom: 24px;
|
||||
padding: 24px;
|
||||
background-color: #fff;
|
||||
border-radius: @van-doc-border-radius;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
background-color: var(--van-doc-background-2);
|
||||
border-radius: var(--van-doc-border-radius);
|
||||
overflow: auto;
|
||||
|
||||
> pre code {
|
||||
@ -145,15 +142,15 @@ export default {
|
||||
> table a,
|
||||
> blockquote a {
|
||||
margin: 0 1px;
|
||||
color: @van-doc-blue;
|
||||
color: var(--van-doc-link-color);
|
||||
-webkit-font-smoothing: auto;
|
||||
|
||||
&:hover {
|
||||
color: darken(@van-doc-blue, 10%);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: darken(@van-doc-blue, 20%);
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,7 +158,6 @@ export default {
|
||||
> h4,
|
||||
> h5,
|
||||
> h6 {
|
||||
color: @van-doc-black;
|
||||
font-weight: normal;
|
||||
line-height: 1.6;
|
||||
|
||||
@ -190,23 +186,19 @@ export default {
|
||||
|
||||
> p {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
> p,
|
||||
> blockquote p {
|
||||
color: @van-doc-text-color;
|
||||
color: var(--van-doc-text-color-3);
|
||||
font-size: 15px;
|
||||
line-height: 26px;
|
||||
|
||||
strong {
|
||||
color: black;
|
||||
color: var(--van-doc-text-color-1);
|
||||
}
|
||||
}
|
||||
|
||||
> table {
|
||||
width: 100%;
|
||||
margin-top: 12px;
|
||||
color: @van-doc-text-color;
|
||||
color: var(--van-doc-text-color-3);
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
border-collapse: collapse;
|
||||
@ -227,7 +219,7 @@ export default {
|
||||
|
||||
td {
|
||||
padding: 8px;
|
||||
border-top: 1px solid @van-doc-code-background-color;
|
||||
border-top: 1px solid var(--van-doc-border-color);
|
||||
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
@ -236,10 +228,10 @@ export default {
|
||||
code {
|
||||
margin: 0;
|
||||
padding: 2px 6px;
|
||||
color: @van-doc-blue;
|
||||
color: var(--van-doc-blue);
|
||||
font-weight: 600;
|
||||
font-size: 11px;
|
||||
background-color: fade(@van-doc-blue, 10%);
|
||||
background-color: rgba(25, 137, 250, 0.15);
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
@ -251,9 +243,9 @@ export default {
|
||||
|
||||
em {
|
||||
display: inline-block;
|
||||
color: @van-doc-green;
|
||||
color: var(--van-doc-green);
|
||||
font-size: 14px;
|
||||
font-family: @van-doc-code-font-family;
|
||||
font-family: 'Source Code Pro', 'Monaco', 'Inconsolata', monospace;
|
||||
font-style: normal;
|
||||
max-width: 300px;
|
||||
-webkit-font-smoothing: auto;
|
||||
@ -269,7 +261,7 @@ export default {
|
||||
position: relative;
|
||||
margin: 5px 0 5px 10px;
|
||||
padding-left: 15px;
|
||||
color: @van-doc-text-color;
|
||||
color: var(--van-doc-text-color-3);
|
||||
font-size: 15px;
|
||||
line-height: 26px;
|
||||
|
||||
@ -281,7 +273,7 @@ export default {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-top: 10px;
|
||||
border: 1px solid @van-doc-dark-grey;
|
||||
border: 1px solid currentColor;
|
||||
border-radius: 50%;
|
||||
content: '';
|
||||
}
|
||||
@ -311,15 +303,17 @@ export default {
|
||||
> blockquote {
|
||||
margin: 16px 0 0;
|
||||
padding: 16px;
|
||||
background-color: #ecf9ff;
|
||||
border-radius: @van-doc-border-radius;
|
||||
font-size: 14px;
|
||||
color: var(--van-doc-blockquote-color);
|
||||
background-color: var(--van-doc-blockquote-background);
|
||||
border-radius: var(--van-doc-border-radius);
|
||||
}
|
||||
|
||||
> img,
|
||||
> p img {
|
||||
width: 100%;
|
||||
margin: 16px 0;
|
||||
border-radius: @van-doc-border-radius;
|
||||
border-radius: var(--van-doc-border-radius);
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,7 +328,6 @@ export default {
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
color: @van-doc-black;
|
||||
font-weight: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
|
@ -24,6 +24,16 @@
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li v-if="darkModeClass" class="van-doc-header__top-nav-item">
|
||||
<a
|
||||
class="van-doc-header__link"
|
||||
target="_blank"
|
||||
@click="toggleTheme"
|
||||
>
|
||||
<img :src="themeImg" />
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li
|
||||
ref="version"
|
||||
v-if="versions"
|
||||
@ -69,6 +79,7 @@
|
||||
<script>
|
||||
import SearchInput from './SearchInput.vue';
|
||||
import { packageVersion } from 'site-desktop-shared';
|
||||
import { getDefaultTheme, syncThemeToChild } from '../../common/iframe-sync';
|
||||
|
||||
export default {
|
||||
name: 'VanDocHeader',
|
||||
@ -82,10 +93,12 @@ export default {
|
||||
config: Object,
|
||||
versions: Array,
|
||||
langConfigs: Array,
|
||||
darkModeClass: String,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
currentTheme: getDefaultTheme(),
|
||||
packageVersion,
|
||||
showVersionPop: false,
|
||||
};
|
||||
@ -112,9 +125,32 @@ export default {
|
||||
searchConfig() {
|
||||
return this.config.searchConfig;
|
||||
},
|
||||
|
||||
themeImg() {
|
||||
if (this.currentTheme === 'light') {
|
||||
return 'https://b.yzcdn.cn/vant/dark-theme.svg';
|
||||
}
|
||||
return 'https://b.yzcdn.cn/vant/light-theme.svg';
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
currentTheme: {
|
||||
handler(newVal, oldVal) {
|
||||
window.localStorage.setItem('vantTheme', newVal);
|
||||
document.body.classList.remove(`van-doc-theme-${oldVal}`);
|
||||
document.body.classList.add(`van-doc-theme-${newVal}`);
|
||||
syncThemeToChild(newVal);
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleTheme() {
|
||||
this.currentTheme = this.currentTheme === 'light' ? 'dark' : 'light';
|
||||
},
|
||||
|
||||
toggleVersionPop() {
|
||||
const val = !this.showVersionPop;
|
||||
|
||||
@ -147,18 +183,16 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.van-doc-header {
|
||||
width: 100%;
|
||||
background-color: #001938;
|
||||
background-color: var(--van-doc-header-background);
|
||||
user-select: none;
|
||||
|
||||
&__top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: @van-doc-header-top-height;
|
||||
padding: 0 @van-doc-padding;
|
||||
height: var(--van-doc-header-top-height);
|
||||
padding: 0 var(--van-doc-padding);
|
||||
|
||||
&-nav {
|
||||
flex: 1;
|
||||
@ -234,7 +268,7 @@ export default {
|
||||
transition: 0.2s;
|
||||
|
||||
&:hover {
|
||||
color: @van-doc-blue;
|
||||
color: var(--van-doc-link-color);
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
}
|
||||
@ -268,6 +302,8 @@ export default {
|
||||
}
|
||||
|
||||
&__link {
|
||||
cursor: pointer;
|
||||
|
||||
span {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
|
@ -71,22 +71,19 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.van-doc-nav {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
min-width: @van-doc-nav-width;
|
||||
max-width: @van-doc-nav-width;
|
||||
padding: @van-doc-padding 0;
|
||||
min-width: var(--van-doc-nav-width);
|
||||
max-width: var(--van-doc-nav-width);
|
||||
padding: 8px 0;
|
||||
overflow-y: scroll;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
background-color: var(--van-doc-background-2);
|
||||
|
||||
@media (min-width: @van-doc-row-max-width) {
|
||||
@media (min-width: var(--van-doc-row-max-width)) {
|
||||
left: 50%;
|
||||
margin-left: -(@van-doc-row-max-width / 2);
|
||||
margin-left: calc((var(--van-doc-row-max-width) / 2 * -1));
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
@ -110,8 +107,8 @@ export default {
|
||||
}
|
||||
|
||||
&__title {
|
||||
padding: 8px 0 8px @van-doc-padding;
|
||||
color: #455a64;
|
||||
padding: 24px 0 0 var(--van-doc-padding);
|
||||
color: var(--van-doc-text-color-2);
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
line-height: 28px;
|
||||
@ -121,21 +118,19 @@ export default {
|
||||
a {
|
||||
display: block;
|
||||
margin: 8px 0;
|
||||
padding: 8px 0 8px @van-doc-padding;
|
||||
color: #455a64;
|
||||
padding: 6px 0 6px var(--van-doc-padding);
|
||||
color: var(--van-doc-text-color-3);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
transition: color 0.2s;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
color: @van-doc-green;
|
||||
color: var(--van-doc-link-color);
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: 600;
|
||||
background-color: #ebfff0;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
span {
|
||||
|
@ -38,8 +38,6 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
#docsearch {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
@ -44,34 +44,31 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.van-doc-simulator {
|
||||
position: absolute;
|
||||
top: @van-doc-padding + @van-doc-header-top-height;
|
||||
right: @van-doc-padding;
|
||||
top: calc(var(--van-doc-padding) + var(--van-doc-header-top-height));
|
||||
right: var(--van-doc-padding);
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
width: @van-doc-simulator-width;
|
||||
min-width: @van-doc-simulator-width;
|
||||
width: var(--van-doc-simulator-width);
|
||||
min-width: var(--van-doc-simulator-width);
|
||||
overflow: hidden;
|
||||
background: #fafafa;
|
||||
border-radius: @van-doc-border-radius;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
background: var(--van-doc-background-2);
|
||||
border-radius: var(--van-doc-border-radius);
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
right: auto;
|
||||
left: 750px;
|
||||
}
|
||||
|
||||
@media (min-width: @van-doc-row-max-width) {
|
||||
@media (min-width: var(--van-doc-row-max-width)) {
|
||||
right: 50%;
|
||||
margin-right: -(@van-doc-row-max-width / 2) + 24px;
|
||||
margin-right: calc(var(--van-doc-row-max-width) / 2 * -1 + 24px);
|
||||
}
|
||||
|
||||
&-fixed {
|
||||
position: fixed;
|
||||
top: @van-doc-padding;
|
||||
top: var(--van-doc-padding);
|
||||
}
|
||||
|
||||
iframe {
|
||||
|
@ -5,6 +5,7 @@
|
||||
:config="config"
|
||||
:versions="versions"
|
||||
:lang-configs="langConfigs"
|
||||
:dark-mode-class="darkModeClass"
|
||||
@switch-version="$emit('switch-version', $event)"
|
||||
/>
|
||||
<doc-nav :lang="lang" :nav-config="config.nav" />
|
||||
@ -39,8 +40,9 @@ export default {
|
||||
lang: String,
|
||||
versions: Array,
|
||||
simulator: String,
|
||||
hasSimulator: Boolean,
|
||||
langConfigs: Array,
|
||||
hasSimulator: Boolean,
|
||||
darkModeClass: String,
|
||||
config: {
|
||||
type: Object,
|
||||
required: true,
|
||||
@ -108,7 +110,3 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
</style>
|
||||
|
@ -3,7 +3,7 @@ import { createRouter, createWebHashHistory } from 'vue-router';
|
||||
import { isMobile, decamelize } from '../common';
|
||||
import { config, documents } from 'site-desktop-shared';
|
||||
import { getLang, setDefaultLang } from '../common/locales';
|
||||
import { listenToSyncPath, syncPathToChild } from '../common/iframe-router';
|
||||
import { listenToSyncPath, syncPathToChild } from '../common/iframe-sync';
|
||||
|
||||
if (isMobile) {
|
||||
location.replace('mobile.html' + location.hash);
|
||||
|
@ -10,21 +10,49 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { watch } from 'vue';
|
||||
import DemoNav from './components/DemoNav.vue';
|
||||
import { useCurrentTheme } from '../common/iframe-sync';
|
||||
import { config } from 'site-mobile-shared';
|
||||
|
||||
export default {
|
||||
components: { DemoNav },
|
||||
|
||||
setup() {
|
||||
const theme = useCurrentTheme();
|
||||
|
||||
watch(
|
||||
theme,
|
||||
(newVal, oldVal) => {
|
||||
document.body.classList.remove(`van-doc-theme-${oldVal}`);
|
||||
document.body.classList.add(`van-doc-theme-${newVal}`);
|
||||
|
||||
const { darkModeClass } = config.site;
|
||||
if (darkModeClass) {
|
||||
document.body.classList.toggle(darkModeClass, newVal === 'dark');
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../common/style/var';
|
||||
@import '../common/style/base';
|
||||
|
||||
body {
|
||||
min-width: 100vw;
|
||||
}
|
||||
|
||||
.van-doc-theme-light {
|
||||
background-color: var(--van-doc-gray-1);
|
||||
}
|
||||
|
||||
.van-doc-theme-dark {
|
||||
background-color: var(--van-doc-black);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0;
|
||||
background: transparent;
|
||||
|
@ -20,13 +20,11 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.van-doc-demo-block {
|
||||
&__title {
|
||||
margin: 0;
|
||||
padding: 32px 16px 16px;
|
||||
color: @van-doc-text-light-blue;
|
||||
color: var(--van-doc-text-color-4);
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
|
@ -52,14 +52,11 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.demo-home {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
padding: 46px 20px 20px;
|
||||
background: #fff;
|
||||
|
||||
&__title,
|
||||
&__desc {
|
||||
@ -94,7 +91,7 @@ export default {
|
||||
|
||||
&__desc {
|
||||
margin: 0 0 40px;
|
||||
color: rgba(69, 90, 100, 0.6);
|
||||
color: var(--van-doc-text-color-4);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
@ -43,12 +43,10 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.demo-home-nav {
|
||||
&__title {
|
||||
margin: 24px 0 8px 16px;
|
||||
color: rgba(69, 90, 100, 0.6);
|
||||
color: var(--van-doc-text-color-4);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@ -57,20 +55,20 @@ export default {
|
||||
display: flex;
|
||||
margin: 0 0 12px;
|
||||
padding-left: 20px;
|
||||
color: #323233;
|
||||
color: var(--van-doc-text-color-3);
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
background: #f7f8fa;
|
||||
background-color: var(--van-doc-background-3);
|
||||
border-radius: 99px;
|
||||
transition: background 0.3s;
|
||||
transition: opacity 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: darken(#f7f8fa, 3%);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: darken(#f7f8fa, 6%);
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 56px;
|
||||
background-color: #fff;
|
||||
background-color: var(--van-doc-background-3);
|
||||
|
||||
&__title {
|
||||
font-weight: 600;
|
||||
|
@ -4,7 +4,7 @@ import DemoHome from './components/DemoHome.vue';
|
||||
import { decamelize } from '../common';
|
||||
import { demos, config } from 'site-mobile-shared';
|
||||
import { getLang, setDefaultLang } from '../common/locales';
|
||||
import { listenToSyncPath, syncPathToParent } from '../common/iframe-router';
|
||||
import { listenToSyncPath, syncPathToParent } from '../common/iframe-sync';
|
||||
|
||||
const { locales, defaultLang } = config.site;
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
import glob from 'fast-glob';
|
||||
import { join, parse } from 'path';
|
||||
import { existsSync, readFileSync, readdirSync } from 'fs';
|
||||
import { pascalize, getVantConfig, normalizePath } from '../common/index.js';
|
||||
import {
|
||||
isDev,
|
||||
pascalize,
|
||||
getVantConfig,
|
||||
normalizePath,
|
||||
} from '../common/index.js';
|
||||
import {
|
||||
SRC_DIR,
|
||||
DOCS_DIR,
|
||||
@ -75,7 +80,10 @@ function genImportDocuments(items: DocumentItem[]) {
|
||||
return items
|
||||
.map((item) => {
|
||||
const path = normalizePath(item.path);
|
||||
return `const ${item.name} = () => import('${path}');`;
|
||||
if (isDev()) {
|
||||
return `const ${item.name} = () => import('${path}');`;
|
||||
}
|
||||
return `import ${item.name} from '${path}';`;
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
|
10
packages/vant-compat/LICENSE
Normal file
10
packages/vant-compat/LICENSE
Normal file
@ -0,0 +1,10 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Youzan
|
||||
Copyright (c) Chen Jiahan and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
32
packages/vant-compat/README.md
Normal file
32
packages/vant-compat/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
# @vant/compat
|
||||
|
||||
This package provides Vant 3 compatible behavior for Vant 4 users.
|
||||
|
||||
## Install
|
||||
|
||||
```shell
|
||||
# with npm
|
||||
npm i @vant/compat
|
||||
|
||||
# with yarn
|
||||
yarn add @vant/compat
|
||||
|
||||
# with pnpm
|
||||
pnpm add @vant/compat
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
// Same as Toast in Vant 3
|
||||
import { Toast } from '@vant/compat';
|
||||
|
||||
// Same as Dialog in Vant 3
|
||||
import { Dialog } from '@vant/compat';
|
||||
|
||||
// Same as Notify in Vant 3
|
||||
import { Notify } from '@vant/compat';
|
||||
|
||||
// Same as ImagePreview in Vant 3
|
||||
import { ImagePreview } from '@vant/compat';
|
||||
```
|
1
packages/vant-compat/build.js
Normal file
1
packages/vant-compat/build.js
Normal file
@ -0,0 +1 @@
|
||||
require('../vant-use/build');
|
52
packages/vant-compat/package.json
Normal file
52
packages/vant-compat/package.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "@vant/compat",
|
||||
"version": "1.0.0",
|
||||
"description": "Provide Vant 3 compatible behavior for Vant 4",
|
||||
"main": "dist/index.cjs.js",
|
||||
"module": "dist/index.esm.mjs",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.esm.mjs",
|
||||
"require": "./dist/index.cjs.js"
|
||||
}
|
||||
},
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf ./dist",
|
||||
"dev": "node ./build.js -w",
|
||||
"build:types": "tsc -p ./tsconfig.json --emitDeclarationOnly",
|
||||
"build:bundle": "node ./build.js",
|
||||
"build": "pnpm clean && pnpm build:bundle && pnpm build:types",
|
||||
"release": "pnpm build && release-it"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vant-ui/vant.git",
|
||||
"directory": "packages/vant-compat"
|
||||
},
|
||||
"bugs": "https://github.com/vant-ui/vant/issues",
|
||||
"author": "chenjiahan",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@vue/runtime-core": "^3.2.27",
|
||||
"vant": "workspace:*",
|
||||
"vue": "^3.2.27",
|
||||
"esbuild": "^0.14.29",
|
||||
"release-it": "^15.1.1",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"release-it": {
|
||||
"git": {
|
||||
"tag": false,
|
||||
"commitMessage": "release: @vant/compat ${version}"
|
||||
}
|
||||
}
|
||||
}
|
30
packages/vant-compat/src/dialog.ts
Normal file
30
packages/vant-compat/src/dialog.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import {
|
||||
Dialog as VanDialog,
|
||||
showDialog,
|
||||
closeDialog,
|
||||
showConfirmDialog,
|
||||
setDialogDefaultOptions,
|
||||
resetDialogDefaultOptions,
|
||||
} from 'vant';
|
||||
import type { App } from 'vue';
|
||||
|
||||
export const Dialog = (...args: Parameters<typeof showDialog>) =>
|
||||
showDialog(...args);
|
||||
|
||||
Dialog.Component = VanDialog;
|
||||
Dialog.alert = Dialog;
|
||||
Dialog.config = showConfirmDialog;
|
||||
Dialog.close = closeDialog;
|
||||
Dialog.setDefaultOptions = setDialogDefaultOptions;
|
||||
Dialog.resetDefaultOptions = resetDialogDefaultOptions;
|
||||
|
||||
Dialog.install = (app: App) => {
|
||||
app.use(Dialog.Component);
|
||||
app.config.globalProperties.$dialog = Dialog;
|
||||
};
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$dialog: typeof Dialog;
|
||||
}
|
||||
}
|
11
packages/vant-compat/src/image-preview.ts
Normal file
11
packages/vant-compat/src/image-preview.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { ImagePreview as VanImagePreview, showImagePreview } from 'vant';
|
||||
import type { App } from 'vue';
|
||||
|
||||
export const ImagePreview = (...args: Parameters<typeof showImagePreview>) =>
|
||||
showImagePreview(...args);
|
||||
|
||||
ImagePreview.Component = VanImagePreview;
|
||||
|
||||
ImagePreview.install = (app: App) => {
|
||||
app.use(ImagePreview.Component);
|
||||
};
|
4
packages/vant-compat/src/index.ts
Normal file
4
packages/vant-compat/src/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './toast';
|
||||
export * from './notify';
|
||||
export * from './dialog';
|
||||
export * from './image-preview';
|
27
packages/vant-compat/src/notify.ts
Normal file
27
packages/vant-compat/src/notify.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import {
|
||||
Notify as VanNotify,
|
||||
showNotify,
|
||||
closeNotify,
|
||||
setNotifyDefaultOptions,
|
||||
resetNotifyDefaultOptions,
|
||||
} from 'vant';
|
||||
import type { App } from 'vue';
|
||||
|
||||
export const Notify = (...args: Parameters<typeof showNotify>) =>
|
||||
showNotify(...args);
|
||||
|
||||
Notify.clear = closeNotify;
|
||||
Notify.Component = VanNotify;
|
||||
Notify.setDefaultOptions = setNotifyDefaultOptions;
|
||||
Notify.resetDefaultOptions = resetNotifyDefaultOptions;
|
||||
|
||||
Notify.install = (app: App) => {
|
||||
app.use(Notify.Component);
|
||||
app.config.globalProperties.$notify = Notify;
|
||||
};
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$notify: typeof Notify;
|
||||
}
|
||||
}
|
49
packages/vant-compat/src/toast.ts
Normal file
49
packages/vant-compat/src/toast.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import {
|
||||
showToast,
|
||||
closeToast,
|
||||
showFailToast,
|
||||
showSuccessToast,
|
||||
allowMultipleToast,
|
||||
setToastDefaultOptions,
|
||||
resetToastDefaultOptions,
|
||||
} from 'vant';
|
||||
import type { App } from 'vue';
|
||||
|
||||
export const Toast = (...args: Parameters<typeof showToast>) => {
|
||||
const toast = showToast(...args);
|
||||
return {
|
||||
clear: toast.close,
|
||||
...toast,
|
||||
};
|
||||
};
|
||||
|
||||
Toast.fail = (...args: Parameters<typeof showFailToast>) => {
|
||||
const toast = showFailToast(...args);
|
||||
return {
|
||||
clear: toast.close,
|
||||
...toast,
|
||||
};
|
||||
};
|
||||
|
||||
Toast.success = (...args: Parameters<typeof showSuccessToast>) => {
|
||||
const toast = showSuccessToast(...args);
|
||||
return {
|
||||
clear: toast.close,
|
||||
...toast,
|
||||
};
|
||||
};
|
||||
|
||||
Toast.clear = closeToast;
|
||||
Toast.allowMultiple = allowMultipleToast;
|
||||
Toast.setDefaultOptions = setToastDefaultOptions;
|
||||
Toast.resetDefaultOptions = resetToastDefaultOptions;
|
||||
|
||||
Toast.install = (app: App) => {
|
||||
app.config.globalProperties.$toast = Toast;
|
||||
};
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$toast: typeof Toast;
|
||||
}
|
||||
}
|
8
packages/vant-compat/tsconfig.json
Normal file
8
packages/vant-compat/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
@ -31,7 +31,7 @@
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vant-ui/vant.git",
|
||||
"directory": "packages/vant-markdown-loader"
|
||||
"directory": "packages/vant-popperjs"
|
||||
},
|
||||
"bugs": "https://github.com/vant-ui/vant/issues",
|
||||
"author": "chenjiahan",
|
||||
|
@ -14,7 +14,7 @@ function bundleBundle(format) {
|
||||
outfile,
|
||||
// preserve Chinese character
|
||||
charset: 'utf8',
|
||||
external: ['vue'],
|
||||
external: ['vue', 'vant'],
|
||||
entryPoints: ['./src/index.ts'],
|
||||
}).then(finish);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ref, Ref } from 'vue';
|
||||
import { inBrowser } from '../utils';
|
||||
|
||||
type VisibilityState = "hidden" | "visible";
|
||||
type VisibilityState = 'hidden' | 'visible';
|
||||
|
||||
let visibility: Ref<VisibilityState>;
|
||||
|
||||
|
Binary file not shown.
@ -132,7 +132,7 @@ module.exports = {
|
||||
|
||||
### Adapt to PC Browsers
|
||||
|
||||
Vant is a mobile-first component library, if you want to use Vant in PC browsers, you can use the [@vant/touch-emulator](https://github.com/vant-ui/vant/tree/3.x/packages/vant-touch-emulator) module. This module will automatically convert the mouse events of the PC browser into the touch events of the mobile browser.
|
||||
Vant is a mobile-first component library, if you want to use Vant in PC browsers, you can use the [@vant/touch-emulator](https://github.com/vant-ui/vant/tree/dev/packages/vant-touch-emulator) module. This module will automatically convert the mouse events of the PC browser into the touch events of the mobile browser.
|
||||
|
||||
```bash
|
||||
# Install
|
||||
|
@ -197,7 +197,7 @@ module.exports = {
|
||||
|
||||
Vant 是一个面向移动端的组件库,因此默认只适配了移动端设备,这意味着组件只监听了移动端的 `touch` 事件,没有监听桌面端的 `mouse` 事件。
|
||||
|
||||
如果你需要在桌面端使用 Vant,可以引入我们提供的 [@vant/touch-emulator](https://github.com/vant-ui/vant/tree/3.x/packages/vant-touch-emulator),这个库会在桌面端自动将 `mouse` 事件转换成对应的 `touch` 事件,使得组件能够在桌面端使用。
|
||||
如果你需要在桌面端使用 Vant,可以引入我们提供的 [@vant/touch-emulator](https://github.com/vant-ui/vant/tree/dev/packages/vant-touch-emulator),这个库会在桌面端自动将 `mouse` 事件转换成对应的 `touch` 事件,使得组件能够在桌面端使用。
|
||||
|
||||
```bash
|
||||
# 安装模块
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ Contains color specifications, font specifications, and component design specifi
|
||||
|
||||
<img src="https://fastly.jsdelivr.net/npm/@vant/assets/tab_202009101415.png" style="width: 80%; box-shadow: 0 1px 2px rgba(0,0,0,.2)">
|
||||
|
||||
<a class="design-download" href="https://github.com/vant-ui/vant/blob/3.x/packages/vant/docs/assets/design.sketch?raw=true">Download</a>
|
||||
<a class="design-download" href="https://github.com/vant-ui/vant/blob/dev/packages/vant/docs/assets/design.sketch?raw=true">Download</a>
|
||||
|
||||
### Icons (Sketch)
|
||||
|
||||
@ -30,7 +30,7 @@ Contains icon library resources.
|
||||
|
||||
<img src="https://fastly.jsdelivr.net/npm/@vant/assets/design-icons-0321.png" style="width: 80%; box-shadow: 0 1px 2px rgba(0,0,0,.2)">
|
||||
|
||||
<a class="design-download" href="https://github.com/vant-ui/vant/blob/3.x/packages/vant-icons/assets/icons.sketch?raw=true">Download</a>
|
||||
<a class="design-download" href="https://github.com/vant-ui/vant/blob/dev/packages/vant-icons/assets/icons.sketch?raw=true">Download</a>
|
||||
|
||||
### Axure
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
<img src="https://fastly.jsdelivr.net/npm/@vant/assets/tab_202009101415.png" style="width: 80%; box-shadow: 0 1px 2px rgba(0,0,0,.2)">
|
||||
|
||||
<a class="design-download" href="https://github.com/vant-ui/vant/blob/3.x/packages/vant/docs/assets/design.sketch?raw=true">下载</a>
|
||||
<a class="design-download" href="https://github.com/vant-ui/vant/blob/dev/packages/vant/docs/assets/design.sketch?raw=true">下载</a>
|
||||
|
||||
### 图标设计稿(Sketch)
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
<img src="https://fastly.jsdelivr.net/npm/@vant/assets/design-icons-0321.png" style="width: 80%; box-shadow: 0 1px 2px rgba(0,0,0,.2)">
|
||||
|
||||
<a class="design-download" href="https://github.com/vant-ui/vant/blob/3.x/packages/vant-icons/assets/icons.sketch?raw=true">下载</a>
|
||||
<a class="design-download" href="https://github.com/vant-ui/vant/blob/dev/packages/vant-icons/assets/icons.sketch?raw=true">下载</a>
|
||||
|
||||
#### 在线资源
|
||||
|
||||
|
@ -68,12 +68,6 @@ Select 是桌面端常用的组件,但它的交互形式不适合移动端。
|
||||
|
||||
在移动端,我们推荐使用 [Picker 选择器组件](#/zh-CN/picker) 作为代替。
|
||||
|
||||
### 是否支持在 uni-app 中使用?
|
||||
|
||||
Vant 所有组件都是基于 Vue 框架实现的,没有针对 uni-app 进行适配,因此不保证各个组件在 uni-app 下的可用性。
|
||||
|
||||
如果你在 uni-app 中使用 Vant 遇到问题,建议向 uni-app 进行反馈。
|
||||
|
||||
### 部分组件无法在桌面端进行操作?
|
||||
|
||||
参见[桌面端适配](#/zh-CN/advanced-usage#zhuo-mian-duan-gua-pei)。
|
||||
|
@ -19,7 +19,7 @@
|
||||
- 🍭 Support Tree Shaking
|
||||
- 🍭 Support Custom Theme
|
||||
- 🍭 Support Accessibility (still improving)
|
||||
- 🍭 Support Dark Mode
|
||||
- 🍭 Support Dark Mode (Requires upgrade to [Vant 4](https://vant-contrib.gitee.io/vant/v4/#/en-US/config-provider))
|
||||
- 🍭 Support SSR
|
||||
- 🌍 Support i18n, built-in 20+ languages
|
||||
|
||||
@ -33,17 +33,6 @@ Vant 2 supports modern browsers and Android >= 4.0、iOS >= 8.0.
|
||||
|
||||
Vant 3/4 supports modern browsers and Chrome >= 51、iOS >= 10.0 (same as Vue 3).
|
||||
|
||||
### Maintenance Status
|
||||
|
||||
The current maintenance status of each version of Vant is as follows:
|
||||
|
||||
| Name | Framework | Release | Latest Version | Status |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Vant 4 | Vue 3 | `2022.11` |  | Under active development |
|
||||
| Vant 3 | Vue 3 | `2020.12` |  | Bugfix only |
|
||||
| Vant 2 | Vue 2 | `2019.06` |  | Bugfix only |
|
||||
| Vant 1 | Vue 2 | `2018.03` |  | End of life |
|
||||
|
||||
## Links
|
||||
|
||||
### Official Ecosystem
|
||||
@ -52,15 +41,16 @@ The current maintenance status of each version of Vant is as follows:
|
||||
| --- | --- |
|
||||
| [vant-weapp](https://github.com/vant-ui/vant-weapp) | WeChat MiniProgram UI |
|
||||
| [vant-demo](https://github.com/vant-ui/vant-demo) | Collection of Vant demos |
|
||||
| [vant-cli](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli) | Scaffold for UI library |
|
||||
| [vant-icons](https://github.com/vant-ui/vant/tree/3.x/packages/vant-icons) | Vant icons |
|
||||
| [vant-touch-emulator](https://github.com/vant-ui/vant/tree/3.x/packages/vant-touch-emulator) | Using vant in desktop browsers |
|
||||
| [vant-cli](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli) | Scaffold for UI library |
|
||||
| [vant-icons](https://github.com/vant-ui/vant/tree/dev/packages/vant-icons) | Vant icons |
|
||||
| [vant-touch-emulator](https://github.com/vant-ui/vant/tree/dev/packages/vant-touch-emulator) | Using vant in desktop browsers |
|
||||
|
||||
### Community Ecosystem
|
||||
|
||||
| Project | Description |
|
||||
| --- | --- |
|
||||
| [3lang3/react-vant](https://github.com/3lang3/react-vant) | React mobile UI Components based on Vant |
|
||||
| [rc-ui-lib](https://github.com/rancui/rc-ui-lib) | React Mobile UI Components Library |
|
||||
| [vant-aliapp](https://github.com/ant-move/Vant-Aliapp) | Alipay MiniProgram UI |
|
||||
| [taroify](https://gitee.com/mallfoundry/taroify) | Vant Taro |
|
||||
| [vant-theme](https://github.com/Aisen60/vant-theme) | Online theme preview built on Vant UI |
|
||||
@ -71,7 +61,7 @@ The current maintenance status of each version of Vant is as follows:
|
||||
|
||||
- [Feedback](https://github.com/vant-ui/vant/issues)
|
||||
- [Changelog](#/en-US/changelog)
|
||||
- [Discussions](https://github.com/vant-ui/vant/discussions)
|
||||
- [Gitter](https://gitter.im/vant-contrib/discuss?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
|
||||
|
||||
## Contribution
|
||||
|
||||
@ -93,7 +83,7 @@ Thanks to the following friends for their contributions to Vant:
|
||||
|
||||
### Contribution Guide
|
||||
|
||||
Please make sure to read the [Contributing Guide](https://github.com/vant-ui/vant/blob/3.x/.github/CONTRIBUTING.md) before making a pull request.
|
||||
Please make sure to read the [Contributing Guide](https://github.com/vant-ui/vant/blob/dev/.github/CONTRIBUTING.md) before making a pull request.
|
||||
|
||||
### LICENSE
|
||||
|
||||
|
@ -25,13 +25,13 @@ Vant 是一个**轻量、可靠的移动端组件库**,于 2017 年开源。
|
||||
- 🍭 支持主题定制,内置 700+ 个主题变量
|
||||
- 🍭 支持按需引入和 Tree Shaking
|
||||
- 🍭 支持无障碍访问(持续改进中)
|
||||
- 🍭 支持深色模式
|
||||
- 🍭 支持深色模式(从 [Vant 4](https://vant-contrib.gitee.io/vant/v4/#/zh-CN/config-provider) 开始支持)
|
||||
- 🍭 支持服务器端渲染
|
||||
- 🌍 支持国际化,内置 20+ 种语言包
|
||||
|
||||
### 版本提示
|
||||
|
||||
你当前浏览的是 **Vant 3.x 版本** 的文档,适用于 Vue 3 开发。如果你在使用 Vue 2,请浏览 [Vant 2 文档](https://vant-contrib.gitee.io/vant/v2)。
|
||||
你当前浏览的是 **Vant 4.x 版本** 的文档,适用于 Vue 3 开发。如果你在使用 Vue 2,请浏览 [Vant 2 文档](https://vant-contrib.gitee.io/vant/v2)。
|
||||
|
||||
### 快速上手
|
||||
|
||||
@ -43,17 +43,6 @@ Vant 2 支持现代浏览器以及 Android >= 4.0、iOS >= 8.0。
|
||||
|
||||
Vant 3/4 支持现代浏览器以及 Chrome >= 51、iOS >= 10.0(与 Vue 3 一致)。
|
||||
|
||||
### 维护状态
|
||||
|
||||
目前 Vant 各个版本的维护状态如下:
|
||||
|
||||
| 名称 | 框架 | 发布时间 | 最新版 | 维护状态 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Vant 4 | Vue 3 | `2022.11` |  | 持续迭代新功能 |
|
||||
| Vant 3 | Vue 3 | `2020.12` |  | 停止迭代新功能,bug 会被处理和修复 |
|
||||
| Vant 2 | Vue 2 | `2019.06` |  | 停止迭代新功能,重要 bug 会被处理和修复 |
|
||||
| Vant 1 | Vue 2 | `2018.03` |  | 停止维护,不再接受 PR |
|
||||
|
||||
## 链接
|
||||
|
||||
### 官方生态
|
||||
@ -64,9 +53,9 @@ Vant 3/4 支持现代浏览器以及 Chrome >= 51、iOS >= 10.0(与 Vue 3 一
|
||||
| --- | --- |
|
||||
| [vant-weapp](https://github.com/vant-ui/vant-weapp) | Vant 微信小程序版 |
|
||||
| [vant-demo](https://github.com/vant-ui/vant-demo) | Vant 官方示例合集 |
|
||||
| [vant-cli](https://github.com/vant-ui/vant/tree/3.x/packages/vant-cli) | 开箱即用的组件库搭建工具 |
|
||||
| [vant-icons](https://github.com/vant-ui/vant/tree/3.x/packages/vant-icons) | Vant 图标库 |
|
||||
| [vant-touch-emulator](https://github.com/vant-ui/vant/tree/3.x/packages/vant-touch-emulator) | 在桌面端使用 Vant 的辅助库 |
|
||||
| [vant-cli](https://github.com/vant-ui/vant/tree/dev/packages/vant-cli) | 开箱即用的组件库搭建工具 |
|
||||
| [vant-icons](https://github.com/vant-ui/vant/tree/dev/packages/vant-icons) | Vant 图标库 |
|
||||
| [vant-touch-emulator](https://github.com/vant-ui/vant/tree/dev/packages/vant-touch-emulator) | 在桌面端使用 Vant 的辅助库 |
|
||||
|
||||
### 社区生态
|
||||
|
||||
@ -75,6 +64,7 @@ Vant 3/4 支持现代浏览器以及 Chrome >= 51、iOS >= 10.0(与 Vue 3 一
|
||||
| 项目 | 描述 |
|
||||
| --- | --- |
|
||||
| [3lang3/react-vant](https://github.com/3lang3/react-vant) | 参照 Vant 打造的 React 移动端组件库 |
|
||||
| [rc-ui-lib](https://github.com/rancui/rc-ui-lib) | 基于 Vant 的 React 版本移动端 UI 组件库 |
|
||||
| [vant-aliapp](https://github.com/ant-move/Vant-Aliapp) | Vant 支付宝小程序版 |
|
||||
| [taroify](https://gitee.com/mallfoundry/taroify) | Vant Taro 版 |
|
||||
| [vant-theme](https://github.com/Aisen60/vant-theme) | Vant 在线主题预览工具 |
|
||||
@ -85,8 +75,8 @@ Vant 3/4 支持现代浏览器以及 Chrome >= 51、iOS >= 10.0(与 Vue 3 一
|
||||
|
||||
- [意见反馈](https://github.com/vant-ui/vant/issues)
|
||||
- [更新日志](#/zh-CN/changelog)
|
||||
- [码云镜像仓库](https://gitee.com/vant-contrib/vant)
|
||||
- [Discussions 讨论区](https://github.com/vant-ui/vant/discussions)
|
||||
- [码云镜像](https://gitee.com/vant-contrib/vant)
|
||||
- [Gitter 讨论组](https://gitter.im/vant-contrib/discuss?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
|
||||
|
||||
## 贡献
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 从 v2 升级
|
||||
# 从 v2 升级到 v3
|
||||
|
||||
### 介绍
|
||||
|
||||
|
365
packages/vant/docs/markdown/migrate-from-v3.zh-CN.md
Normal file
365
packages/vant/docs/markdown/migrate-from-v3.zh-CN.md
Normal file
@ -0,0 +1,365 @@
|
||||
# 从 v3 升级到 v4
|
||||
|
||||
### 介绍
|
||||
|
||||
本文档提供了从 Vant 3 到 Vant 4 的升级指南。
|
||||
|
||||
## 按需引入方式调整
|
||||
|
||||
### 移除 babel-plugin-import
|
||||
|
||||
从 Vant 4.0 版本开始,将不再支持 `babel-plugin-import`,请移除项目中依赖的 `babel-plugin-import` 插件。
|
||||
|
||||
只需要删除 `babel.config.js` 中的以下代码即可:
|
||||
|
||||
```diff
|
||||
module.exports = {
|
||||
plugins: [
|
||||
- ['import', {
|
||||
- libraryName: 'vant',
|
||||
- libraryDirectory: 'es',
|
||||
- style: true
|
||||
- }, 'vant']
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
#### 收益
|
||||
|
||||
移除 `babel-plugin-import` 有以下收益:
|
||||
|
||||
- 不再强依赖 babel,项目可以使用 esbuild、swc 等更高效的编译工具,大幅度提升编译效率。
|
||||
- 不再受到 `babel-plugin-import` 的 import 写法限制,可以从 vant 中导入除了组件以外的其他内容,比如 Vant 4 中新增的 `showToast` 等方法:
|
||||
|
||||
```ts
|
||||
import { showToast, showDialog } from 'vant';
|
||||
```
|
||||
|
||||
#### 样式引入方案
|
||||
|
||||
移除 `babel-plugin-import` 对项目的 JS 体积不会有影响,因为 Vant 默认支持通过 Tree Shaking 优化来移除不需要的 JS 代码。
|
||||
|
||||
而 CSS 代码的引入方式可以从以下两种方式中进行选择:
|
||||
|
||||
- 通过 [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components) 插件实现按需引入样式,详细用法参见 [快速上手](#/zh-CN/quickstart)。
|
||||
- 在项目中全量引入 Vant 的样式文件:
|
||||
|
||||
```js
|
||||
import 'vant/lib/index.css';
|
||||
```
|
||||
|
||||
## 组件重构
|
||||
|
||||
### 介绍
|
||||
|
||||
在 Vant 4 中,一共有三个组件被完全重构,它们是:
|
||||
|
||||
- `Area`
|
||||
- `Picker`
|
||||
- `DatetimePicker`
|
||||
|
||||
之所以重构这三个组件,是因为在之前的版本中,`Picker` 组件的 API 设计存在一些不合理的设计,导致大家在使用时经常遇到问题,比如:
|
||||
|
||||
- columns 数据格式定义不合理,容易产生误解
|
||||
- 数据流不清晰,暴露了过多的实例方法来对数据进行操作
|
||||
|
||||
为了解决上述问题,我们在 v4 版本中对 `Picker` 组件进行了重构,同时也重构了基于 `Picker` 派生出的 `Area` 和 `DatetimePicker` 组件。
|
||||
|
||||
### Picker 组件重构
|
||||
|
||||
#### 主要变更
|
||||
|
||||
- 支持通过 `v-model` 绑定当前选中的值,移除 `default-index` 属性
|
||||
- 重新定义了 `columns` 属性的结构
|
||||
- 移除了操作内部数据的实例方法,仅保留 `confirm` 方法
|
||||
- 新增 `getSelectedOptions` 实例方法
|
||||
- 调整了 `confirm`、`cancel`、`change` 事件的参数
|
||||
- 重命名 `item-height` 属性为 `option-height`
|
||||
- 重命名 `visible-item-count` 属性为 `visible-option-num`
|
||||
|
||||
> 详细用法请参见 [Picker 组件文档](#/zh-CN/picker)。
|
||||
|
||||
### DatetimePicker 组件重构
|
||||
|
||||
DatetimePicker 组件被拆分为:
|
||||
|
||||
- [TimePicker](#/zh-CN/time-picker): 用于时间选择。
|
||||
- [DatePicker](#/zh-CN/date-picker): 用于日期选择。
|
||||
- [PickerGroup](#/zh-CN/picker-group): 用于用于结合多个 Picker 选择器组件。
|
||||
|
||||
同时,TimePicker 和 DatePicker 组件也基于新版 Picker 组件进行重构,并优化了部分 API 设计。
|
||||
|
||||
#### 主要变更
|
||||
|
||||
以下是 TimePicker 和 DatePicker 的主要 API 变化,更多细节请参考 [TimePicker](#/zh-CN/time-picker) 和 [DatePicker](#/zh-CN/date-picker) 文档。
|
||||
|
||||
- `v-model` 绑定的值调整为数组格式
|
||||
- 新增 `columns-type` 属性,用于控制选项类型和顺序
|
||||
- 移除 `type` 属性和 `columns-order` 属性
|
||||
- 移除 `getPicker` 方法
|
||||
- 调整 `confirm`、`cancel`、`change` 事件的参数,与 Picker 组件保持一致
|
||||
|
||||
> Vant 4 不再提供旧版的 DatetimePicker 组件,使用 PickerGroup 组件可以实现更灵活、更丰富的交互效果,具体用法请参考 [PickerGroup](#/zh-CN/picker-group) 组件文档。
|
||||
|
||||
### Area 组件重构
|
||||
|
||||
Area 组件是基于 Picker 组件进行封装的,因此本次升级也对 Area 组件进行了内部逻辑的重构,并优化了部分 API 设计。
|
||||
|
||||
#### 主要变更
|
||||
|
||||
- 支持通过 `v-model` 绑定当前选中的值
|
||||
- 移除 `reset` 方法,现在可以通过修改 `v-model` 来进行重置
|
||||
- 移除 `is-oversea-code` 属性
|
||||
- 调整 `confirm`、`cancel`、`change` 事件的参数,与 Picker 组件保持一致
|
||||
- 重命名 `value` 属性为 `modelValue`
|
||||
- 重命名 `item-height` 属性为 `option-height`
|
||||
- 重命名 `visible-item-count` 属性为 `visible-option-num`
|
||||
|
||||
> 详细用法请参见 [Area 组件文档](#/zh-CN/area)。
|
||||
|
||||
## API 调整
|
||||
|
||||
### Dialog 调用方式调整
|
||||
|
||||
在 Vant 3 中,`Dialog` 是一个函数,调用函数可以快速唤起全局的弹窗组件,而 `Dialog.Component` 才是 `Dialog` 组件对象,这与大部分组件的用法存在差异,容易导致使用错误。
|
||||
|
||||
为了更符合直觉,我们在 Vant 4 中调整了 `Dialog` 的调用方式,将 `Dialog()` 函数重命名为 `showDialog()`。
|
||||
|
||||
```js
|
||||
// Vant 3
|
||||
Dialog(); // 函数调用
|
||||
Dialog.Component; // 组件对象
|
||||
|
||||
// Vant 4
|
||||
showDialog(); // 函数调用
|
||||
Dialog; // 组件对象
|
||||
```
|
||||
|
||||
`Dialog` 上挂载的其他方法也进行了重命名,新旧 API 的映射关系如下:
|
||||
|
||||
```js
|
||||
Dialog(); // -> showDialog()
|
||||
Dialog.alert(); // -> showDialog()
|
||||
Dialog.confirm(); // -> showConfirmDialog()
|
||||
Dialog.close(); // -> closeDialog();
|
||||
Dialog.setDefaultOptions(); // -> setDialogDefaultOptions()
|
||||
Dialog.resetDefaultOptions(); // -> resetDialogDefaultOptions()
|
||||
```
|
||||
|
||||
#### 兼容方案
|
||||
|
||||
为了便于代码迁移,我们提供了兼容方案,你可以使用 `@vant/compat` 中导出的 `Dialog` 对象来兼容原有代码。
|
||||
|
||||
```js
|
||||
import { Dialog } from '@vant/compat';
|
||||
|
||||
Dialog();
|
||||
Dialog.close();
|
||||
```
|
||||
|
||||
`@vant/compat` 中导出的 `Dialog` 与 Vant 3 中的 `Dialog` 拥有完全一致的 API 和行为,因此你只需要修改 `Dialog` 的引用路径,其他代码可以保持不变。
|
||||
|
||||
### Toast 调用方式调整
|
||||
|
||||
Vant 4 中,`Toast` 组件的调用方式也进行了调整,与 `Dialog` 组件的改动一致:
|
||||
|
||||
```js
|
||||
// Vant 3
|
||||
Toast(); // 函数调用
|
||||
|
||||
// Vant 4
|
||||
showToast(); // 函数调用
|
||||
Toast; // 组件对象
|
||||
```
|
||||
|
||||
`Toast` 上挂载的其他方法也进行了重命名,新旧 API 的映射关系如下:
|
||||
|
||||
```js
|
||||
Toast(); // -> showToast()
|
||||
Toast.fail(); // -> showFailToast()
|
||||
Toast.success(); // -> showSuccessToast()
|
||||
Toast.loading(); // -> showLoadingToast()
|
||||
Toast.clear(); // -> closeToast()
|
||||
Toast.setDefaultOptions(); // -> setToastDefaultOptions()
|
||||
Toast.resetDefaultOptions(); // -> resetToastDefaultOptions()
|
||||
```
|
||||
|
||||
同时,Vant 4 将不再在 `this` 对象上全局注册 `$toast` 方法,这意味着 `this` 对象上将无法访问到 `$toast`。
|
||||
|
||||
#### 兼容方案
|
||||
|
||||
为了便于代码迁移,我们提供了兼容方案,你可以使用 `@vant/compat` 中导出的 `Toast` 对象来兼容原有代码。
|
||||
|
||||
```js
|
||||
import { Toast } from '@vant/compat';
|
||||
|
||||
Toast();
|
||||
Toast.clear();
|
||||
```
|
||||
|
||||
`@vant/compat` 中导出的 `Toast` 与 Vant 3 中的 `Toast` 拥有完全一致的 API 和行为,因此你只需要修改 `Toast` 的引用路径,其他代码可以保持不变。
|
||||
|
||||
### Notify 调用方式调整
|
||||
|
||||
Vant 4 中,`Notify` 组件的调用方式也进行了调整,与 `Dialog` 组件的改动一致:
|
||||
|
||||
```js
|
||||
// Vant 3
|
||||
Notify(); // 函数调用
|
||||
Notify.Component; // 组件对象
|
||||
|
||||
// Vant 4
|
||||
showNotify(); // 函数调用
|
||||
Notify; // 组件对象
|
||||
```
|
||||
|
||||
`Notify` 上挂载的其他方法也进行了重命名,新旧 API 的映射关系如下:
|
||||
|
||||
```js
|
||||
Notify(); // -> showNotify()
|
||||
Notify.clear(); // -> closeNotify()
|
||||
Notify.setDefaultOptions(); // -> setNotifyDefaultOptions()
|
||||
Notify.resetDefaultOptions(); // -> resetNotifyDefaultOptions()
|
||||
```
|
||||
|
||||
同时,Vant 4 将不再在 `this` 对象上全局注册 `$notify` 方法,这意味着 `this` 对象上将无法访问到 `$notify`。
|
||||
|
||||
#### 兼容方案
|
||||
|
||||
为了便于代码迁移,我们提供了兼容方案,你可以使用 `@vant/compat` 中导出的 `Notify` 对象来兼容原有代码。
|
||||
|
||||
```js
|
||||
import { Notify } from '@vant/compat';
|
||||
|
||||
Notify();
|
||||
Notify.clear();
|
||||
```
|
||||
|
||||
`@vant/compat` 中导出的 `Notify` 与 Vant 3 中的 `Notify` 拥有完全一致的 API 和行为,因此你只需要修改 `Notify` 的引用路径,其他代码可以保持不变。
|
||||
|
||||
### ImagePreview 调用方式调整
|
||||
|
||||
Vant 4 中,`ImagePreview` 组件的调用方式也进行了调整,与 `ImagePreview` 组件的改动一致:
|
||||
|
||||
```js
|
||||
// Vant 3
|
||||
ImagePreview(); // 函数调用
|
||||
ImagePreview.Component; // 组件对象
|
||||
|
||||
// Vant 4
|
||||
showImagePreview(); // 函数调用
|
||||
ImagePreview; // 组件对象
|
||||
```
|
||||
|
||||
#### 兼容方案
|
||||
|
||||
为了便于代码迁移,我们提供了兼容方案,你可以使用 `@vant/compat` 中导出的 `ImagePreview` 对象来兼容原有代码。
|
||||
|
||||
```js
|
||||
import { ImagePreview } from '@vant/compat';
|
||||
|
||||
ImagePreview();
|
||||
```
|
||||
|
||||
`@vant/compat` 中导出的 `ImagePreview` 与 Vant 3 中的 `ImagePreview` 拥有完全一致的 API 和行为,因此你只需要修改 `ImagePreview` 的引用路径,其他代码可以保持不变。
|
||||
|
||||
### 事件命名调整
|
||||
|
||||
从 Vant 4 开始,所有的事件均采用 Vue 官方推荐的**驼峰格式**进行命名。
|
||||
|
||||
```js
|
||||
// Vant 3
|
||||
emit('click-input');
|
||||
|
||||
// Vant 4
|
||||
emit('clickInput');
|
||||
```
|
||||
|
||||
这项改动**不影响原有的模板代码**,Vue 会自动在模板中对事件名进行格式转换:
|
||||
|
||||
```html
|
||||
<!-- 以下代码可以照常运行,无须做任何更改 -->
|
||||
<van-field @click-input="onClick" />
|
||||
```
|
||||
|
||||
如果你在 JSX 中使用 Vant 组件,需要将监听的事件名调整为驼峰格式,新的监听方式更加符合 JSX 本身的规范:
|
||||
|
||||
```jsx
|
||||
// Vant 3
|
||||
<Field onClick-input={onClick} />
|
||||
|
||||
// Vant 4
|
||||
<Field onClickInput={onClick} />
|
||||
```
|
||||
|
||||
### 其他 API 调整
|
||||
|
||||
在 Vant 4.0 版本中,以下 API 进行了不兼容更新:
|
||||
|
||||
#### AddressEdit
|
||||
|
||||
- 移除 `show-postal` 属性
|
||||
- 移除 `postal-validator` 属性
|
||||
- `change-area` 事件的参数调整为 `PickerOption[]` 类型
|
||||
- 移除未在文档中标注的 `getArea` 实例方法
|
||||
|
||||
#### Popup
|
||||
|
||||
Popup 的 CSS 样式进行了一定调整,请确认是否对项目中的 UI 产生影响。
|
||||
|
||||
- 默认添加了 `box-sizing: border-box` 样式
|
||||
- 调整了 `position="center"` 时的水平居中方式,以解决弹窗宽度无法正确自适应的问题:
|
||||
|
||||
```less
|
||||
// Vant 3
|
||||
.van-popup--center {
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
}
|
||||
|
||||
// Vant 4
|
||||
.van-popup--center {
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: fit-content;
|
||||
max-width: calc(100vw - var(--van-padding-md) * 2);
|
||||
margin: 0 auto;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
```
|
||||
|
||||
#### Tabs
|
||||
|
||||
- 移除了 `click` 和 `disabled` 事件,请使用 `click-tab` 事件代替
|
||||
|
||||
## 样式变量调整
|
||||
|
||||
### 移除 Less 变量
|
||||
|
||||
目前 Vant 已经支持了基于 CSS 变量的主题定制能力,因此后续将不再提供基于 Less 的主题定制方式。
|
||||
|
||||
这意味着 Vant 的 npm 包中将不再会包含 `.less` 样式源文件,只会提供编译后的 `.css` 样式文件。
|
||||
|
||||
如果你的项目正在使用旧版的 Less 主题定制,请使用 [ConfigProvider 全局配置](#/zh-CN/config-provider) 组件进行替换。
|
||||
|
||||
### 简化 CSS 变量名
|
||||
|
||||
考虑到 **代码体积** 和 **使用便捷性**,我们对部分 CSS 变量的名称进行了简化,在变量名中使用更简短的单词,涉及以下变更:
|
||||
|
||||
```less
|
||||
animation-duration -> duration
|
||||
animation-timing-function-enter -> ease-out
|
||||
animation-timing-function-leave -> ease-in
|
||||
background-color -> background
|
||||
background-color-light -> background-2
|
||||
border-radius -> radius
|
||||
border-width-base -> border-width
|
||||
box-shadow -> shadow
|
||||
font-family -> font
|
||||
font-weight-bold -> font-bold
|
||||
price-integer-font -> price-font
|
||||
text-link -> link
|
||||
transition-duration -> duration
|
||||
```
|
||||
|
||||
由于涉及的 CSS 变量较多,建议在代码仓库中进行全局匹配和替换。
|
@ -50,7 +50,7 @@ The easiest way to use Vant is to include a CDN link in the HTML file, after whi
|
||||
app.use(vant.Lazyload);
|
||||
|
||||
// Call function component
|
||||
vant.Toast('Message');
|
||||
vant.showToast('Message');
|
||||
|
||||
app.mount('#app');
|
||||
</script>
|
||||
@ -195,19 +195,19 @@ Some components of Vant are provided as function, including `Toast`, `Dialog`, `
|
||||
|
||||
```js
|
||||
// Toast
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
import 'vant/es/toast/style';
|
||||
|
||||
// Dialog
|
||||
import { Dialog } from 'vant';
|
||||
import { showDialog } from 'vant';
|
||||
import 'vant/es/dialog/style';
|
||||
|
||||
// Notify
|
||||
import { Notify } from 'vant';
|
||||
import { showNotify } from 'vant';
|
||||
import 'vant/es/notify/style';
|
||||
|
||||
// ImagePreview
|
||||
import { ImagePreview } from 'vant';
|
||||
import { showImagePreview } from 'vant';
|
||||
import 'vant/es/image-preview/style';
|
||||
```
|
||||
|
||||
|
@ -54,8 +54,8 @@ pnpm add vant
|
||||
// 可以通过下面的方式手动注册
|
||||
app.use(vant.Lazyload);
|
||||
|
||||
// 调用函数组件,弹出一个 Toast
|
||||
vant.Toast('提示');
|
||||
// 调用工具函数,弹出一个 Toast
|
||||
vant.showToast('提示');
|
||||
|
||||
app.mount('#app');
|
||||
</script>
|
||||
@ -200,19 +200,19 @@ Vant 中有个别组件是以函数的形式提供的,包括 `Toast`,`Dialog
|
||||
|
||||
```js
|
||||
// Toast
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
import 'vant/es/toast/style';
|
||||
|
||||
// Dialog
|
||||
import { Dialog } from 'vant';
|
||||
import { showDialog } from 'vant';
|
||||
import 'vant/es/dialog/style';
|
||||
|
||||
// Notify
|
||||
import { Notify } from 'vant';
|
||||
import { showNotify } from 'vant';
|
||||
import 'vant/es/notify/style';
|
||||
|
||||
// ImagePreview
|
||||
import { ImagePreview } from 'vant';
|
||||
import { showImagePreview } from 'vant';
|
||||
import 'vant/es/image-preview/style';
|
||||
```
|
||||
|
||||
|
@ -1,176 +0,0 @@
|
||||
# Custom Theme
|
||||
|
||||
### Deprecated
|
||||
|
||||
This document is deprecated. Vant provides a more convenient [ConfigProvider](#/en-US/config-provider) component for theme configuration. Less variables **will be removed in the next major version**.
|
||||
|
||||
### Intro
|
||||
|
||||
Vant use [Less](http://lesscss.org/) as css preprocessor,you can override the default less variables to custom theme.
|
||||
|
||||
### Less variables
|
||||
|
||||
There are some [basic variables](<(https://github.com/vant-ui/vant/blob/3.x/packages/vant/src/style/var.less)>) below, for component less variables, please refer to the documentation of each component, or view the `var.less` file in the component source directory.
|
||||
|
||||
```less
|
||||
// Color Palette
|
||||
@black: #000;
|
||||
@white: #fff;
|
||||
@gray-1: #f7f8fa;
|
||||
@gray-2: #f2f3f5;
|
||||
@gray-3: #ebedf0;
|
||||
@gray-4: #dcdee0;
|
||||
@gray-5: #c8c9cc;
|
||||
@gray-6: #969799;
|
||||
@gray-7: #646566;
|
||||
@gray-8: #323233;
|
||||
@red: #ee0a24;
|
||||
@blue: #1989fa;
|
||||
@orange: #ff976a;
|
||||
@orange-dark: #ed6a0c;
|
||||
@orange-light: #fffbe8;
|
||||
@green: #07c160;
|
||||
|
||||
// Gradient Colors
|
||||
@gradient-red: linear-gradient(to right, #ff6034, #ee0a24);
|
||||
@gradient-orange: linear-gradient(to right, #ffd01e, #ff8917);
|
||||
|
||||
// Component Colors
|
||||
@text-color: @gray-8;
|
||||
@active-color: @gray-2;
|
||||
@active-opacity: 0.7;
|
||||
@disabled-opacity: 0.5;
|
||||
@background-color: @gray-1;
|
||||
@background-color-light: @white;
|
||||
@text-link-color: #576b95;
|
||||
|
||||
// Padding
|
||||
@padding-base: 4px;
|
||||
@padding-xs: @padding-base * 2;
|
||||
@padding-sm: @padding-base * 3;
|
||||
@padding-md: @padding-base * 4;
|
||||
@padding-lg: @padding-base * 6;
|
||||
@padding-xl: @padding-base * 8;
|
||||
|
||||
// Font
|
||||
@font-size-xs: 10px;
|
||||
@font-size-sm: 12px;
|
||||
@font-size-md: 14px;
|
||||
@font-size-lg: 16px;
|
||||
@font-weight-bold: 500;
|
||||
@line-height-xs: 14px;
|
||||
@line-height-sm: 18px;
|
||||
@line-height-md: 20px;
|
||||
@line-height-lg: 22px;
|
||||
@base-font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue',
|
||||
Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB',
|
||||
'Microsoft Yahei', sans-serif;
|
||||
@price-integer-font-family: Avenir-Heavy, PingFang SC, Helvetica Neue, Arial,
|
||||
sans-serif;
|
||||
|
||||
// Animation
|
||||
@animation-duration-base: 0.3s;
|
||||
@animation-duration-fast: 0.2s;
|
||||
@animation-timing-function-enter: ease-out;
|
||||
@animation-timing-function-leave: ease-in;
|
||||
|
||||
// Border
|
||||
@border-color: @gray-3;
|
||||
@border-width-base: 1px;
|
||||
@border-radius-sm: 2px;
|
||||
@border-radius-md: 4px;
|
||||
@border-radius-lg: 8px;
|
||||
@border-radius-max: 999px;
|
||||
```
|
||||
|
||||
## How to custom theme
|
||||
|
||||
### Step 1: import less file
|
||||
|
||||
First you should import the less source file to your project. you can use babel-plugin-import to automatically import or just manually import less file.
|
||||
|
||||
#### Automatically import style
|
||||
|
||||
Configure babel plugin in babel.config.js, if you are using babel6, please manually import less file.
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
plugins: [
|
||||
[
|
||||
'import',
|
||||
{
|
||||
libraryName: 'vant',
|
||||
libraryDirectory: 'es',
|
||||
// specify less file path
|
||||
style: (name) => `${name}/style/less`,
|
||||
},
|
||||
'vant',
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
#### Manually import style
|
||||
|
||||
```js
|
||||
// import all styles
|
||||
import 'vant/lib/index.less';
|
||||
|
||||
// import style of single component
|
||||
import 'vant/lib/button/style/less';
|
||||
```
|
||||
|
||||
### Step 2: modify less variables
|
||||
|
||||
Use [modifyVars](http://lesscss.org/usage/#using-less-in-the-browser-modify-variables) provided by less.js to modify less variables,webpack config for reference:
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
module.exports = {
|
||||
rules: [
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [
|
||||
// ...other loaders
|
||||
{
|
||||
loader: 'less-loader',
|
||||
options: {
|
||||
lessOptions: {
|
||||
modifyVars: {
|
||||
// override with less vars
|
||||
'text-color': '#111',
|
||||
'border-color': '#eee',
|
||||
// or override with less file
|
||||
hack: `true; @import "your-less-file-path.less";`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
If you build a project by vue-cli,it can be configured in `vue.config.js`:
|
||||
|
||||
```js
|
||||
// vue.config.js
|
||||
module.exports = {
|
||||
css: {
|
||||
loaderOptions: {
|
||||
less: {
|
||||
lessOptions: {
|
||||
modifyVars: {
|
||||
// override with less vars
|
||||
'text-color': '#111',
|
||||
'border-color': '#eee',
|
||||
// or override with less file
|
||||
hack: `true; @import "your-less-file-path.less";`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
@ -1,184 +0,0 @@
|
||||
# 定制主题
|
||||
|
||||
### 废弃提示
|
||||
|
||||
本文档已废弃,Vant 提供了更方便的 [ConfigProvider 全局配置](#/zh-CN/config-provider) 组件进行主题配置。基于 Less 变量进行定制的方式**将在下个大版本废弃**。
|
||||
|
||||
### 介绍
|
||||
|
||||
Vant 提供了一套默认主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。如果你想完全替换主题色或者其他样式,可以按照本文档进行主题定制。
|
||||
|
||||
### 示例工程
|
||||
|
||||
我们提供了一个基于 Vue CLI 3 的示例工程,仓库地址为 [Vant Demo](https://github.com/vant-ui/vant-demo),其中包含了定制主题的基本配置,可以作为参考。
|
||||
|
||||
### 样式变量
|
||||
|
||||
Vant 使用了 [Less](http://lesscss.org/) 对样式进行预处理,并内置了一些样式变量,通过替换样式变量即可定制你自己需要的主题。
|
||||
|
||||
下面是所有的[基础样式变量](https://github.com/vant-ui/vant/blob/3.x/packages/vant/src/style/var.less),组件的样式变量请参考各个组件的文档,或查看组件源码目录下的 `var.less` 文件。
|
||||
|
||||
```less
|
||||
// Color Palette
|
||||
@black: #000;
|
||||
@white: #fff;
|
||||
@gray-1: #f7f8fa;
|
||||
@gray-2: #f2f3f5;
|
||||
@gray-3: #ebedf0;
|
||||
@gray-4: #dcdee0;
|
||||
@gray-5: #c8c9cc;
|
||||
@gray-6: #969799;
|
||||
@gray-7: #646566;
|
||||
@gray-8: #323233;
|
||||
@red: #ee0a24;
|
||||
@blue: #1989fa;
|
||||
@orange: #ff976a;
|
||||
@orange-dark: #ed6a0c;
|
||||
@orange-light: #fffbe8;
|
||||
@green: #07c160;
|
||||
|
||||
// Gradient Colors
|
||||
@gradient-red: linear-gradient(to right, #ff6034, #ee0a24);
|
||||
@gradient-orange: linear-gradient(to right, #ffd01e, #ff8917);
|
||||
|
||||
// Component Colors
|
||||
@text-color: @gray-8;
|
||||
@active-color: @gray-2;
|
||||
@active-opacity: 0.7;
|
||||
@disabled-opacity: 0.5;
|
||||
@background-color: @gray-1;
|
||||
@background-color-light: @white;
|
||||
@text-link-color: #576b95;
|
||||
|
||||
// Padding
|
||||
@padding-base: 4px;
|
||||
@padding-xs: @padding-base * 2;
|
||||
@padding-sm: @padding-base * 3;
|
||||
@padding-md: @padding-base * 4;
|
||||
@padding-lg: @padding-base * 6;
|
||||
@padding-xl: @padding-base * 8;
|
||||
|
||||
// Font
|
||||
@font-size-xs: 10px;
|
||||
@font-size-sm: 12px;
|
||||
@font-size-md: 14px;
|
||||
@font-size-lg: 16px;
|
||||
@font-weight-bold: 500;
|
||||
@line-height-xs: 14px;
|
||||
@line-height-sm: 18px;
|
||||
@line-height-md: 20px;
|
||||
@line-height-lg: 22px;
|
||||
@base-font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue',
|
||||
Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB',
|
||||
'Microsoft Yahei', sans-serif;
|
||||
@price-integer-font-family: Avenir-Heavy, PingFang SC, Helvetica Neue, Arial,
|
||||
sans-serif;
|
||||
|
||||
// Animation
|
||||
@animation-duration-base: 0.3s;
|
||||
@animation-duration-fast: 0.2s;
|
||||
@animation-timing-function-enter: ease-out;
|
||||
@animation-timing-function-leave: ease-in;
|
||||
|
||||
// Border
|
||||
@border-color: @gray-3;
|
||||
@border-width-base: 1px;
|
||||
@border-radius-sm: 2px;
|
||||
@border-radius-md: 4px;
|
||||
@border-radius-lg: 8px;
|
||||
@border-radius-max: 999px;
|
||||
```
|
||||
|
||||
## 定制方法
|
||||
|
||||
### 步骤一 引入样式源文件
|
||||
|
||||
定制主题时,需要引入组件对应的 Less 样式文件,支持按需引入和手动引入两种方式。
|
||||
|
||||
#### 按需引入样式(推荐)
|
||||
|
||||
在 babel.config.js 中配置按需引入样式源文件,注意 babel 6 不支持按需引入样式,请手动引入样式。
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
plugins: [
|
||||
[
|
||||
'import',
|
||||
{
|
||||
libraryName: 'vant',
|
||||
libraryDirectory: 'es',
|
||||
// 指定样式路径
|
||||
style: (name) => `${name}/style/less`,
|
||||
},
|
||||
'vant',
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
#### 手动引入样式
|
||||
|
||||
```js
|
||||
// 引入全部样式
|
||||
import 'vant/lib/index.less';
|
||||
|
||||
// 引入单个组件样式
|
||||
import 'vant/lib/button/style/less';
|
||||
```
|
||||
|
||||
### 步骤二 修改样式变量
|
||||
|
||||
使用 Less 提供的 [modifyVars](http://lesscss.org/usage/#using-less-in-the-browser-modify-variables) 即可对变量进行修改,下面是参考的 webpack 配置。
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
module.exports = {
|
||||
rules: [
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [
|
||||
// ...其他 loader 配置
|
||||
{
|
||||
loader: 'less-loader',
|
||||
options: {
|
||||
// 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
|
||||
lessOptions: {
|
||||
modifyVars: {
|
||||
// 直接覆盖变量
|
||||
'text-color': '#111',
|
||||
'border-color': '#eee',
|
||||
// 或者可以通过 less 文件覆盖(文件路径为绝对路径)
|
||||
hack: `true; @import "your-less-file-path.less";`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
如果 vue-cli 搭建的项目,可以在 `vue.config.js` 中进行配置。
|
||||
|
||||
```js
|
||||
// vue.config.js
|
||||
module.exports = {
|
||||
css: {
|
||||
loaderOptions: {
|
||||
less: {
|
||||
// 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
|
||||
lessOptions: {
|
||||
modifyVars: {
|
||||
// 直接覆盖变量
|
||||
'text-color': '#111',
|
||||
'border-color': '#eee',
|
||||
// 或者可以通过 less 文件覆盖(文件路径为绝对路径)
|
||||
hack: `true; @import "your-less-file-path.less";`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
@ -52,6 +52,7 @@ export function initDemoLocale() {
|
||||
disabled: '禁用状态',
|
||||
uneditable: '不可编辑',
|
||||
basicUsage: '基础用法',
|
||||
usingUrl: '使用图片 URL',
|
||||
advancedUsage: '高级用法',
|
||||
loadingStatus: '加载状态',
|
||||
},
|
||||
@ -78,6 +79,7 @@ export function initDemoLocale() {
|
||||
disabled: 'Disabled',
|
||||
uneditable: 'Uneditable',
|
||||
basicUsage: 'Basic Usage',
|
||||
usingUrl: 'Using URL',
|
||||
advancedUsage: 'Advanced Usage',
|
||||
loadingStatus: 'Loading',
|
||||
},
|
||||
|
@ -1,27 +1,27 @@
|
||||
{
|
||||
"name": "vant",
|
||||
"version": "3.6.12",
|
||||
"description": "Lightweight Mobile UI Components built on Vue",
|
||||
"version": "4.0.0-rc.0",
|
||||
"description": "Mobile UI Components built on Vue",
|
||||
"main": "lib/vant.cjs.js",
|
||||
"module": "es/index.mjs",
|
||||
"style": "lib/index.css",
|
||||
"typings": "lib/index.d.ts",
|
||||
"unpkg": "lib/vant.min.js",
|
||||
"jsdelivr": "lib/vant.min.js",
|
||||
"npm": {
|
||||
"tag": "next"
|
||||
},
|
||||
"files": [
|
||||
"es",
|
||||
"lib"
|
||||
],
|
||||
"npm": {
|
||||
"tag": "latest-v3"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vant-cli dev",
|
||||
"lint": "vant-cli lint",
|
||||
"test": "vant-cli test",
|
||||
"build": "vant-cli build",
|
||||
"build:site": "vant-cli build-site",
|
||||
"release": "cp ../../README.md ./ && vant-cli release --tag latest-v3 && rm ./README.md",
|
||||
"release": "cp ../../README.md ./ && vant-cli release && rm ./README.md",
|
||||
"release:site": "pnpm build:site && npx gh-pages -d site-dist --add",
|
||||
"test:watch": "vant-cli test --watch",
|
||||
"test:coverage": "open test/coverage/index.html"
|
||||
@ -69,8 +69,7 @@
|
||||
"sideEffects": [
|
||||
"es/**/style/*",
|
||||
"lib/**/style/*",
|
||||
"*.css",
|
||||
"*.less"
|
||||
"*.css"
|
||||
],
|
||||
"web-types": "lib/web-types.json"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import { Button, ButtonType } from '../button';
|
||||
|
||||
const [name, bem] = createNamespace('action-bar-button');
|
||||
|
||||
const actionBarButtonProps = extend({}, routeProps, {
|
||||
export const actionBarButtonProps = extend({}, routeProps, {
|
||||
type: String as PropType<ButtonType>,
|
||||
text: String,
|
||||
icon: String,
|
||||
|
@ -1,29 +1,27 @@
|
||||
@import './var.less';
|
||||
|
||||
:root {
|
||||
--van-action-bar-button-height: @action-bar-button-height;
|
||||
--van-action-bar-button-warning-color: @action-bar-button-warning-color;
|
||||
--van-action-bar-button-danger-color: @action-bar-button-danger-color;
|
||||
body {
|
||||
--van-action-bar-button-height: 40px;
|
||||
--van-action-bar-button-warning-color: var(--van-gradient-orange);
|
||||
--van-action-bar-button-danger-color: var(--van-gradient-red);
|
||||
}
|
||||
|
||||
.van-action-bar-button {
|
||||
flex: 1;
|
||||
height: var(--van-action-bar-button-height);
|
||||
font-weight: var(--van-font-weight-bold);
|
||||
font-weight: var(--van-font-bold);
|
||||
font-size: var(--van-font-size-md);
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
|
||||
&--first {
|
||||
margin-left: 5px;
|
||||
border-top-left-radius: var(--van-border-radius-max);
|
||||
border-bottom-left-radius: var(--van-border-radius-max);
|
||||
border-top-left-radius: var(--van-radius-max);
|
||||
border-bottom-left-radius: var(--van-radius-max);
|
||||
}
|
||||
|
||||
&--last {
|
||||
margin-right: 5px;
|
||||
border-top-right-radius: var(--van-border-radius-max);
|
||||
border-bottom-right-radius: var(--van-border-radius-max);
|
||||
border-top-right-radius: var(--van-radius-max);
|
||||
border-bottom-right-radius: var(--van-radius-max);
|
||||
}
|
||||
|
||||
&--warning {
|
||||
|
@ -3,6 +3,7 @@ import _ActionBarButton from './ActionBarButton';
|
||||
|
||||
export const ActionBarButton = withInstall(_ActionBarButton);
|
||||
export default ActionBarButton;
|
||||
export { actionBarButtonProps } from './ActionBarButton';
|
||||
export type { ActionBarButtonProps } from './ActionBarButton';
|
||||
|
||||
declare module 'vue' {
|
||||
|
@ -1,5 +0,0 @@
|
||||
@import '../style/var.less';
|
||||
|
||||
@action-bar-button-height: 40px;
|
||||
@action-bar-button-warning-color: var(--van-gradient-orange);
|
||||
@action-bar-button-danger-color: var(--van-gradient-red);
|
@ -12,7 +12,7 @@ import { Badge, type BadgeProps } from '../badge';
|
||||
|
||||
const [name, bem] = createNamespace('action-bar-icon');
|
||||
|
||||
const actionBarIconProps = extend({}, routeProps, {
|
||||
export const actionBarIconProps = extend({}, routeProps, {
|
||||
dot: Boolean,
|
||||
text: String,
|
||||
icon: String,
|
||||
|
@ -1,14 +1,12 @@
|
||||
@import './var.less';
|
||||
|
||||
:root {
|
||||
--van-action-bar-icon-width: @action-bar-icon-width;
|
||||
--van-action-bar-icon-height: @action-bar-icon-height;
|
||||
--van-action-bar-icon-color: @action-bar-icon-color;
|
||||
--van-action-bar-icon-size: @action-bar-icon-size;
|
||||
--van-action-bar-icon-font-size: @action-bar-icon-font-size;
|
||||
--van-action-bar-icon-active-color: @action-bar-icon-active-color;
|
||||
--van-action-bar-icon-text-color: @action-bar-icon-text-color;
|
||||
--van-action-bar-icon-background-color: @action-bar-icon-background-color;
|
||||
body {
|
||||
--van-action-bar-icon-width: 48px;
|
||||
--van-action-bar-icon-height: 100%;
|
||||
--van-action-bar-icon-color: var(--van-text-color);
|
||||
--van-action-bar-icon-size: 18px;
|
||||
--van-action-bar-icon-font-size: var(--van-font-size-xs);
|
||||
--van-action-bar-icon-active-color: var(--van-active-color);
|
||||
--van-action-bar-icon-text-color: var(--van-text-color);
|
||||
--van-action-bar-icon-background: var(--van-background-2);
|
||||
}
|
||||
|
||||
.van-action-bar-icon {
|
||||
@ -21,7 +19,7 @@
|
||||
font-size: var(--van-action-bar-icon-font-size);
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
background: var(--van-action-bar-icon-background-color);
|
||||
background: var(--van-action-bar-icon-background);
|
||||
cursor: pointer;
|
||||
|
||||
&:active {
|
||||
|
@ -3,6 +3,7 @@ import _ActionBarIcon from './ActionBarIcon';
|
||||
|
||||
export const ActionBarIcon = withInstall(_ActionBarIcon);
|
||||
export default ActionBarIcon;
|
||||
export { actionBarIconProps } from './ActionBarIcon';
|
||||
export type { ActionBarIconProps } from './ActionBarIcon';
|
||||
|
||||
declare module 'vue' {
|
||||
|
@ -1,10 +0,0 @@
|
||||
@import '../style/var.less';
|
||||
|
||||
@action-bar-icon-width: 48px;
|
||||
@action-bar-icon-height: 100%;
|
||||
@action-bar-icon-color: var(--van-text-color);
|
||||
@action-bar-icon-size: 18px;
|
||||
@action-bar-icon-font-size: var(--van-font-size-xs);
|
||||
@action-bar-icon-active-color: var(--van-active-color);
|
||||
@action-bar-icon-text-color: var(--van-gray-7);
|
||||
@action-bar-icon-background-color: var(--van-background-color-light);
|
@ -7,7 +7,7 @@ const [name, bem] = createNamespace('action-bar');
|
||||
|
||||
export const ACTION_BAR_KEY = Symbol(name);
|
||||
|
||||
const actionBarProps = {
|
||||
export const actionBarProps = {
|
||||
placeholder: Boolean,
|
||||
safeAreaInsetBottom: truthProp,
|
||||
};
|
||||
|
@ -32,12 +32,12 @@ app.use(ActionBarButton);
|
||||
```
|
||||
|
||||
```js
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const onClickIcon = () => Toast('Click Icon');
|
||||
const onClickButton = () => Toast('Click Button');
|
||||
const onClickIcon = () => showToast('Click Icon');
|
||||
const onClickButton = () => showToast('Click Button');
|
||||
return {
|
||||
onClickIcon,
|
||||
onClickButton,
|
||||
@ -155,7 +155,7 @@ The component provides the following CSS variables, which can be used to customi
|
||||
|
||||
| Name | Default Value | Description |
|
||||
| --- | --- | --- |
|
||||
| --van-action-bar-background-color | _var(--van-background-color-light)_ | - |
|
||||
| --van-action-bar-background | _var(--van-background-2)_ | - |
|
||||
| --van-action-bar-height | _50px_ | - |
|
||||
| --van-action-bar-icon-width | _48px_ | - |
|
||||
| --van-action-bar-icon-height | _100%_ | - |
|
||||
@ -163,8 +163,8 @@ The component provides the following CSS variables, which can be used to customi
|
||||
| --van-action-bar-icon-size | _18px_ | - |
|
||||
| --van-action-bar-icon-font-size | _var(--van-font-size-xs)_ | - |
|
||||
| --van-action-bar-icon-active-color | _var(--van-active-color)_ | - |
|
||||
| --van-action-bar-icon-text-color | _var(--van-gray-7)_ | - |
|
||||
| --van-action-bar-icon-background-color | _var(--van-background-color-light)_ | - |
|
||||
| --van-action-bar-icon-text-color | _var(--van-text-color)_ | - |
|
||||
| --van-action-bar-icon-background | _var(--van-background-2)_ | - |
|
||||
| --van-action-bar-button-height | _40px_ | - |
|
||||
| --van-action-bar-button-warning-color | _var(--van-gradient-orange)_ | - |
|
||||
| --van-action-bar-button-danger-color | _var(--van-gradient-red)_ | - |
|
||||
|
@ -32,12 +32,12 @@ app.use(ActionBarButton);
|
||||
```
|
||||
|
||||
```js
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const onClickIcon = () => Toast('点击图标');
|
||||
const onClickButton = () => Toast('点击按钮');
|
||||
const onClickIcon = () => showToast('点击图标');
|
||||
const onClickButton = () => showToast('点击按钮');
|
||||
return {
|
||||
onClickIcon,
|
||||
onClickButton,
|
||||
@ -157,18 +157,18 @@ import type {
|
||||
|
||||
组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 [ConfigProvider 组件](#/zh-CN/config-provider)。
|
||||
|
||||
| 名称 | 默认值 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| --van-action-bar-background-color | _var(--van-background-color-light)_ | - |
|
||||
| --van-action-bar-height | _50px_ | - |
|
||||
| --van-action-bar-icon-width | _48px_ | - |
|
||||
| --van-action-bar-icon-height | _100%_ | - |
|
||||
| --van-action-bar-icon-color | _var(--van-text-color)_ | - |
|
||||
| --van-action-bar-icon-size | _18px_ | - |
|
||||
| --van-action-bar-icon-font-size | _var(--van-font-size-xs)_ | - |
|
||||
| --van-action-bar-icon-active-color | _var(--van-active-color)_ | - |
|
||||
| --van-action-bar-icon-text-color | _var(--van-gray-7)_ | - |
|
||||
| --van-action-bar-icon-background-color | _var(--van-background-color-light)_ | - |
|
||||
| --van-action-bar-button-height | _40px_ | - |
|
||||
| --van-action-bar-button-warning-color | _var(--van-gradient-orange)_ | - |
|
||||
| --van-action-bar-button-danger-color | _var(--van-gradient-red)_ | - |
|
||||
| 名称 | 默认值 | 描述 |
|
||||
| ------------------------------------- | ---------------------------- | ---- |
|
||||
| --van-action-bar-background | _var(--van-background-2)_ | - |
|
||||
| --van-action-bar-height | _50px_ | - |
|
||||
| --van-action-bar-icon-width | _48px_ | - |
|
||||
| --van-action-bar-icon-height | _100%_ | - |
|
||||
| --van-action-bar-icon-color | _var(--van-text-color)_ | - |
|
||||
| --van-action-bar-icon-size | _18px_ | - |
|
||||
| --van-action-bar-icon-font-size | _var(--van-font-size-xs)_ | - |
|
||||
| --van-action-bar-icon-active-color | _var(--van-active-color)_ | - |
|
||||
| --van-action-bar-icon-text-color | _var(--van-text-color)_ | - |
|
||||
| --van-action-bar-icon-background | _var(--van-background-2)_ | - |
|
||||
| --van-action-bar-button-height | _40px_ | - |
|
||||
| --van-action-bar-button-warning-color | _var(--van-gradient-orange)_ | - |
|
||||
| --van-action-bar-button-danger-color | _var(--van-gradient-red)_ | - |
|
||||
|
@ -3,7 +3,7 @@ import VanActionBar from '..';
|
||||
import VanActionBarIcon from '../../action-bar-icon';
|
||||
import VanActionBarButton from '../../action-bar-button';
|
||||
import { useTranslate } from '../../../docs/site';
|
||||
import { Toast } from '../../toast';
|
||||
import { showToast } from '../../toast';
|
||||
|
||||
const t = useTranslate({
|
||||
'zh-CN': {
|
||||
@ -33,8 +33,8 @@ const t = useTranslate({
|
||||
customButtonColor: 'Custom Button Color',
|
||||
},
|
||||
});
|
||||
const onClickIcon = () => Toast(t('clickIcon'));
|
||||
const onClickButton = () => Toast(t('clickButton'));
|
||||
const onClickIcon = () => showToast(t('clickIcon'));
|
||||
const onClickButton = () => showToast(t('clickButton'));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,8 +1,6 @@
|
||||
@import './var.less';
|
||||
|
||||
:root {
|
||||
--van-action-bar-background-color: @action-bar-background-color;
|
||||
--van-action-bar-height: @action-bar-height;
|
||||
body {
|
||||
--van-action-bar-background: var(--van-background-2);
|
||||
--van-action-bar-height: 50px;
|
||||
}
|
||||
|
||||
.van-action-bar {
|
||||
@ -14,5 +12,5 @@
|
||||
align-items: center;
|
||||
box-sizing: content-box;
|
||||
height: var(--van-action-bar-height);
|
||||
background: var(--van-action-bar-background-color);
|
||||
background: var(--van-action-bar-background);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import _ActionBar from './ActionBar';
|
||||
|
||||
export const ActionBar = withInstall(_ActionBar);
|
||||
export default ActionBar;
|
||||
export { actionBarProps } from './ActionBar';
|
||||
export type { ActionBarProps } from './ActionBar';
|
||||
|
||||
declare module 'vue' {
|
||||
|
@ -1,4 +0,0 @@
|
||||
@import '../style/var.less';
|
||||
|
||||
@action-bar-background-color: var(--van-background-color-light);
|
||||
@action-bar-height: 50px;
|
@ -29,7 +29,7 @@ export type ActionSheetAction = {
|
||||
className?: unknown;
|
||||
};
|
||||
|
||||
const actionSheetProps = extend({}, popupSharedProps, {
|
||||
export const actionSheetProps = extend({}, popupSharedProps, {
|
||||
title: String,
|
||||
round: truthProp,
|
||||
actions: makeArrayProp<ActionSheetAction>(),
|
||||
|
@ -29,7 +29,7 @@ Use `actions` prop to set options of action-sheet.
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
@ -41,7 +41,7 @@ export default {
|
||||
];
|
||||
const onSelect = (item) => {
|
||||
show.value = false;
|
||||
Toast(item.name);
|
||||
showToast(item.name);
|
||||
};
|
||||
|
||||
return {
|
||||
@ -67,7 +67,7 @@ export default {
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
@ -77,7 +77,7 @@ export default {
|
||||
{ name: 'Option 2' },
|
||||
{ name: 'Option 3' },
|
||||
];
|
||||
const onCancel = () => Toast('cancel');
|
||||
const onCancel = () => showToast('cancel');
|
||||
|
||||
return {
|
||||
show,
|
||||
@ -247,7 +247,7 @@ The component provides the following CSS variables, which can be used to customi
|
||||
| --van-action-sheet-description-color | _var(--van-text-color-2)_ | - |
|
||||
| --van-action-sheet-description-font-size | _var(--van-font-size-md)_ | - |
|
||||
| --van-action-sheet-description-line-height | _var(--van-line-height-md)_ | - |
|
||||
| --van-action-sheet-item-background | _var(--van-background-color-light)_ | - |
|
||||
| --van-action-sheet-item-background | _var(--van-background-2)_ | - |
|
||||
| --van-action-sheet-item-font-size | _var(--van-font-size-lg)_ | - |
|
||||
| --van-action-sheet-item-line-height | _var(--van-line-height-lg)_ | - |
|
||||
| --van-action-sheet-item-text-color | _var(--van-text-color)_ | - |
|
||||
@ -260,5 +260,5 @@ The component provides the following CSS variables, which can be used to customi
|
||||
| --van-action-sheet-close-icon-padding | _0 var(--van-padding-md)_ | - |
|
||||
| --van-action-sheet-cancel-text-color | _var(--van-gray-7)_ | - |
|
||||
| --van-action-sheet-cancel-padding-top | _var(--van-padding-xs)_ | - |
|
||||
| --van-action-sheet-cancel-padding-color | _var(--van-background-color)_ | - |
|
||||
| --van-action-sheet-cancel-padding-color | _var(--van-background)_ | - |
|
||||
| --van-action-sheet-loading-icon-size | _22px_ | - |
|
||||
|
@ -29,7 +29,7 @@ app.use(ActionSheet);
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
@ -43,7 +43,7 @@ export default {
|
||||
// 默认情况下点击选项时不会自动收起
|
||||
// 可以通过 close-on-click-action 属性开启自动收起
|
||||
show.value = false;
|
||||
Toast(item.name);
|
||||
showToast(item.name);
|
||||
};
|
||||
|
||||
return {
|
||||
@ -71,7 +71,7 @@ export default {
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
@ -81,7 +81,7 @@ export default {
|
||||
{ name: '选项二' },
|
||||
{ name: '选项三' },
|
||||
];
|
||||
const onCancel = () => Toast('取消');
|
||||
const onCancel = () => showToast('取消');
|
||||
|
||||
return {
|
||||
show,
|
||||
@ -259,7 +259,7 @@ import type { ActionSheetProps, ActionSheetAction } from 'vant';
|
||||
| --van-action-sheet-description-color | _var(--van-text-color-2)_ | - |
|
||||
| --van-action-sheet-description-font-size | _var(--van-font-size-md)_ | - |
|
||||
| --van-action-sheet-description-line-height | _var(--van-line-height-md)_ | - |
|
||||
| --van-action-sheet-item-background | _var(--van-background-color-light)_ | - |
|
||||
| --van-action-sheet-item-background | _var(--van-background-2)_ | - |
|
||||
| --van-action-sheet-item-font-size | _var(--van-font-size-lg)_ | - |
|
||||
| --van-action-sheet-item-line-height | _var(--van-line-height-lg)_ | - |
|
||||
| --van-action-sheet-item-text-color | _var(--van-text-color)_ | - |
|
||||
@ -272,5 +272,5 @@ import type { ActionSheetProps, ActionSheetAction } from 'vant';
|
||||
| --van-action-sheet-close-icon-padding | _0 var(--van-padding-md)_ | - |
|
||||
| --van-action-sheet-cancel-text-color | _var(--van-gray-7)_ | - |
|
||||
| --van-action-sheet-cancel-padding-top | _var(--van-padding-xs)_ | - |
|
||||
| --van-action-sheet-cancel-padding-color | _var(--van-background-color)_ | - |
|
||||
| --van-action-sheet-cancel-padding-color | _var(--van-background)_ | - |
|
||||
| --van-action-sheet-loading-icon-size | _22px_ | - |
|
||||
|
@ -3,7 +3,7 @@ import VanCell from '../../cell';
|
||||
import VanActionSheet, { ActionSheetAction } from '..';
|
||||
import { ref, computed } from 'vue';
|
||||
import { useTranslate } from '../../../docs/site';
|
||||
import { Toast } from '../../toast';
|
||||
import { showToast } from '../../toast';
|
||||
|
||||
const t = useTranslate({
|
||||
'zh-CN': {
|
||||
@ -61,10 +61,10 @@ const actionsWithDescription = computed<ActionSheetAction[]>(() => [
|
||||
|
||||
const onSelect = (item: ActionSheetAction) => {
|
||||
showBasic.value = false;
|
||||
Toast(item.name);
|
||||
showToast(item.name);
|
||||
};
|
||||
|
||||
const onCancel = () => Toast(t('cancel'));
|
||||
const onCancel = () => showToast(t('cancel'));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,28 +1,27 @@
|
||||
@import './var.less';
|
||||
@import '../style/mixins/hairline';
|
||||
|
||||
:root {
|
||||
--van-action-sheet-max-height: @action-sheet-max-height;
|
||||
--van-action-sheet-header-height: @action-sheet-header-height;
|
||||
--van-action-sheet-header-font-size: @action-sheet-header-font-size;
|
||||
--van-action-sheet-description-color: @action-sheet-description-color;
|
||||
--van-action-sheet-description-font-size: @action-sheet-description-font-size;
|
||||
--van-action-sheet-description-line-height: @action-sheet-description-line-height;
|
||||
--van-action-sheet-item-background: @action-sheet-item-background;
|
||||
--van-action-sheet-item-font-size: @action-sheet-item-font-size;
|
||||
--van-action-sheet-item-line-height: @action-sheet-item-line-height;
|
||||
--van-action-sheet-item-text-color: @action-sheet-item-text-color;
|
||||
--van-action-sheet-item-disabled-text-color: @action-sheet-item-disabled-text-color;
|
||||
--van-action-sheet-subname-color: @action-sheet-subname-color;
|
||||
--van-action-sheet-subname-font-size: @action-sheet-subname-font-size;
|
||||
--van-action-sheet-subname-line-height: @action-sheet-subname-line-height;
|
||||
--van-action-sheet-close-icon-size: @action-sheet-close-icon-size;
|
||||
--van-action-sheet-close-icon-color: @action-sheet-close-icon-color;
|
||||
--van-action-sheet-close-icon-padding: @action-sheet-close-icon-padding;
|
||||
--van-action-sheet-cancel-text-color: @action-sheet-cancel-text-color;
|
||||
--van-action-sheet-cancel-padding-top: @action-sheet-cancel-padding-top;
|
||||
--van-action-sheet-cancel-padding-color: @action-sheet-cancel-padding-color;
|
||||
--van-action-sheet-loading-icon-size: @action-sheet-loading-icon-size;
|
||||
body {
|
||||
--van-action-sheet-max-height: 80%;
|
||||
--van-action-sheet-header-height: 48px;
|
||||
--van-action-sheet-header-font-size: var(--van-font-size-lg);
|
||||
--van-action-sheet-description-color: var(--van-text-color-2);
|
||||
--van-action-sheet-description-font-size: var(--van-font-size-md);
|
||||
--van-action-sheet-description-line-height: var(--van-line-height-md);
|
||||
--van-action-sheet-item-background: var(--van-background-2);
|
||||
--van-action-sheet-item-font-size: var(--van-font-size-lg);
|
||||
--van-action-sheet-item-line-height: var(--van-line-height-lg);
|
||||
--van-action-sheet-item-text-color: var(--van-text-color);
|
||||
--van-action-sheet-item-disabled-text-color: var(--van-text-color-3);
|
||||
--van-action-sheet-subname-color: var(--van-text-color-2);
|
||||
--van-action-sheet-subname-font-size: var(--van-font-size-sm);
|
||||
--van-action-sheet-subname-line-height: var(--van-line-height-sm);
|
||||
--van-action-sheet-close-icon-size: 22px;
|
||||
--van-action-sheet-close-icon-color: var(--van-gray-5);
|
||||
--van-action-sheet-close-icon-padding: 0 var(--van-padding-md);
|
||||
--van-action-sheet-cancel-text-color: var(--van-gray-7);
|
||||
--van-action-sheet-cancel-padding-top: var(--van-padding-xs);
|
||||
--van-action-sheet-cancel-padding-color: var(--van-background);
|
||||
--van-action-sheet-loading-icon-size: 22px;
|
||||
}
|
||||
|
||||
.van-action-sheet {
|
||||
@ -95,7 +94,7 @@
|
||||
|
||||
&__header {
|
||||
flex-shrink: 0;
|
||||
font-weight: var(--van-font-weight-bold);
|
||||
font-weight: var(--van-font-bold);
|
||||
font-size: var(--van-action-sheet-header-font-size);
|
||||
line-height: var(--van-action-sheet-header-height);
|
||||
text-align: center;
|
||||
|
@ -3,6 +3,7 @@ import _ActionSheet from './ActionSheet';
|
||||
|
||||
export const ActionSheet = withInstall(_ActionSheet);
|
||||
export default ActionSheet;
|
||||
export { actionSheetProps } from './ActionSheet';
|
||||
export type { ActionSheetProps, ActionSheetAction } from './ActionSheet';
|
||||
|
||||
declare module 'vue' {
|
||||
|
@ -1,23 +0,0 @@
|
||||
@import '../style/var.less';
|
||||
|
||||
@action-sheet-max-height: 80%;
|
||||
@action-sheet-header-height: 48px;
|
||||
@action-sheet-header-font-size: var(--van-font-size-lg);
|
||||
@action-sheet-description-color: var(--van-text-color-2);
|
||||
@action-sheet-description-font-size: var(--van-font-size-md);
|
||||
@action-sheet-description-line-height: var(--van-line-height-md);
|
||||
@action-sheet-item-background: var(--van-background-color-light);
|
||||
@action-sheet-item-font-size: var(--van-font-size-lg);
|
||||
@action-sheet-item-line-height: var(--van-line-height-lg);
|
||||
@action-sheet-item-text-color: var(--van-text-color);
|
||||
@action-sheet-item-disabled-text-color: var(--van-text-color-3);
|
||||
@action-sheet-subname-color: var(--van-text-color-2);
|
||||
@action-sheet-subname-font-size: var(--van-font-size-sm);
|
||||
@action-sheet-subname-line-height: var(--van-line-height-sm);
|
||||
@action-sheet-close-icon-size: 22px;
|
||||
@action-sheet-close-icon-color: var(--van-gray-5);
|
||||
@action-sheet-close-icon-padding: 0 var(--van-padding-md);
|
||||
@action-sheet-cancel-text-color: var(--van-gray-7);
|
||||
@action-sheet-cancel-padding-top: var(--van-padding-xs);
|
||||
@action-sheet-cancel-padding-color: var(--van-background-color);
|
||||
@action-sheet-loading-icon-size: 22px;
|
@ -25,18 +25,20 @@ import {
|
||||
import { useExpose } from '../composables/use-expose';
|
||||
|
||||
// Components
|
||||
import { Area, AreaList, AreaColumnOption, AreaInstance } from '../area';
|
||||
import { Area, AreaList, AreaInstance } from '../area';
|
||||
import { Cell } from '../cell';
|
||||
import { Form } from '../form';
|
||||
import { Field, FieldRule } from '../field';
|
||||
import { Popup } from '../popup';
|
||||
import { Toast } from '../toast';
|
||||
import { showToast } from '../toast';
|
||||
import { Button } from '../button';
|
||||
import { Switch } from '../switch';
|
||||
import AddressEditDetail from './AddressEditDetail';
|
||||
|
||||
// Types
|
||||
import type { AddressEditInfo, AddressEditSearchItem } from './types';
|
||||
import { PickerConfirmEventParams, PickerOption } from '../picker';
|
||||
import { AREA_EMPTY_CODE } from '../area/utils';
|
||||
|
||||
const [name, bem, t] = createNamespace('address-edit');
|
||||
|
||||
@ -49,13 +51,10 @@ const DEFAULT_DATA: AddressEditInfo = {
|
||||
province: '',
|
||||
areaCode: '',
|
||||
isDefault: false,
|
||||
postalCode: '',
|
||||
addressDetail: '',
|
||||
};
|
||||
|
||||
const isPostal = (value: string) => /^\d{6}$/.test(value);
|
||||
|
||||
const addressEditProps = {
|
||||
export const addressEditProps = {
|
||||
areaList: Object as PropType<AreaList>,
|
||||
isSaving: Boolean,
|
||||
isDeleting: Boolean,
|
||||
@ -65,7 +64,6 @@ const addressEditProps = {
|
||||
showArea: truthProp,
|
||||
showDetail: truthProp,
|
||||
showDelete: Boolean,
|
||||
showPostal: Boolean,
|
||||
disableArea: Boolean,
|
||||
searchResult: Array as PropType<AddressEditSearchItem[]>,
|
||||
telMaxlength: numericProp,
|
||||
@ -85,10 +83,6 @@ const addressEditProps = {
|
||||
type: Function as PropType<(val: string) => boolean>,
|
||||
default: isMobile,
|
||||
},
|
||||
postalValidator: {
|
||||
type: Function as PropType<(val: string) => boolean>,
|
||||
default: isPostal,
|
||||
},
|
||||
};
|
||||
|
||||
export type AddressEditProps = ExtractPropTypes<typeof addressEditProps>;
|
||||
@ -102,11 +96,11 @@ export default defineComponent({
|
||||
'save',
|
||||
'focus',
|
||||
'delete',
|
||||
'click-area',
|
||||
'change-area',
|
||||
'change-detail',
|
||||
'select-search',
|
||||
'change-default',
|
||||
'clickArea',
|
||||
'changeArea',
|
||||
'changeDetail',
|
||||
'selectSearch',
|
||||
'changeDefault',
|
||||
],
|
||||
|
||||
setup(props, { emit, slots }) {
|
||||
@ -121,9 +115,9 @@ export default defineComponent({
|
||||
);
|
||||
|
||||
const areaText = computed(() => {
|
||||
const { country, province, city, county, areaCode } = data;
|
||||
const { province, city, county, areaCode } = data;
|
||||
if (areaCode) {
|
||||
const arr = [country, province, city, county];
|
||||
const arr = [province, city, county];
|
||||
if (province && province === city) {
|
||||
arr.splice(1, 1);
|
||||
}
|
||||
@ -137,22 +131,13 @@ export default defineComponent({
|
||||
() => props.searchResult?.length && detailFocused.value
|
||||
);
|
||||
|
||||
const assignAreaValues = () => {
|
||||
if (areaRef.value) {
|
||||
const detail: Record<string, string> = areaRef.value.getArea();
|
||||
detail.areaCode = detail.code;
|
||||
delete detail.code;
|
||||
extend(data, detail);
|
||||
}
|
||||
};
|
||||
|
||||
const onFocus = (key: string) => {
|
||||
detailFocused.value = key === 'addressDetail';
|
||||
emit('focus', key);
|
||||
};
|
||||
|
||||
const rules = computed<Record<string, FieldRule[]>>(() => {
|
||||
const { validator, telValidator, postalValidator } = props;
|
||||
const { validator, telValidator } = props;
|
||||
|
||||
const makeRule = (name: string, emptyMessage: string): FieldRule => ({
|
||||
validator: (value) => {
|
||||
@ -177,10 +162,6 @@ export default defineComponent({
|
||||
],
|
||||
areaCode: [makeRule('areaCode', t('areaEmpty'))],
|
||||
addressDetail: [makeRule('addressDetail', t('addressEmpty'))],
|
||||
postalCode: [
|
||||
makeRule('addressDetail', t('postalEmpty')),
|
||||
{ validator: postalValidator, message: t('postalEmpty') },
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
@ -188,33 +169,33 @@ export default defineComponent({
|
||||
|
||||
const onChangeDetail = (val: string) => {
|
||||
data.addressDetail = val;
|
||||
emit('change-detail', val);
|
||||
emit('changeDetail', val);
|
||||
};
|
||||
|
||||
const onAreaConfirm = (values: AreaColumnOption[]) => {
|
||||
values = values.filter(Boolean);
|
||||
const assignAreaText = (options: PickerOption[]) => {
|
||||
data.province = options[0].text as string;
|
||||
data.city = options[1].text as string;
|
||||
data.county = options[2].text as string;
|
||||
};
|
||||
|
||||
if (values.some((value) => !value.code)) {
|
||||
Toast(t('areaEmpty'));
|
||||
const onAreaConfirm = ({
|
||||
selectedValues,
|
||||
selectedOptions,
|
||||
}: PickerConfirmEventParams) => {
|
||||
if (selectedValues.some((value) => value === AREA_EMPTY_CODE)) {
|
||||
showToast(t('areaEmpty'));
|
||||
} else {
|
||||
showAreaPopup.value = false;
|
||||
assignAreaValues();
|
||||
emit('change-area', values);
|
||||
assignAreaText(selectedOptions as PickerOption[]);
|
||||
emit('changeArea', selectedOptions);
|
||||
}
|
||||
};
|
||||
|
||||
const onDelete = () => emit('delete', data);
|
||||
|
||||
// get values of area component
|
||||
const getArea = () => areaRef.value?.getValues() || [];
|
||||
|
||||
// set area code to area component
|
||||
const setAreaCode = (code?: string) => {
|
||||
data.areaCode = code || '';
|
||||
|
||||
if (code) {
|
||||
nextTick(assignAreaValues);
|
||||
}
|
||||
};
|
||||
|
||||
const onDetailBlur = () => {
|
||||
@ -234,8 +215,7 @@ export default defineComponent({
|
||||
'right-icon': () => (
|
||||
<Switch
|
||||
v-model={data.isDefault}
|
||||
size="24"
|
||||
onChange={(event) => emit('change-default', event)}
|
||||
onChange={(event) => emit('changeDefault', event)}
|
||||
/>
|
||||
),
|
||||
};
|
||||
@ -253,21 +233,25 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
useExpose({
|
||||
getArea,
|
||||
setAreaCode,
|
||||
setAddressDetail,
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.areaList,
|
||||
() => setAreaCode(data.areaCode)
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.addressInfo,
|
||||
(value) => {
|
||||
extend(data, DEFAULT_DATA, value);
|
||||
setAreaCode(value.areaCode);
|
||||
nextTick(() => {
|
||||
const options = areaRef.value?.getSelectedOptions();
|
||||
if (
|
||||
options &&
|
||||
options.every(
|
||||
(option) => option && option.value !== AREA_EMPTY_CODE
|
||||
)
|
||||
) {
|
||||
assignAreaText(options as PickerOption[]);
|
||||
}
|
||||
});
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
@ -309,7 +293,7 @@ export default defineComponent({
|
||||
placeholder={props.areaPlaceholder || t('area')}
|
||||
onFocus={() => onFocus('areaCode')}
|
||||
onClick={() => {
|
||||
emit('click-area');
|
||||
emit('clickArea');
|
||||
showAreaPopup.value = !disableArea;
|
||||
}}
|
||||
/>
|
||||
@ -325,20 +309,8 @@ export default defineComponent({
|
||||
onBlur={onDetailBlur}
|
||||
onFocus={() => onFocus('addressDetail')}
|
||||
onInput={onChangeDetail}
|
||||
onSelect-search={(event: Event) => emit('select-search', event)}
|
||||
onSelectSearch={(event: Event) => emit('selectSearch', event)}
|
||||
/>
|
||||
{props.showPostal && (
|
||||
<Field
|
||||
v-show={!hideBottomFields.value}
|
||||
v-model={data.postalCode}
|
||||
type="tel"
|
||||
rules={rules.value.postalCode}
|
||||
label={t('postal')}
|
||||
maxlength="6"
|
||||
placeholder={t('postal')}
|
||||
onFocus={() => onFocus('postalCode')}
|
||||
/>
|
||||
)}
|
||||
{slots.default?.()}
|
||||
</div>
|
||||
{renderSetDefaultCell()}
|
||||
@ -346,7 +318,7 @@ export default defineComponent({
|
||||
<Button
|
||||
block
|
||||
round
|
||||
type="danger"
|
||||
type="primary"
|
||||
text={props.saveButtonText || t('save')}
|
||||
class={bem('button')}
|
||||
loading={props.isSaving}
|
||||
@ -371,8 +343,8 @@ export default defineComponent({
|
||||
lazyRender={false}
|
||||
>
|
||||
<Area
|
||||
v-model={data.areaCode}
|
||||
ref={areaRef}
|
||||
value={data.areaCode}
|
||||
loading={!areaListLoaded.value}
|
||||
areaList={props.areaList}
|
||||
columnsPlaceholder={props.areaColumnsPlaceholder}
|
||||
|
@ -28,7 +28,7 @@ export default defineComponent({
|
||||
showSearchResult: Boolean,
|
||||
},
|
||||
|
||||
emits: ['blur', 'focus', 'input', 'select-search'],
|
||||
emits: ['blur', 'focus', 'input', 'selectSearch'],
|
||||
|
||||
setup(props, { emit }) {
|
||||
const field = ref<FieldInstance>();
|
||||
@ -37,21 +37,10 @@ export default defineComponent({
|
||||
props.focused && props.searchResult && props.showSearchResult;
|
||||
|
||||
const onSelect = (express: AddressEditSearchItem) => {
|
||||
emit('select-search', express);
|
||||
emit('selectSearch', express);
|
||||
emit('input', `${express.address || ''} ${express.name || ''}`.trim());
|
||||
};
|
||||
|
||||
const renderSearchTitle = (express: AddressEditSearchItem) => {
|
||||
if (express.name) {
|
||||
const text = express.name.replace(
|
||||
props.value!,
|
||||
`<span class=${bem('keyword')}>${props.value}</span>`
|
||||
);
|
||||
|
||||
return <div innerHTML={text} />;
|
||||
}
|
||||
};
|
||||
|
||||
const renderSearchResult = () => {
|
||||
if (!showSearchResult()) {
|
||||
return;
|
||||
@ -60,12 +49,10 @@ export default defineComponent({
|
||||
const { searchResult } = props;
|
||||
return searchResult!.map((express) => (
|
||||
<Cell
|
||||
v-slots={{
|
||||
title: () => renderSearchTitle(express),
|
||||
}}
|
||||
clickable
|
||||
key={express.name + express.address}
|
||||
key={(express.name || '') + (express.address || '')}
|
||||
icon="location-o"
|
||||
title={express.name}
|
||||
label={express.address}
|
||||
class={bem('search-item')}
|
||||
border={false}
|
||||
|
@ -23,7 +23,6 @@ app.use(AddressEdit);
|
||||
```html
|
||||
<van-address-edit
|
||||
:area-list="areaList"
|
||||
show-postal
|
||||
show-delete
|
||||
show-set-default
|
||||
show-search-result
|
||||
@ -37,14 +36,14 @@ app.use(AddressEdit);
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const searchResult = ref([]);
|
||||
|
||||
const onSave = () => Toast('save');
|
||||
const onDelete = () => Toast('delete');
|
||||
const onSave = () => showToast('save');
|
||||
const onDelete = () => showToast('delete');
|
||||
const onChangeDetail = (val) => {
|
||||
if (val) {
|
||||
searchResult.value = [
|
||||
@ -80,7 +79,6 @@ export default {
|
||||
| area-placeholder | placeholder of area input field | _string_ | `Area` |
|
||||
| address-info | Address Info | _AddressEditInfo_ | `{}` |
|
||||
| search-result | Address search result | _AddressEditSearchItem[]_ | `[]` |
|
||||
| show-postal | Whether to show postal field | _boolean_ | `false` |
|
||||
| show-delete | Whether to show delete button | _boolean_ | `false` |
|
||||
| show-set-default | Whether to show default address switch | _boolean_ | `false` |
|
||||
| show-search-result | Whether to show address search result | _boolean_ | `false` |
|
||||
@ -95,27 +93,26 @@ export default {
|
||||
| is-deleting | Whether to show delete button loading status | _boolean_ | `false` |
|
||||
| tel-validator | The method to validate tel | _(tel: string) => boolean_ | - |
|
||||
| tel-maxlength | Tel maxlength | _number \| string_ | - |
|
||||
| postal-validator | The method to validate postal | _(tel: string) => boolean_ | - |
|
||||
| validator | Custom validator | _(key, val) => string_ | - |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
| --- | --- | --- |
|
||||
| save | Emitted when the save button is clicked | content: form content |
|
||||
| focus | Emitted when field is focused | key: field name |
|
||||
| delete | Emitted when confirming delete | content: form content |
|
||||
| select-search | Emitted when a search result is selected | value: search content |
|
||||
| save | Emitted when the save button is clicked | _info: AddressEditInfo_ |
|
||||
| focus | Emitted when field is focused | _key: string_ |
|
||||
| delete | Emitted when confirming delete | _info: AddressEditInfo_ |
|
||||
| select-search | Emitted when a search result is selected | _value: string_ |
|
||||
| click-area | Emitted when the area field is clicked | - |
|
||||
| change-area | Emitted when area changed | values: area values |
|
||||
| change-detail | Emitted when address detail changed | value: address detail |
|
||||
| change-default | Emitted when switching default address | value: checked |
|
||||
| change-area | Emitted when area changed | _selectedOptions: PickerOption[]_ |
|
||||
| change-detail | Emitted when address detail changed | _value: string_ |
|
||||
| change-default | Emitted when switching default address | _checked: boolean_ |
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
| ------- | --------------------------- |
|
||||
| default | Custom content below postal |
|
||||
| Name | Description |
|
||||
| ------- | ----------------------------------- |
|
||||
| default | Custom content below address detail |
|
||||
|
||||
### Methods
|
||||
|
||||
@ -160,7 +157,6 @@ addressEditRef.value?.setAddressDetail('');
|
||||
| county | County | _string_ |
|
||||
| addressDetail | Detailed Address | _string_ |
|
||||
| areaCode | Area code | _string_ |
|
||||
| postalCode | Postal code | _string_ |
|
||||
| isDefault | Is default address | _boolean_ |
|
||||
|
||||
### AddressEditSearchItem Data Structure
|
||||
|
@ -23,7 +23,6 @@ app.use(AddressEdit);
|
||||
```html
|
||||
<van-address-edit
|
||||
:area-list="areaList"
|
||||
show-postal
|
||||
show-delete
|
||||
show-set-default
|
||||
show-search-result
|
||||
@ -37,14 +36,14 @@ app.use(AddressEdit);
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const searchResult = ref([]);
|
||||
|
||||
const onSave = () => Toast('save');
|
||||
const onDelete = () => Toast('delete');
|
||||
const onSave = () => showToast('save');
|
||||
const onDelete = () => showToast('delete');
|
||||
const onChangeDetail = (val) => {
|
||||
if (val) {
|
||||
searchResult.value = [
|
||||
@ -80,7 +79,6 @@ export default {
|
||||
| area-placeholder | 地区输入框占位提示文字 | _string_ | `选择省 / 市 / 区` |
|
||||
| address-info | 地址信息初始值 | _AddressEditInfo_ | `{}` |
|
||||
| search-result | 详细地址搜索结果 | _AddressEditSearchItem[]_ | `[]` |
|
||||
| show-postal | 是否显示邮政编码 | _boolean_ | `false` |
|
||||
| show-delete | 是否显示删除按钮 | _boolean_ | `false` |
|
||||
| show-set-default | 是否显示默认地址栏 | _boolean_ | `false` |
|
||||
| show-search-result | 是否显示搜索结果 | _boolean_ | `false` |
|
||||
@ -95,21 +93,20 @@ export default {
|
||||
| is-deleting | 是否显示删除按钮加载动画 | _boolean_ | `false` |
|
||||
| tel-validator | 手机号格式校验函数 | _string => boolean_ | - |
|
||||
| tel-maxlength | 手机号最大长度 | _number \| string_ | - |
|
||||
| postal-validator | 邮政编码格式校验函数 | _string => boolean_ | - |
|
||||
| validator | 自定义校验函数 | _(key, val) => string_ | - |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
| -------------- | -------------------------- | --------------------------- |
|
||||
| save | 点击保存按钮时触发 | content:表单内容 |
|
||||
| focus | 输入框聚焦时触发 | key: 聚焦的输入框对应的 key |
|
||||
| delete | 确认删除地址时触发 | content:表单内容 |
|
||||
| select-search | 选中搜索结果时触发 | value: 搜索结果 |
|
||||
| click-area | 点击收件地区时触发 | - |
|
||||
| change-area | 修改收件地区时触发 | values: 地区信息 |
|
||||
| change-detail | 修改详细地址时触发 | value: 详细地址内容 |
|
||||
| change-default | 切换是否使用默认地址时触发 | value: 是否选中 |
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
| --- | --- | --- |
|
||||
| save | 点击保存按钮时触发 | _info: AddressEditInfo_ |
|
||||
| focus | 输入框聚焦时触发 | _key: string_ |
|
||||
| delete | 确认删除地址时触发 | _info: AddressEditInfo_ |
|
||||
| select-search | 选中搜索结果时触发 | _value: string_ |
|
||||
| click-area | 点击收件地区时触发 | - |
|
||||
| change-area | 修改收件地区时触发 | _selectedOptions: PickerOption[]_ |
|
||||
| change-detail | 修改详细地址时触发 | _value: string_ |
|
||||
| change-default | 切换是否使用默认地址时触发 | _checked: boolean_ |
|
||||
|
||||
### Slots
|
||||
|
||||
@ -162,7 +159,6 @@ addressEditRef.value?.setAddressDetail('');
|
||||
| county | 区县 | _string_ |
|
||||
| addressDetail | 详细地址 | _string_ |
|
||||
| areaCode | 地区编码,通过 [省市区选择](#/zh-CN/area) 获取(必填) | _string_ |
|
||||
| postalCode | 邮政编码 | _string_ |
|
||||
| isDefault | 是否为默认地址 | _boolean_ |
|
||||
|
||||
### AddressEditSearchItem 数据格式
|
||||
|
@ -3,7 +3,7 @@ import VanAddressEdit from '..';
|
||||
import { ref } from 'vue';
|
||||
import { areaList } from '@vant/area-data';
|
||||
import { useTranslate } from '../../../docs/site';
|
||||
import { Toast } from '../../toast';
|
||||
import { showToast } from '../../toast';
|
||||
|
||||
const t = useTranslate({
|
||||
'zh-CN': {
|
||||
@ -41,8 +41,8 @@ const t = useTranslate({
|
||||
});
|
||||
const searchResult = ref([]);
|
||||
|
||||
const onSave = () => Toast(t('save'));
|
||||
const onDelete = () => Toast(t('delete'));
|
||||
const onSave = () => showToast(t('save'));
|
||||
const onDelete = () => showToast(t('delete'));
|
||||
const onChangeDetail = (val: string) => {
|
||||
searchResult.value = val ? t('searchResult') : [];
|
||||
};
|
||||
@ -52,7 +52,6 @@ const onChangeDetail = (val: string) => {
|
||||
<demo-block :title="t('basicUsage')">
|
||||
<van-address-edit
|
||||
:area-list="areaList"
|
||||
show-postal
|
||||
show-delete
|
||||
show-set-default
|
||||
show-search-result
|
||||
|
@ -1,10 +1,9 @@
|
||||
@import './var.less';
|
||||
|
||||
:root {
|
||||
--van-address-edit-padding: @address-edit-padding;
|
||||
--van-address-edit-buttons-padding: @address-edit-buttons-padding;
|
||||
--van-address-edit-button-margin-bottom: @address-edit-button-margin-bottom;
|
||||
--van-address-edit-button-font-size: @address-edit-button-font-size;
|
||||
body {
|
||||
--van-address-edit-padding: var(--van-padding-sm);
|
||||
--van-address-edit-buttons-padding: var(--van-padding-xl)
|
||||
var(--van-padding-base);
|
||||
--van-address-edit-button-margin-bottom: var(--van-padding-sm);
|
||||
--van-address-edit-button-font-size: var(--van-font-size-lg);
|
||||
}
|
||||
|
||||
.van-address-edit {
|
||||
@ -34,13 +33,7 @@
|
||||
font-size: var(--van-address-edit-button-font-size);
|
||||
}
|
||||
|
||||
&-detail {
|
||||
&__search-item {
|
||||
background: var(--van-gray-2);
|
||||
}
|
||||
|
||||
&__keyword {
|
||||
color: var(--van-danger-color);
|
||||
}
|
||||
&-detail__search-item {
|
||||
background: var(--van-gray-2);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import _AddressEdit, { AddressEditProps } from './AddressEdit';
|
||||
|
||||
export const AddressEdit = withInstall(_AddressEdit);
|
||||
export default AddressEdit;
|
||||
export { addressEditProps } from './AddressEdit';
|
||||
export type { AddressEditProps };
|
||||
export type {
|
||||
AddressEditInfo,
|
||||
|
@ -88,25 +88,6 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-cell van-field">
|
||||
<div class="van-cell__title van-field__label">
|
||||
<label id="van-field-label"
|
||||
for="van-field-input"
|
||||
>
|
||||
Postal
|
||||
</label>
|
||||
</div>
|
||||
<div class="van-cell__value van-field__value">
|
||||
<div class="van-field__body">
|
||||
<input type="tel"
|
||||
id="van-field-input"
|
||||
class="van-field__control"
|
||||
placeholder="Postal"
|
||||
aria-labelledby="van-field-label"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-cell van-cell--center van-address-edit__default">
|
||||
<div class="van-cell__title">
|
||||
@ -116,7 +97,6 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</div>
|
||||
<div role="switch"
|
||||
class="van-switch"
|
||||
style="font-size: 24px;"
|
||||
tabindex="0"
|
||||
aria-checked="false"
|
||||
>
|
||||
@ -126,7 +106,7 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</div>
|
||||
<div class="van-address-edit__buttons">
|
||||
<button type="submit"
|
||||
class="van-button van-button--danger van-button--normal van-button--block van-button--round van-address-edit__button"
|
||||
class="van-button van-button--primary van-button--normal van-button--block van-button--round van-address-edit__button"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
|
@ -95,7 +95,7 @@ exports[`should render AddressEdit correctly 1`] = `
|
||||
</div>
|
||||
<div class="van-address-edit__buttons">
|
||||
<button type="submit"
|
||||
class="van-button van-button--danger van-button--normal van-button--block van-button--round van-address-edit__button"
|
||||
class="van-button van-button--primary van-button--normal van-button--block van-button--round van-address-edit__button"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
@ -193,25 +193,6 @@ exports[`should render AddressEdit with props correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-cell van-field">
|
||||
<div class="van-cell__title van-field__label">
|
||||
<label id="van-field-label"
|
||||
for="van-field-input"
|
||||
>
|
||||
Postal
|
||||
</label>
|
||||
</div>
|
||||
<div class="van-cell__value van-field__value">
|
||||
<div class="van-field__body">
|
||||
<input type="tel"
|
||||
id="van-field-input"
|
||||
class="van-field__control"
|
||||
placeholder="Postal"
|
||||
aria-labelledby="van-field-label"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-cell van-cell--center van-address-edit__default">
|
||||
<div class="van-cell__title">
|
||||
@ -221,7 +202,6 @@ exports[`should render AddressEdit with props correctly 1`] = `
|
||||
</div>
|
||||
<div role="switch"
|
||||
class="van-switch van-switch--on"
|
||||
style="font-size: 24px;"
|
||||
tabindex="0"
|
||||
aria-checked="true"
|
||||
>
|
||||
@ -231,7 +211,7 @@ exports[`should render AddressEdit with props correctly 1`] = `
|
||||
</div>
|
||||
<div class="van-address-edit__buttons">
|
||||
<button type="submit"
|
||||
class="van-button van-button--danger van-button--normal van-button--block van-button--round van-address-edit__button"
|
||||
class="van-button van-button--primary van-button--normal van-button--block van-button--round van-address-edit__button"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
@ -292,9 +272,6 @@ exports[`should valid area code and render error message correctly 1`] = `
|
||||
aria-labelledby="van-field-label"
|
||||
>
|
||||
</div>
|
||||
<div class="van-field__error-message">
|
||||
Please select a receiving area
|
||||
</div>
|
||||
</div>
|
||||
<i class="van-badge__wrapper van-icon van-icon-arrow van-cell__right-icon">
|
||||
</i>
|
||||
@ -326,31 +303,6 @@ exports[`should valid name and render error message correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`should valid postal code and render error message correctly 1`] = `
|
||||
<div class="van-cell van-field">
|
||||
<div class="van-cell__title van-field__label">
|
||||
<label id="van-field-label"
|
||||
for="van-field-input"
|
||||
>
|
||||
Postal
|
||||
</label>
|
||||
</div>
|
||||
<div class="van-cell__value van-field__value">
|
||||
<div class="van-field__body">
|
||||
<input type="tel"
|
||||
id="van-field-input"
|
||||
class="van-field__control"
|
||||
placeholder="Postal"
|
||||
aria-labelledby="van-field-label"
|
||||
>
|
||||
</div>
|
||||
<div class="van-field__error-message">
|
||||
Wrong postal code
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`should valid tel and render error message correctly 1`] = `
|
||||
<div class="van-cell van-field">
|
||||
<div class="van-cell__title van-field__label">
|
@ -1,4 +1,4 @@
|
||||
import { AddressEdit } from '..';
|
||||
import { AddressEdit, AddressEditInstance } from '..';
|
||||
import { areaList } from '../../area/demo/area-simple';
|
||||
import { mount, later, trigger } from '../../../test';
|
||||
import { submitForm } from '../../form/test/shared';
|
||||
@ -11,7 +11,6 @@ const defaultAddressInfo = {
|
||||
county: '朝阳区',
|
||||
addressDetail: 'address detail',
|
||||
areaCode: '110101',
|
||||
postalCode: '10000',
|
||||
isDefault: true,
|
||||
};
|
||||
|
||||
@ -23,7 +22,6 @@ const createComponent = (addressInfo = {}) => {
|
||||
...defaultAddressInfo,
|
||||
...addressInfo,
|
||||
},
|
||||
showPostal: true,
|
||||
showSetDefault: true,
|
||||
},
|
||||
});
|
||||
@ -45,7 +43,6 @@ test('should render AddressEdit with props correctly', () => {
|
||||
props: {
|
||||
areaList,
|
||||
addressInfo: defaultAddressInfo,
|
||||
showPostal: true,
|
||||
showSetDefault: true,
|
||||
showSearchResult: true,
|
||||
},
|
||||
@ -58,7 +55,7 @@ test('should allow to custom validator with validator prop', async () => {
|
||||
const wrapper = mount(AddressEdit, {
|
||||
props: {
|
||||
areaList,
|
||||
validator: (key, value) => `foo ${key}${value}`,
|
||||
validator: (key: string, value: string) => `foo ${key}${value}`,
|
||||
},
|
||||
});
|
||||
|
||||
@ -103,48 +100,13 @@ test('should valid address detail and render error message correctly', async ()
|
||||
expect(fields[3].html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should valid postal code and render error message correctly', async () => {
|
||||
const { fields, wrapper } = createComponent({
|
||||
postalCode: '123',
|
||||
});
|
||||
|
||||
await submitForm(wrapper);
|
||||
expect(fields[4].html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should emit change-detail event after changing address detail', () => {
|
||||
test('should emit changeDetail event after changing address detail', () => {
|
||||
const wrapper = mount(AddressEdit);
|
||||
const field = wrapper.findAll('.van-field__control')[3];
|
||||
|
||||
field.element.value = '123';
|
||||
(field.element as HTMLInputElement).value = '123';
|
||||
field.trigger('input');
|
||||
expect(wrapper.emitted('change-detail')[0][0]).toEqual('123');
|
||||
});
|
||||
|
||||
test('should return current areas after calling getArea method', () => {
|
||||
const wrapper = mount(AddressEdit, {
|
||||
props: { areaList },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.getArea()).toEqual([
|
||||
{ code: '110000', name: '北京市' },
|
||||
{ code: '110100', name: '北京市' },
|
||||
{ code: '110101', name: '东城区' },
|
||||
]);
|
||||
});
|
||||
|
||||
test('should update current areas after calling setAreaCode method', async () => {
|
||||
const wrapper = mount(AddressEdit, {
|
||||
props: { areaList },
|
||||
});
|
||||
|
||||
wrapper.vm.setAreaCode('110102');
|
||||
await later();
|
||||
expect(wrapper.vm.getArea()).toEqual([
|
||||
{ code: '110000', name: '北京市' },
|
||||
{ code: '110100', name: '北京市' },
|
||||
{ code: '110102', name: '西城区' },
|
||||
]);
|
||||
expect(wrapper.emitted('changeDetail')).toEqual([['123']]);
|
||||
});
|
||||
|
||||
test('should show search result after focusing to address detail', async () => {
|
||||
@ -160,25 +122,21 @@ test('should show search result after focusing to address detail', async () => {
|
||||
});
|
||||
|
||||
const field = wrapper.findAll('.van-field__control')[3];
|
||||
const input = field.element;
|
||||
const input = field.element as HTMLInputElement;
|
||||
await field.trigger('focus');
|
||||
|
||||
const items = wrapper.findAll('.van-icon-location-o');
|
||||
items[0].element.parentNode.click();
|
||||
(items[0].element.parentNode as HTMLElement).click();
|
||||
await later();
|
||||
expect(input.value).toEqual('address1 name1');
|
||||
|
||||
items[1].element.parentNode.click();
|
||||
(items[1].element.parentNode as HTMLElement).click();
|
||||
await later();
|
||||
expect(input.value).toEqual('name2');
|
||||
|
||||
items[2].element.parentNode.click();
|
||||
(items[2].element.parentNode as HTMLElement).click();
|
||||
await later();
|
||||
expect(input.value).toEqual('address2');
|
||||
|
||||
await field.trigger('blur');
|
||||
await later(150);
|
||||
expect(wrapper.vm.detailFocused).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should emit delete event after clicking the delete button', async () => {
|
||||
@ -199,12 +157,12 @@ test('should update address detail after calling the setAddressDetail method', a
|
||||
|
||||
expect(textarea.element.value).toEqual('address detail');
|
||||
|
||||
vm.setAddressDetail('test');
|
||||
(vm as AddressEditInstance).setAddressDetail('test');
|
||||
await later();
|
||||
expect(textarea.element.value).toEqual('test');
|
||||
});
|
||||
|
||||
test('should emit click-area event after clicking the area field', () => {
|
||||
test('should emit clickArea event after clicking the area field', () => {
|
||||
const wrapper = mount(AddressEdit, {
|
||||
props: {
|
||||
disableArea: true,
|
||||
@ -213,7 +171,7 @@ test('should emit click-area event after clicking the area field', () => {
|
||||
|
||||
const field = wrapper.findAll('.van-field')[2];
|
||||
field.trigger('click');
|
||||
expect(wrapper.emitted('click-area')[0]).toBeTruthy();
|
||||
expect(wrapper.emitted('clickArea')).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('should limit tel maxlength when using tel-maxlength prop', () => {
|
||||
@ -224,8 +182,9 @@ test('should limit tel maxlength when using tel-maxlength prop', () => {
|
||||
});
|
||||
|
||||
const telInput = wrapper.find('input[type="tel"]');
|
||||
telInput.element.value = '123456';
|
||||
const inputEl = telInput.element as HTMLInputElement;
|
||||
inputEl.value = '123456';
|
||||
trigger(telInput, 'input');
|
||||
|
||||
expect(telInput.element.value).toEqual('1234');
|
||||
expect(inputEl.value).toEqual('1234');
|
||||
});
|
@ -1,10 +1,9 @@
|
||||
import type { ComponentPublicInstance } from 'vue';
|
||||
import type { AreaColumnOption } from '../area';
|
||||
import type { AddressEditProps } from './AddressEdit';
|
||||
|
||||
export type AddressEditSearchItem = {
|
||||
name: string;
|
||||
address: string;
|
||||
name?: string;
|
||||
address?: string;
|
||||
};
|
||||
|
||||
export type AddressEditInfo = {
|
||||
@ -16,12 +15,10 @@ export type AddressEditInfo = {
|
||||
province: string;
|
||||
areaCode: string;
|
||||
isDefault?: boolean;
|
||||
postalCode?: string;
|
||||
addressDetail: string;
|
||||
};
|
||||
|
||||
export type AddressEditExpose = {
|
||||
getArea: () => AreaColumnOption[];
|
||||
setAreaCode: (code?: string | undefined) => void;
|
||||
setAddressDetail: (value: string) => void;
|
||||
};
|
||||
|
@ -1,6 +0,0 @@
|
||||
@import '../style/var.less';
|
||||
|
||||
@address-edit-padding: var(--van-padding-sm);
|
||||
@address-edit-buttons-padding: var(--van-padding-xl) var(--van-padding-base);
|
||||
@address-edit-button-margin-bottom: var(--van-padding-sm);
|
||||
@address-edit-button-font-size: var(--van-font-size-lg);
|
@ -15,7 +15,7 @@ import AddressListItem, { AddressListAddress } from './AddressListItem';
|
||||
|
||||
const [name, bem, t] = createNamespace('address-list');
|
||||
|
||||
const addressListProps = {
|
||||
export const addressListProps = {
|
||||
list: makeArrayProp<AddressListAddress>(),
|
||||
modelValue: numericProp,
|
||||
switchable: truthProp,
|
||||
@ -36,9 +36,9 @@ export default defineComponent({
|
||||
'add',
|
||||
'edit',
|
||||
'select',
|
||||
'click-item',
|
||||
'edit-disabled',
|
||||
'select-disabled',
|
||||
'clickItem',
|
||||
'editDisabled',
|
||||
'selectDisabled',
|
||||
'update:modelValue',
|
||||
],
|
||||
|
||||
@ -49,12 +49,12 @@ export default defineComponent({
|
||||
disabled?: boolean
|
||||
) => {
|
||||
const onEdit = () =>
|
||||
emit(disabled ? 'edit-disabled' : 'edit', item, index);
|
||||
emit(disabled ? 'editDisabled' : 'edit', item, index);
|
||||
|
||||
const onClick = () => emit('click-item', item, index);
|
||||
const onClick = () => emit('clickItem', item, index);
|
||||
|
||||
const onSelect = () => {
|
||||
emit(disabled ? 'select-disabled' : 'select', item, index);
|
||||
emit(disabled ? 'selectDisabled' : 'select', item, index);
|
||||
|
||||
if (!disabled) {
|
||||
emit('update:modelValue', item.id);
|
||||
@ -90,7 +90,7 @@ export default defineComponent({
|
||||
<Button
|
||||
round
|
||||
block
|
||||
type="danger"
|
||||
type="primary"
|
||||
text={props.addButtonText || t('add')}
|
||||
class={bem('add')}
|
||||
onClick={() => emit('add')}
|
||||
|
@ -62,7 +62,7 @@ export default defineComponent({
|
||||
}
|
||||
if (props.address.isDefault && props.defaultTagText) {
|
||||
return (
|
||||
<Tag type="danger" round class={bem('tag')}>
|
||||
<Tag type="primary" round class={bem('tag')}>
|
||||
{props.defaultTagText}
|
||||
</Tag>
|
||||
);
|
||||
@ -98,11 +98,11 @@ export default defineComponent({
|
||||
<div class={bem({ disabled })} onClick={onClick}>
|
||||
<Cell
|
||||
v-slots={{
|
||||
value: renderContent,
|
||||
title: renderContent,
|
||||
'right-icon': renderRightIcon,
|
||||
}}
|
||||
border={false}
|
||||
valueClass={bem('value')}
|
||||
titleClass={bem('title')}
|
||||
/>
|
||||
{slots.bottom?.(extend({}, props.address, { disabled }))}
|
||||
</div>
|
||||
|
@ -34,7 +34,7 @@ app.use(AddressList);
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
@ -63,8 +63,8 @@ export default {
|
||||
},
|
||||
];
|
||||
|
||||
const onAdd = () => Toast('Add');
|
||||
const onEdit = (item, index) => Toast('Edit:' + index);
|
||||
const onAdd = () => showToast('Add');
|
||||
const onEdit = (item, index) => showToast('Edit:' + index);
|
||||
|
||||
return {
|
||||
list,
|
||||
@ -148,5 +148,5 @@ The component provides the following CSS variables, which can be used to customi
|
||||
| --van-address-list-item-disabled-text-color | _var(--van-text-color-3)_ | - |
|
||||
| --van-address-list-item-font-size | _13px_ | - |
|
||||
| --van-address-list-item-line-height | _var(--van-line-height-sm)_ | - |
|
||||
| --van-address-list-item-radio-icon-color | _var(--van-danger-color)_ | - |
|
||||
| --van-address-list-radio-color | _var(--van-primary-color)_ | - |
|
||||
| --van-address-list-edit-icon-size | _20px_ | - |
|
||||
|
@ -34,7 +34,7 @@ app.use(AddressList);
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
import { Toast } from 'vant';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
@ -63,8 +63,8 @@ export default {
|
||||
},
|
||||
];
|
||||
|
||||
const onAdd = () => Toast('新增地址');
|
||||
const onEdit = (item, index) => Toast('编辑地址:' + index);
|
||||
const onAdd = () => showToast('新增地址');
|
||||
const onEdit = (item, index) => showToast('编辑地址:' + index);
|
||||
|
||||
return {
|
||||
list,
|
||||
@ -148,5 +148,5 @@ import type { AddressListProps, AddressListAddress } from 'vant';
|
||||
| --van-address-list-item-disabled-text-color | _var(--van-text-color-3)_ | - |
|
||||
| --van-address-list-item-font-size | _13px_ | - |
|
||||
| --van-address-list-item-line-height | _var(--van-line-height-sm)_ | - |
|
||||
| --van-address-list-item-radio-icon-color | _var(--van-danger-color)_ | - |
|
||||
| --van-address-list-radio-color | _var(--van-primary-color)_ | - |
|
||||
| --van-address-list-edit-icon-size | _20px_ | - |
|
||||
|
@ -2,7 +2,7 @@
|
||||
import VanAddressList from '..';
|
||||
import { ref } from 'vue';
|
||||
import { useTranslate } from '../../../docs/site';
|
||||
import { Toast } from '../../toast';
|
||||
import { showToast } from '../../toast';
|
||||
|
||||
const t = useTranslate({
|
||||
'zh-CN': {
|
||||
@ -67,10 +67,10 @@ const t = useTranslate({
|
||||
|
||||
const chosenAddressId = ref('1');
|
||||
const onAdd = () => {
|
||||
Toast(t('add'));
|
||||
showToast(t('add'));
|
||||
};
|
||||
const onEdit = (item: unknown, index: number) => {
|
||||
Toast(`${t('edit')}:${index}`);
|
||||
showToast(`${t('edit')}:${index}`);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -1,19 +1,17 @@
|
||||
@import './var.less';
|
||||
|
||||
:root {
|
||||
--van-address-list-padding: @address-list-padding;
|
||||
--van-address-list-disabled-text-color: @address-list-disabled-text-color;
|
||||
--van-address-list-disabled-text-padding: @address-list-disabled-text-padding;
|
||||
--van-address-list-disabled-text-font-size: @address-list-disabled-text-font-size;
|
||||
--van-address-list-disabled-text-line-height: @address-list-disabled-text-line-height;
|
||||
--van-address-list-add-button-z-index: @address-list-add-button-z-index;
|
||||
--van-address-list-item-padding: @address-list-item-padding;
|
||||
--van-address-list-item-text-color: @address-list-item-text-color;
|
||||
--van-address-list-item-disabled-text-color: @address-list-item-disabled-text-color;
|
||||
--van-address-list-item-font-size: @address-list-item-font-size;
|
||||
--van-address-list-item-line-height: @address-list-item-line-height;
|
||||
--van-address-list-item-radio-icon-color: @address-list-item-radio-icon-color;
|
||||
--van-address-list-edit-icon-size: @address-list-edit-icon-size;
|
||||
body {
|
||||
--van-address-list-padding: var(--van-padding-sm) var(--van-padding-sm) 80px;
|
||||
--van-address-list-disabled-text-color: var(--van-text-color-2);
|
||||
--van-address-list-disabled-text-padding: calc(var(--van-padding-base) * 5) 0;
|
||||
--van-address-list-disabled-text-font-size: var(--van-font-size-md);
|
||||
--van-address-list-disabled-text-line-height: var(--van-line-height-md);
|
||||
--van-address-list-add-button-z-index: 999;
|
||||
--van-address-list-item-padding: var(--van-padding-sm);
|
||||
--van-address-list-item-text-color: var(--van-text-color);
|
||||
--van-address-list-item-disabled-text-color: var(--van-text-color-3);
|
||||
--van-address-list-item-font-size: 13px;
|
||||
--van-address-list-item-line-height: var(--van-line-height-sm);
|
||||
--van-address-list-radio-color: var(--van-primary-color);
|
||||
--van-address-list-edit-icon-size: 20px;
|
||||
}
|
||||
|
||||
.van-address-list {
|
||||
@ -30,7 +28,7 @@
|
||||
width: 100%;
|
||||
padding-left: var(--van-padding-md);
|
||||
padding-right: var(--van-padding-md);
|
||||
background-color: var(--van-background-color-light);
|
||||
background-color: var(--van-background-2);
|
||||
}
|
||||
|
||||
&__add {
|
||||
@ -48,14 +46,14 @@
|
||||
|
||||
.van-address-item {
|
||||
padding: var(--van-address-list-item-padding);
|
||||
background-color: var(--van-background-color-light);
|
||||
border-radius: var(--van-border-radius-lg);
|
||||
background-color: var(--van-background-2);
|
||||
border-radius: var(--van-radius-lg);
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: var(--van-padding-sm);
|
||||
}
|
||||
|
||||
&__value {
|
||||
&__title {
|
||||
padding-right: 44px;
|
||||
}
|
||||
|
||||
@ -106,7 +104,7 @@
|
||||
}
|
||||
|
||||
.van-radio__icon--checked .van-icon {
|
||||
background-color: var(--van-address-list-item-radio-icon-color);
|
||||
border-color: var(--van-address-list-item-radio-icon-color);
|
||||
background-color: var(--van-address-list-radio-color);
|
||||
border-color: var(--van-address-list-radio-color);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user