mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
Merge branch 'dev' into next
This commit is contained in:
commit
9b3b1e896c
@ -1,7 +1,9 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
@ -9,15 +11,3 @@ insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.js]
|
||||
indent_size = 2
|
||||
|
||||
[*.vue]
|
||||
indent_size = 2
|
||||
|
||||
[*.css]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
8
.github/CONTRIBUTING.md
vendored
8
.github/CONTRIBUTING.md
vendored
@ -38,8 +38,12 @@ npm run dev
|
||||
# open http://localhost:8080
|
||||
```
|
||||
|
||||
## Contribute from the browser with a single click
|
||||
## Contribute online with a single click
|
||||
|
||||
You can use gitpod (A free online IDE) with a single click it will launch a ready to code workspace with dependencies pre-installed and the web server running so that you don't have to waste any time on the dev setup and start contributing straight away.
|
||||
You can use Gitpod (A free online VS Code-like IDE) for contributing, With a single click it will launch a workspace and automatically:
|
||||
|
||||
- clone the vant repo.
|
||||
- run `npm run bootstrap`.
|
||||
- run `npm run dev`.
|
||||
|
||||
[](https://gitpod.io/#https://github.com/youzan/vant)
|
||||
|
14
.ls-lint.yml
Normal file
14
.ls-lint.yml
Normal file
@ -0,0 +1,14 @@
|
||||
ls:
|
||||
src/**:
|
||||
.js: kebab-case | PascalCase
|
||||
.ts: kebab-case | PascalCase
|
||||
.tsx: kebab-case | PascalCase
|
||||
.vue: kebab-case | PascalCase
|
||||
.less: kebab-case
|
||||
.spec.js: kebab-case
|
||||
|
||||
types:
|
||||
.d.ts: kebab-case
|
||||
|
||||
ignore:
|
||||
- src/locale/lang
|
29
README.md
29
README.md
@ -15,8 +15,13 @@
|
||||
<p align="center">
|
||||
🔥 <a href="https://youzan.github.io/vant">文档网站</a>
|
||||
|
||||
|
||||
💡 <a href="https://vant-contrib.gitee.io/vant">国内镜像文档</a>
|
||||
|
||||
|
||||
🇨🇳 <a href="./README.zh-CN.md">中文版介绍</a>
|
||||
|
||||
|
||||
🚀 <a href="https://github.com/youzan/vant-weapp" target="_blank">小程序版</a>
|
||||
</p>
|
||||
|
||||
@ -24,14 +29,14 @@
|
||||
|
||||
## Features
|
||||
|
||||
* 60+ Reusable components
|
||||
* 90% Unit test coverage
|
||||
* Extensive documentation and demos
|
||||
* Support [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)
|
||||
* Support Custom Theme
|
||||
* Support i18n
|
||||
* Support TS
|
||||
* Support SSR
|
||||
- 60+ Reusable components
|
||||
- 90% Unit test coverage
|
||||
- Extensive documentation and demos
|
||||
- Support [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)
|
||||
- Support Custom Theme
|
||||
- Support i18n
|
||||
- Support TS
|
||||
- Support SSR
|
||||
|
||||
## Install
|
||||
|
||||
@ -66,17 +71,17 @@ Modern browsers and Android 4.0+, iOS 8.0+.
|
||||
## Ecosystem
|
||||
|
||||
| Project | Description |
|
||||
|-----|------|
|
||||
| --- | --- |
|
||||
| [vant-demo](https://github.com/youzan/vant-demo) | Official vant demo collection |
|
||||
| [vant-weapp](https://github.com/youzan/vant-weapp) | WeChat MiniProgram UI |
|
||||
| [vant-weapp](https://github.com/youzan/vant-weapp) | WeChat MiniProgram UI |
|
||||
| [vant-cli](https://github.com/youzan/vant/tree/dev/packages/vant-cli) | Scaffold for UI library |
|
||||
| [vant-icons](https://github.com/youzan/vant/tree/dev/packages/vant-icons) | Vant icons |
|
||||
| [vant-touch-emulator](https://github.com/youzan/vant/tree/dev/packages/vant-touch-emulator) | Using vant in desktop browsers |
|
||||
|
||||
## Links
|
||||
|
||||
* [Documentation](https://youzan.github.io/vant)
|
||||
* [Changelog](https://youzan.github.io/vant#/en-US/changelog)
|
||||
- [Documentation](https://youzan.github.io/vant)
|
||||
- [Changelog](https://youzan.github.io/vant#/en-US/changelog)
|
||||
|
||||
## Preview
|
||||
|
||||
|
@ -14,6 +14,10 @@
|
||||
<p align="center">
|
||||
🔥 <a href="https://youzan.github.io/vant">文档网站</a>
|
||||
|
||||
|
||||
💡 <a href="https://vant-contrib.gitee.io/vant">国内镜像文档</a>
|
||||
|
||||
|
||||
🚀 <a href="https://github.com/youzan/vant-weapp" target="_blank">小程序版</a>
|
||||
</p>
|
||||
|
||||
@ -21,14 +25,14 @@
|
||||
|
||||
## 特性
|
||||
|
||||
* 60+ 高质量组件
|
||||
* 90% 单元测试覆盖率
|
||||
* 完善的中英文文档和示例
|
||||
* 支持按需引入
|
||||
* 支持主题定制
|
||||
* 支持国际化
|
||||
* 支持 TS
|
||||
* 支持 SSR
|
||||
- 60+ 高质量组件
|
||||
- 90% 单元测试覆盖率
|
||||
- 完善的中英文文档和示例
|
||||
- 支持按需引入
|
||||
- 支持主题定制
|
||||
- 支持国际化
|
||||
- 支持 TS
|
||||
- 支持 SSR
|
||||
|
||||
## 安装
|
||||
|
||||
@ -79,7 +83,7 @@ vant 也支持按需引入、CDN 引入等方式,详细说明见 [快速上手
|
||||
## 生态
|
||||
|
||||
| 项目 | 描述 |
|
||||
|-----|------|
|
||||
| --- | --- |
|
||||
| [vant-demo](https://github.com/youzan/vant-demo) | Vant 官方示例合集 |
|
||||
| [vant-weapp](https://github.com/youzan/vant-weapp) | 微信小程序组件库 |
|
||||
| [vant-cli](https://github.com/youzan/vant/tree/dev/packages/vant-cli) | 开箱即用的组件库搭建工具 |
|
||||
@ -88,9 +92,9 @@ vant 也支持按需引入、CDN 引入等方式,详细说明见 [快速上手
|
||||
|
||||
## 链接
|
||||
|
||||
* [详细文档](https://youzan.github.io/vant)
|
||||
* [更新日志](https://youzan.github.io/vant#/zh-CN/changelog)
|
||||
* [码云镜像](https://gitee.com/organizations/vant-contrib)
|
||||
- [详细文档](https://youzan.github.io/vant)
|
||||
- [更新日志](https://youzan.github.io/vant#/zh-CN/changelog)
|
||||
- [码云镜像](https://gitee.com/organizations/vant-contrib)
|
||||
|
||||
## 手机预览
|
||||
|
||||
|
@ -1,5 +1,205 @@
|
||||
# Changelog
|
||||
|
||||
### Intro
|
||||
|
||||
Vant follows [Semantic Versioning 2.0.0](https://semver.org/lang/zh-CN/).
|
||||
|
||||
**Release Schedule**
|
||||
|
||||
- Patch version:released weekly, including features and bug fixes.
|
||||
- Minor version:released every one to two months, including backwards compatible features.
|
||||
- Major version:including breaking changes and new features.
|
||||
|
||||
### [v2.6.2](https://github.com/youzan/vant/compare/v2.6.1...v2.6.2)
|
||||
|
||||
`2020-04-18`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Empty: support offline scenario [#6055](https://github.com/youzan/vant/issues/6055)
|
||||
- NoticeBar: add replay event [#6079](https://github.com/youzan/vant/issues/6079)
|
||||
- Overlay: add lock-scroll prop [#6082](https://github.com/youzan/vant/issues/6082)
|
||||
- Uploader: add lazy-load prop [#6083](https://github.com/youzan/vant/issues/6083)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Checkbox: get changed value in click event [#6066](https://github.com/youzan/vant/issues/6066)
|
||||
- Picker: setColumnValues failed in cascade mode [#6080](https://github.com/youzan/vant/issues/6080)
|
||||
- Slider: incorrect bar-height when vertical [#6065](https://github.com/youzan/vant/issues/6065)
|
||||
- Swipe: incorrect width after resize if hidden [#6084](https://github.com/youzan/vant/issues/6084)
|
||||
|
||||
### [v2.6.1](https://github.com/youzan/vant/compare/v2.6.0...v2.6.1)
|
||||
|
||||
`2020-04-14`
|
||||
|
||||
**Feature**
|
||||
|
||||
- AddressEdit: add area-placeholder prop [#6023](https://github.com/youzan/vant/issues/6023)
|
||||
- ImagePreview: support local registration [#6031](https://github.com/youzan/vant/issues/6031)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- sortChildren broke SSR [#6046](https://github.com/youzan/vant/issues/6046)
|
||||
- Calendar: default-date should be today, close #6025 [#6025](https://github.com/youzan/vant/issues/6025) [#6028](https://github.com/youzan/vant/issues/6028)
|
||||
|
||||
### [v2.6.0](https://github.com/youzan/vant/compare/v2.5.9...v2.6.0)
|
||||
|
||||
`2020-04-09`
|
||||
|
||||
**Feature**
|
||||
|
||||
- add ShareSheet component [#6019](https://github.com/youzan/vant/issues/6019)
|
||||
- add Empty component [#6010](https://github.com/youzan/vant/issues/6010)
|
||||
|
||||
**Feature**
|
||||
|
||||
- Form: add show-error prop [#5941](https://github.com/youzan/vant/issues/5941)
|
||||
- Tabbar: add placeholder prop [#5979](https://github.com/youzan/vant/issues/5979)
|
||||
- Sku: enable safe-area-inset-bottom by default [#5960](https://github.com/youzan/vant/issues/5960)
|
||||
- Tabbar: enable safe-area-inset-bottom by default when fixed [#5968](https://github.com/youzan/vant/issues/5968)
|
||||
- SubmitBar: enable safe-area-inset-bottom by default [#5956](https://github.com/youzan/vant/issues/5956)
|
||||
- GoodsAction: enable safe-area-inset-bottom by default [#5955](https://github.com/youzan/vant/issues/5955)
|
||||
- Swipe: allow swipe multiple item at once [#5953](https://github.com/youzan/vant/issues/5953)
|
||||
- Calendar: auto selected to max range [#5992](https://github.com/youzan/vant/issues/5992)
|
||||
|
||||
**Improvement**
|
||||
|
||||
- NavBar: improve active feedback [#5949](https://github.com/youzan/vant/issues/5949)
|
||||
- Popup: improve leave animation timing function [#5954](https://github.com/youzan/vant/issues/5954)
|
||||
- Picker: improve scroll speed [#5951](https://github.com/youzan/vant/issues/5951)
|
||||
- Swipe: improve swipe threshold [#6003](https://github.com/youzan/vant/issues/6003)
|
||||
- TreeSelect: update nav background color [#5991](https://github.com/youzan/vant/issues/5991)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Button: icon-prefix prop not work [#5947](https://github.com/youzan/vant/issues/5947)
|
||||
- Calendar: rendering error when activated [#5978](https://github.com/youzan/vant/issues/5978)
|
||||
- Form: incorrect validation order when add field dynamically [b8dea3](https://github.com/youzan/vant/commit/b8dea3c13b7dbf6533169653c493a3156c07f1d4)
|
||||
- NavBar: icon align center [#5948](https://github.com/youzan/vant/issues/5948)
|
||||
- Stepper: readonly not work in lagacy mobile safari [#5976](https://github.com/youzan/vant/issues/5976)
|
||||
|
||||
### [v2.5.9](https://github.com/youzan/vant/compare/v2.5.8...v2.5.9)
|
||||
|
||||
`2020-03-31`
|
||||
|
||||
**Feature**
|
||||
|
||||
- AddressEdit: add click-area event [#5939](https://github.com/youzan/vant/issues/5939)
|
||||
- NavBar: add placeholder prop [#5938](https://github.com/youzan/vant/issues/5938)
|
||||
- Steps: add click-step event [#5937](https://github.com/youzan/vant/issues/5937)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- NumberKeyboard: show-delete-key prop not work [#5935](https://github.com/youzan/vant/issues/5935)
|
||||
- Toast: incorrect height in legacy devices [#5931](https://github.com/youzan/vant/issues/5931)
|
||||
- Sticky: Fixed error when accessing the window during SSR [#5958](https://github.com/youzan/vant/issues/5958)
|
||||
|
||||
### [v2.5.8](https://github.com/youzan/vant/compare/v2.5.7...v2.5.8)
|
||||
|
||||
`2020-03-27`
|
||||
|
||||
**Feature**
|
||||
|
||||
- support generate webstorm types [#5900](https://github.com/youzan/vant/issues/5900)
|
||||
- Circle: improve text padding [10f32d](https://github.com/youzan/vant/commit/10f32d6619199e99ff743cb5425db1e54e495fd0)
|
||||
- Form: add show-error-message prop [#5927](https://github.com/youzan/vant/issues/5927)
|
||||
- ImagePreview: enable swipe lazy-render [#5879](https://github.com/youzan/vant/issues/5879)
|
||||
- Sidebar: set overflow-y auto [#5921](https://github.com/youzan/vant/issues/5921)
|
||||
- Swipe: add lazy-render prop [365f2b](https://github.com/youzan/vant/commit/365f2b16f7d9592f92413e206439585468a8a1c7)
|
||||
- Swipe: use flex layout [f701de](https://github.com/youzan/vant/commit/f701de9e58db5f88a582e3277c97a0c9ca99eec4)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Calendar: fix the default date of multiple selection type [#5907](https://github.com/youzan/vant/issues/5907)
|
||||
- PullRefresh: track should be full of container [#5878](https://github.com/youzan/vant/issues/5878)
|
||||
- Sticky: shoud rerender after visibility changed [#5888](https://github.com/youzan/vant/issues/5888)
|
||||
- Swipe: incorrect offset after resize [#5922](https://github.com/youzan/vant/issues/5922)
|
||||
|
||||
### [v2.5.7](https://github.com/youzan/vant/compare/v2.5.6...v2.5.7)
|
||||
|
||||
`2020-03-20`
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Locale: fix incorrect japanese filename [e8c88a](https://github.com/youzan/vant/commit/e8c88a380217eb48cef8aa7dc29d378a1031120a)
|
||||
|
||||
### [v2.5.6](https://github.com/youzan/vant/compare/v2.5.5...v2.5.6)
|
||||
|
||||
`2020-03-20`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Calendar: add allow-same-day prop [#5688](https://github.com/youzan/vant/issues/5688)
|
||||
- GoodsAction: add badge prop, mark info prop as deprecated [0dea9e](https://github.com/youzan/vant/commit/0dea9e2cb1562decc07ef4467d085247b91924fd)
|
||||
- GridItem: add badge prop, mark info prop as deprecated [db94b2](https://github.com/youzan/vant/commit/db94b20c8258ebb31bac99ea1f0c918d62de1059)
|
||||
- Icon: add badge prop, mark info prop deprecated [575577](https://github.com/youzan/vant/commit/575577ed58a1e6daa36ffba7db8054556aa0d24d)
|
||||
- ImagePreview: add closed event [5b279a](https://github.com/youzan/vant/commit/5b279ab0dc862c0a3257d18fe17d04ed8dd8c1dd)
|
||||
- locale: add japanese language [#5853](https://github.com/youzan/vant/issues/5853) [#5854](https://github.com/youzan/vant/issues/5854)
|
||||
- SidebarItem: add badge prop, mark info prop as deprecated [01482f](https://github.com/youzan/vant/commit/01482f20bc2150a7e4667fac062b4f129b0ac0c1)
|
||||
- Tab: add badge prop, mark info prop as deprecated [214b13](https://github.com/youzan/vant/commit/214b13b8fff411a401fe6ccfc9eb979a51df7461)
|
||||
- TabbarItem: add badge prop, mark info prop as deprecated [d61cbd](https://github.com/youzan/vant/commit/d61cbdd086c9050fa467803be676a1eb14d50f16)
|
||||
- TreeSelect: add badge option, mark info option as deprecated [0cc7a3](https://github.com/youzan/vant/commit/0cc7a305287f43314910f893092c09004cef5349)
|
||||
- Uploader: add chooseFile method [#5818](https://github.com/youzan/vant/issues/5818)
|
||||
- Uploader: add show-upload prop [66c0b3](https://github.com/youzan/vant/commit/66c0b3c1b7d101f242071cf90e5c0b2b899edbdd)
|
||||
- Uploader: use before read promise resolved value [#5813](https://github.com/youzan/vant/issues/5813)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Calendar: incorret button native-type [#5873](https://github.com/youzan/vant/issues/5873)
|
||||
- Field: should not cache input slot [#5868](https://github.com/youzan/vant/issues/5868)
|
||||
- ImagePreview: should not show previews image [7fcfc5](https://github.com/youzan/vant/commit/7fcfc5f3270d3507a002247c53a29da211f1ecb6)
|
||||
- Picker: update cascade after setColumnIndex [#5807](https://github.com/youzan/vant/issues/5807)
|
||||
- Picker: update cascade after setColumnValue [#5807](https://github.com/youzan/vant/issues/5807)
|
||||
- Toast: should lock scroll when use forbidClick [df8777](https://github.com/youzan/vant/commit/df877751b3497eb6477797ee1a52933067e57676)
|
||||
|
||||
### [v2.5.5](https://github.com/youzan/vant/compare/v2.5.4...v2.5.5)
|
||||
|
||||
`2020-03-11`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Calendar: add show-title prop [#5779](https://github.com/youzan/vant/issues/5779)
|
||||
- Calendar: add show-subtitle prop [#5779](https://github.com/youzan/vant/issues/5779)
|
||||
- Field: improve number keyboard [e89baa](https://github.com/youzan/vant/commit/e89baa12ae24dbd27466bd6ec694074ab99acf5d)
|
||||
- Stepper: improve number keyboard [58e74a](https://github.com/youzan/vant/commit/58e74a9e8bfc36f69103c6a301170c5f6ada03dd)
|
||||
- GoodsActionIcon: add dot prop [b983ac](https://github.com/youzan/vant/commit/b983ac08919056e1095767d1deb3f78e5274b41c)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- AddressEdit: check addressDetail only when showDetail is true [#5803](https://github.com/youzan/vant/issues/5803)
|
||||
- Calendar: color not work in multiple mode [#5786](https://github.com/youzan/vant/issues/5786)
|
||||
- Field: should not get formValue from button slot [#5785](https://github.com/youzan/vant/issues/5785)
|
||||
- GoodsActionIcon: info not work with icon slot [#5788](https://github.com/youzan/vant/issues/5788)
|
||||
- Stepper: skip form number validation [#5792](https://github.com/youzan/vant/issues/5792)
|
||||
- Sticky: should not detect scroll when hidden [41e5c0](https://github.com/youzan/vant/commit/41e5c035dcf75c1f1d4c04673d3db255e439d452)
|
||||
|
||||
### [v2.5.4](https://github.com/youzan/vant/compare/v2.5.3...v2.5.4)
|
||||
|
||||
`2020-03-08`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Calendar: add multiple type [#5705](https://github.com/youzan/vant/issues/5705)
|
||||
- Field: input inherit line-height [#5737](https://github.com/youzan/vant/issues/5737)
|
||||
- Search: add left slot [#5771](https://github.com/youzan/vant/issues/5771)
|
||||
- Uploader: add upload-icon prop [b3b46c](https://github.com/youzan/vant/commit/b3b46cde45f885b746a2a633e5fc0e87e1881abe)
|
||||
- Uploader: increase border-radius to 8px [c67918](https://github.com/youzan/vant/commit/c6791841f4b06e699a684da0243526147438d852)
|
||||
- Uploader: update upload area style [bd4e64](https://github.com/youzan/vant/commit/bd4e64190e63eea30c342ea5255d8603a70385f9)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Calendar: incorrect position when poppable is false [#5760](https://github.com/youzan/vant/issues/5760)
|
||||
- DropdownMenu: menu ref may not exist in some cases [#5770](https://github.com/youzan/vant/issues/5770)
|
||||
- Tabs: incorrect scrollspy position while inside a scroller [0993b3](https://github.com/youzan/vant/commit/0993b394b16fdbf92bdf02d39090e631bba1f471)
|
||||
- Tabs: lock scroll not work when using scrollspy [#5727](https://github.com/youzan/vant/issues/5727)
|
||||
- TimePicker: incorrect value when set min-minute dynamically [#5767](https://github.com/youzan/vant/issues/5767)
|
||||
|
||||
**Types**
|
||||
|
||||
- Form: fix missing scrollToField method [df4439](https://github.com/youzan/vant/commit/df4439e9f6759a446b522652233703601093e99d)
|
||||
- ImagePreview: fix missing closeable option [d5438d](https://github.com/youzan/vant/commit/d5438dfe0dc9df22e94881b57def33207eca44e6)
|
||||
- Toast: fix missing iconPrefix option [3237e5](https://github.com/youzan/vant/commit/3237e56561e1b6b80ea3431f3b8a9f30f61d4b08)
|
||||
|
||||
### [v2.5.3](https://github.com/youzan/vant/compare/v2.5.2...v2.5.3)
|
||||
|
||||
`2020-02-28`
|
||||
|
@ -10,6 +10,200 @@ Vant 遵循 [Semver](https://semver.org/lang/zh-CN/) 语义化版本规范。
|
||||
- 次版本号:每隔一至二个月发布,包含新特性和较大的功能更新,向下兼容。
|
||||
- 主版本号:发布时间不定,包含不兼容更新,预计下一个主版本会与 Vue 3.0 同期发布。
|
||||
|
||||
### [v2.6.2](https://github.com/youzan/vant/compare/v2.6.1...v2.6.2)
|
||||
|
||||
`2020-04-18`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Empty: 支持在离线环境下使用 network 图片 [#6055](https://github.com/youzan/vant/issues/6055)
|
||||
- NoticeBar: 新增 replay 事件,在每次滚动结束时触发 [#6079](https://github.com/youzan/vant/issues/6079)
|
||||
- Overlay: 新增 lock-scroll 属性,用于控制是否锁定背景滚动 [#6082](https://github.com/youzan/vant/issues/6082)
|
||||
- Uploader: 新增 lazy-load 属性,用于开启图片懒加载 [#6083](https://github.com/youzan/vant/issues/6083)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Checkbox: 修复在 click 事件的回调中获取到的 value 未改变的问题 [#6066](https://github.com/youzan/vant/issues/6066)
|
||||
- Picker: 修复级联模式下使用 setColumnValues 方法导致报错的问题 [#6080](https://github.com/youzan/vant/issues/6080)
|
||||
- Slider: 修复在垂直模式下使用 bar-height 后样式错误的问题 [#6065](https://github.com/youzan/vant/issues/6065)
|
||||
- Swipe: 修复元素隐藏且触发 resize 事件后渲染错误的问题 [#6084](https://github.com/youzan/vant/issues/6084)
|
||||
|
||||
### [v2.6.1](https://github.com/youzan/vant/compare/v2.6.0...v2.6.1)
|
||||
|
||||
`2020-04-14`
|
||||
|
||||
**Feature**
|
||||
|
||||
- AddressEdit: 新增 area-placeholder 属性 [#6023](https://github.com/youzan/vant/issues/6023)
|
||||
- ImagePreview: 支持通过局部注册的方式使用 [#6031](https://github.com/youzan/vant/issues/6031)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Calendar: 修复 default-date 默认值为 min-date 而不是今天的问题 [#6025](https://github.com/youzan/vant/issues/6025) [#6028](https://github.com/youzan/vant/issues/6028)
|
||||
- 修复部分组件在 SSR 时报错 `Cannot read property 'children' of null` 的问题 [#6046](https://github.com/youzan/vant/issues/6046)
|
||||
|
||||
### [v2.6.0](https://github.com/youzan/vant/compare/v2.5.9...v2.6.0)
|
||||
|
||||
`2020-04-09`
|
||||
|
||||
**Feature**
|
||||
|
||||
- 新增 ShareSheet 分享面板组件,用于进行分享操作 [#6019](https://github.com/youzan/vant/issues/6019)
|
||||
- 新增 Empty 空状态组件,作为空状态时的占位提示 [#6010](https://github.com/youzan/vant/issues/6010)
|
||||
|
||||
<img src="https://img.yzcdn.cn/vant/component-preview-2.6.png" style="width: 540px;">
|
||||
|
||||
**Feature**
|
||||
|
||||
- Form: 新增 show-error 属性,用于控制展示错误提示 [#5941](https://github.com/youzan/vant/issues/5941)
|
||||
- Tabbar: 新增 placeholder 属性,用于在吸底时生成占位元素 [#5979](https://github.com/youzan/vant/issues/5979)
|
||||
- Sku: 默认开启底部安全区适配 [#5960](https://github.com/youzan/vant/issues/5960)
|
||||
- SubmitBar: 默认开启底部安全区适配 [#5956](https://github.com/youzan/vant/issues/5956)
|
||||
- GoodsAction: 默认开启底部安全区适配 [#5955](https://github.com/youzan/vant/issues/5955)
|
||||
- Tabbar: 固定在底部时默认开启底部安全区适配 [#5968](https://github.com/youzan/vant/issues/5968)
|
||||
- Swipe: 允许一次滚动多页轮播 [#5953](https://github.com/youzan/vant/issues/5953)
|
||||
- Calendar: 设置 max-range 后,选择超出范围时会自动选择到最大范围 [#5992](https://github.com/youzan/vant/issues/5992)
|
||||
|
||||
**Improvement**
|
||||
|
||||
- NavBar: 优化点击反馈效果 [#5949](https://github.com/youzan/vant/issues/5949)
|
||||
- Popup: 优化退场动画效果 [#5954](https://github.com/youzan/vant/issues/5954)
|
||||
- Picker: 优化惯性滑动速率 [#5951](https://github.com/youzan/vant/issues/5951)
|
||||
- Swipe: 优化滚动手势体验,滑动较慢时会回弹到原位置 [#6003](https://github.com/youzan/vant/issues/6003)
|
||||
- TreeSelect: 更新左侧栏背景色,增强区分度 [#5991](https://github.com/youzan/vant/issues/5991)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Button: 修复 icon-prefix 属性不生效的问题 [#5947](https://github.com/youzan/vant/issues/5947)
|
||||
- Calendar: 修复 keep-alive 时可能出现渲染空白的问题 [#5978](https://github.com/youzan/vant/issues/5978)
|
||||
- Form: 修复动态插入 Field 时校验顺序错误的问题 [b8dea3](https://github.com/youzan/vant/commit/b8dea3c13b7dbf6533169653c493a3156c07f1d4)
|
||||
- NavBar: 修复图标在部分机型上不居中的问题 [#5948](https://github.com/youzan/vant/issues/5948)
|
||||
- Stepper: 修复 disable-input 属性在低版本 safari 上不生效的问题 [#5976](https://github.com/youzan/vant/issues/5976)
|
||||
|
||||
### [v2.5.9](https://github.com/youzan/vant/compare/v2.5.8...v2.5.9)
|
||||
|
||||
`2020-03-31`
|
||||
|
||||
**Feature**
|
||||
|
||||
- AddressEdit: 新增 click-area 事件 [#5939](https://github.com/youzan/vant/issues/5939)
|
||||
- NavBar: 新增 placeholder 属性 [#5938](https://github.com/youzan/vant/issues/5938)
|
||||
- Steps: 新增 click-step 事件 [#5937](https://github.com/youzan/vant/issues/5937)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- NumberKeyboard: 修复 show-delete-key 属性不生效的问题 [#5935](https://github.com/youzan/vant/issues/5935)
|
||||
- Toast: 修复在部分机型上高度错误的问题 [#5931](https://github.com/youzan/vant/issues/5931)
|
||||
- Sticky: 修复 SSR 时访问 window 对象导致报错的问题 [#5958](https://github.com/youzan/vant/issues/5958)
|
||||
|
||||
### [v2.5.8](https://github.com/youzan/vant/compare/v2.5.7...v2.5.8)
|
||||
|
||||
`2020-03-27`
|
||||
|
||||
**Feature**
|
||||
|
||||
- 新增 Webstorm 的 web-types.json 定义文件,提供智能提示 [#5900](https://github.com/youzan/vant/issues/5900)
|
||||
- Form: 新增 show-error-message 属性 [#5927](https://github.com/youzan/vant/issues/5927)
|
||||
- ImagePreview: 开启延迟渲染,提高渲染性能 [#5879](https://github.com/youzan/vant/issues/5879)
|
||||
- Swipe: 新增 lazy-render 属性 [365f2b](https://github.com/youzan/vant/commit/365f2b16f7d9592f92413e206439585468a8a1c7)
|
||||
|
||||
**Improvement**
|
||||
|
||||
- Circle: 优化文字边距 [10f32d](https://github.com/youzan/vant/commit/10f32d6619199e99ff743cb5425db1e54e495fd0)
|
||||
- Sidebar: 新增 overflow-y: auto 样式 [#5921](https://github.com/youzan/vant/issues/5921)
|
||||
- Swipe: 调整为 flex 布局 [f701de](https://github.com/youzan/vant/commit/f701de9e58db5f88a582e3277c97a0c9ca99eec4)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Calendar: 修复 multiple 模式下 default-date 格式错误的问题 [#5907](https://github.com/youzan/vant/issues/5907)
|
||||
- PullRefresh: 修复内部元素高度未填满容器的问题 [#5878](https://github.com/youzan/vant/issues/5878)
|
||||
- Sticky: 修复切换显示状态时可能出现定位错误的问题 [#5888](https://github.com/youzan/vant/issues/5888)
|
||||
- Swipe: 修复屏幕 resize 后可能导致轮播位置错误的问题 [#5922](https://github.com/youzan/vant/issues/5922)
|
||||
|
||||
### [v2.5.7](https://github.com/youzan/vant/compare/v2.5.6...v2.5.7)
|
||||
|
||||
`2020-03-20`
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Locale: 修复日语配置文件命名错误的问题 [e8c88a](https://github.com/youzan/vant/commit/e8c88a380217eb48cef8aa7dc29d378a1031120a)
|
||||
|
||||
### [v2.5.6](https://github.com/youzan/vant/compare/v2.5.5...v2.5.6)
|
||||
|
||||
`2020-03-20`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Calendar: 新增 allow-same-day 属性 [#5688](https://github.com/youzan/vant/issues/5688)
|
||||
- GoodsAction: 新增 badge 属性 [0dea9e](https://github.com/youzan/vant/commit/0dea9e2cb1562decc07ef4467d085247b91924fd)
|
||||
- GridItem: 新增 badge 属性 [db94b2](https://github.com/youzan/vant/commit/db94b20c8258ebb31bac99ea1f0c918d62de1059)
|
||||
- Icon: 新增 badge 属性 [575577](https://github.com/youzan/vant/commit/575577ed58a1e6daa36ffba7db8054556aa0d24d)
|
||||
- ImagePreview: 新增 closed 事件 [5b279a](https://github.com/youzan/vant/commit/5b279ab0dc862c0a3257d18fe17d04ed8dd8c1dd)
|
||||
- locale: 新增日语配置文件 [#5853](https://github.com/youzan/vant/issues/5853) [#5854](https://github.com/youzan/vant/issues/5854)
|
||||
- SidebarItem: 新增 badge 属性 [01482f](https://github.com/youzan/vant/commit/01482f20bc2150a7e4667fac062b4f129b0ac0c1)
|
||||
- Tab: 新增 badge 属性 [214b13](https://github.com/youzan/vant/commit/214b13b8fff411a401fe6ccfc9eb979a51df7461)
|
||||
- TabbarItem: 新增 badge 属性 [d61cbd](https://github.com/youzan/vant/commit/d61cbdd086c9050fa467803be676a1eb14d50f16)
|
||||
- TreeSelect: 新增 badge 选项 [0cc7a3](https://github.com/youzan/vant/commit/0cc7a305287f43314910f893092c09004cef5349)
|
||||
- Uploader: 新增 chooseFile 方法 [#5818](https://github.com/youzan/vant/issues/5818)
|
||||
- Uploader: 新增 show-upload 属性 [66c0b3](https://github.com/youzan/vant/commit/66c0b3c1b7d101f242071cf90e5c0b2b899edbdd)
|
||||
- Uploader: 支持在 before-read 中返回修改后的文件对象 [#5813](https://github.com/youzan/vant/issues/5813)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Calendar: 修复在 Form 内使用时错误触发表单提交的问题 [#5873](https://github.com/youzan/vant/issues/5873)
|
||||
- Field: 修复通过插槽使用 Uploader 时上传图片未展示的问题 [#5868](https://github.com/youzan/vant/issues/5868)
|
||||
- ImagePreview: 修复上次调用结果未清除的问题 [7fcfc5](https://github.com/youzan/vant/commit/7fcfc5f3270d3507a002247c53a29da211f1ecb6)
|
||||
- Picker: 修复 setValues、setIndexes 等方法未触发多列联动更新的问题 [#5807](https://github.com/youzan/vant/issues/5807)
|
||||
- Toast: 修复设置 forbidClick 后未锁定滚动的问题 [df8777](https://github.com/youzan/vant/commit/df877751b3497eb6477797ee1a52933067e57676)
|
||||
|
||||
### [v2.5.5](https://github.com/youzan/vant/compare/v2.5.4...v2.5.5)
|
||||
|
||||
`2020-03-11`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Calendar: 新增 show-title 属性 [#5779](https://github.com/youzan/vant/issues/5779)
|
||||
- Calendar: 新增 show-subtitle 属性 [#5779](https://github.com/youzan/vant/issues/5779)
|
||||
- Field: 优化虚拟键盘,type="number" 调起数字键盘 [e89baa](https://github.com/youzan/vant/commit/e89baa12ae24dbd27466bd6ec694074ab99acf5d)
|
||||
- Stepper: 优化虚拟键盘,调起数字键盘 [58e74a](https://github.com/youzan/vant/commit/58e74a9e8bfc36f69103c6a301170c5f6ada03dd)
|
||||
- GoodsActionIcon: 新增 dot 属性 [b983ac](https://github.com/youzan/vant/commit/b983ac08919056e1095767d1deb3f78e5274b41c)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- AddressEdit: 修复 showDetail 为 false 时仍然会校验地址的问题 [#5803](https://github.com/youzan/vant/issues/5803)
|
||||
- Calendar: 修复在 multiple 模式下 color 属性不生效的问题 [#5786](https://github.com/youzan/vant/issues/5786)
|
||||
- Field: 修复 button 插槽可能导致表单校验失败的问题 [#5785](https://github.com/youzan/vant/issues/5785)
|
||||
- GoodsActionIcon: 修复使用 icon 插槽时 info 属性不生效的问题 [#5788](https://github.com/youzan/vant/issues/5788)
|
||||
- Stepper: 修复在 Form 中使用时必须输入整数的问题 [#5792](https://github.com/youzan/vant/issues/5792)
|
||||
- Sticky: 修复 Sticky 切换显隐导致位置错误的问题 [41e5c0](https://github.com/youzan/vant/commit/41e5c035dcf75c1f1d4c04673d3db255e439d452)
|
||||
|
||||
### [v2.5.4](https://github.com/youzan/vant/compare/v2.5.3...v2.5.4)
|
||||
|
||||
`2020-03-08`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Calendar: 新增 multiple 类型 [#5705](https://github.com/youzan/vant/issues/5705)
|
||||
- Field: 输入框增加 `line-height: inherit` 样式 [#5737](https://github.com/youzan/vant/issues/5737)
|
||||
- Search: 新增 left 插槽 [#5771](https://github.com/youzan/vant/issues/5771)
|
||||
- Uploader: 新增 upload-icon 属性 [b3b46c](https://github.com/youzan/vant/commit/b3b46cde45f885b746a2a633e5fc0e87e1881abe)
|
||||
- Uploader: 圆角大小由 4px 调整为 8px [c67918](https://github.com/youzan/vant/commit/c6791841f4b06e699a684da0243526147438d852)
|
||||
- Uploader: 优化上传区域样式 [bd4e64](https://github.com/youzan/vant/commit/bd4e64190e63eea30c342ea5255d8603a70385f9)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Calendar: 修复 poppable 为 false 无法自动定位到当前日期的问题 [#5760](https://github.com/youzan/vant/issues/5760)
|
||||
- DropdownMenu: 修复个别情况下 scrollIntoView 报错的问题 [#5770](https://github.com/youzan/vant/issues/5770)
|
||||
- Tabs: 修复 scrollspy 在自定义的滚动容器中无法跳转的问题 [0993b3](https://github.com/youzan/vant/commit/0993b394b16fdbf92bdf02d39090e631bba1f471)
|
||||
- Tabs: 修复 scrollspy 开启时在 safari 上可能出现标签弹回的问题 [#5727](https://github.com/youzan/vant/issues/5727)
|
||||
- TimePicker: 修复动态设置 min-date 时可能出现选中项错误的问题 [#5767](https://github.com/youzan/vant/issues/5767)
|
||||
|
||||
**Types**
|
||||
|
||||
- Form: 修复缺少 scrollToField 方法类型定义的问题 [df4439](https://github.com/youzan/vant/commit/df4439e9f6759a446b522652233703601093e99d)
|
||||
- ImagePreview: 修复缺少 closeable 选项类型定义的问题 [d5438d](https://github.com/youzan/vant/commit/d5438dfe0dc9df22e94881b57def33207eca44e6)
|
||||
- Toast: 修复缺少 iconPrefix 选项类型定义的问题 [3237e5](https://github.com/youzan/vant/commit/3237e56561e1b6b80ea3431f3b8a9f30f61d4b08)
|
||||
|
||||
### [v2.5.3](https://github.com/youzan/vant/compare/v2.5.2...v2.5.3)
|
||||
|
||||
`2020-02-28`
|
||||
|
@ -8,14 +8,14 @@
|
||||
|
||||
### Features
|
||||
|
||||
* 60+ Reusable components
|
||||
* 90% Unit test coverage
|
||||
* Extensive documentation and demos
|
||||
* Support [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)
|
||||
* Support Custom Theme
|
||||
* Support i18n
|
||||
* Support TS
|
||||
* Support SSR
|
||||
- 60+ Reusable components
|
||||
- 90% Unit test coverage
|
||||
- Extensive documentation and demos
|
||||
- Support [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)
|
||||
- Support Custom Theme
|
||||
- Support i18n
|
||||
- Support TS
|
||||
- Support SSR
|
||||
|
||||
### Quickstart
|
||||
|
||||
@ -32,17 +32,17 @@ Modern browsers and Android 4.0+, iOS 8.0+.
|
||||
### Ecosystem
|
||||
|
||||
| Project | Description |
|
||||
|-----|------|
|
||||
| --- | --- |
|
||||
| [vant-demo](https://github.com/youzan/vant-demo) | Official vant demo collection |
|
||||
| [vant-weapp](https://github.com/youzan/vant-weapp) | WeChat MiniProgram UI |
|
||||
| [vant-weapp](https://github.com/youzan/vant-weapp) | WeChat MiniProgram UI |
|
||||
| [vant-cli](https://github.com/youzan/vant/tree/dev/packages/vant-cli) | Scaffold for UI library |
|
||||
| [vant-icons](https://github.com/youzan/vant/tree/dev/packages/vant-icons) | Vant icons |
|
||||
| [vant-touch-emulator](https://github.com/youzan/vant/tree/dev/packages/vant-touch-emulator) | Using vant in desktop browsers |
|
||||
|
||||
### Links
|
||||
|
||||
* [Feedback](https://github.com/youzan/vant/issues)
|
||||
* [Changelog](#/en-US/changelog)
|
||||
- [Feedback](https://github.com/youzan/vant/issues)
|
||||
- [Changelog](#/en-US/changelog)
|
||||
|
||||
### LICENSE
|
||||
|
||||
|
@ -8,14 +8,14 @@
|
||||
|
||||
### 特性
|
||||
|
||||
* 60+ 高质量组件
|
||||
* 90% 单元测试覆盖率
|
||||
* 完善的中英文文档和示例
|
||||
* 支持按需引入
|
||||
* 支持主题定制
|
||||
* 支持国际化
|
||||
* 支持 TS
|
||||
* 支持 SSR
|
||||
- 60+ 高质量组件
|
||||
- 90% 单元测试覆盖率
|
||||
- 完善的中英文文档和示例
|
||||
- 支持按需引入
|
||||
- 支持主题定制
|
||||
- 支持国际化
|
||||
- 支持 TS
|
||||
- 支持 SSR
|
||||
|
||||
### 快速上手
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
### 生态
|
||||
|
||||
| 项目 | 描述 |
|
||||
|-----|------|
|
||||
| --- | --- |
|
||||
| [vant-demo](https://github.com/youzan/vant-demo) | Vant 官方示例合集 |
|
||||
| [vant-weapp](https://github.com/youzan/vant-weapp) | 微信小程序组件库 |
|
||||
| [vant-cli](https://github.com/youzan/vant/tree/dev/packages/vant-cli) | 开箱即用的组件库搭建工具 |
|
||||
@ -57,9 +57,9 @@
|
||||
|
||||
### 链接
|
||||
|
||||
* [意见反馈](https://github.com/youzan/vant/issues)
|
||||
* [更新日志](#/zh-CN/changelog)
|
||||
* [码云镜像](https://gitee.com/organizations/vant-contrib)
|
||||
- [意见反馈](https://github.com/youzan/vant/issues)
|
||||
- [更新日志](#/zh-CN/changelog)
|
||||
- [码云镜像](https://gitee.com/organizations/vant-contrib)
|
||||
|
||||
### 开源协议
|
||||
|
||||
|
@ -78,7 +78,7 @@ import { Button } from 'vant';
|
||||
import Button from 'vant/lib/button';
|
||||
import 'vant/lib/button/style';
|
||||
```
|
||||
|
||||
|
||||
### 3. Import all components
|
||||
|
||||
```js
|
||||
@ -97,17 +97,20 @@ The easiest way to use Vant is to include a CDN link in the html file, after whi
|
||||
|
||||
```html
|
||||
<!-- import style -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.4/lib/index.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/vant@2.6/lib/index.css"
|
||||
/>
|
||||
|
||||
<!-- import script -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vant@2.4/lib/vant.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vant@2.6/lib/vant.min.js"></script>
|
||||
|
||||
<script>
|
||||
// Render the Button component
|
||||
new Vue({
|
||||
el: '#app',
|
||||
template: `<van-button>Button</van-button>`
|
||||
template: `<van-button>Button</van-button>`,
|
||||
});
|
||||
|
||||
// Call function component
|
||||
@ -131,13 +134,13 @@ postcss config example:
|
||||
```js
|
||||
module.exports = {
|
||||
plugins: {
|
||||
'autoprefixer': {
|
||||
browsers: ['Android >= 4.0', 'iOS >= 8']
|
||||
autoprefixer: {
|
||||
browsers: ['Android >= 4.0', 'iOS >= 8'],
|
||||
},
|
||||
'postcss-pxtorem': {
|
||||
rootValue: 37.5,
|
||||
propList: ['*']
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
propList: ['*'],
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
@ -41,7 +41,6 @@ yarn add vant
|
||||
- 配置基于 TypeScript 的工程
|
||||
- 配置自定义主题色方案
|
||||
|
||||
|
||||
## 引入组件
|
||||
|
||||
### 方式一. 自动按需引入组件 (推荐)
|
||||
@ -115,21 +114,24 @@ Vue.use(Vant);
|
||||
|
||||
```html
|
||||
<!-- 引入样式文件 -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.4/lib/index.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/vant@2.6/lib/index.css"
|
||||
/>
|
||||
|
||||
<!-- 引入 Vue 和 Vant 的 JS 文件 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vant@2.4/lib/vant.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vant@2.6/lib/vant.min.js"></script>
|
||||
|
||||
<script>
|
||||
// 在 #app 标签下渲染一个按钮组件
|
||||
new Vue({
|
||||
el: '#app',
|
||||
template: `<van-button>按钮</van-button>`
|
||||
});
|
||||
// 在 #app 标签下渲染一个按钮组件
|
||||
new Vue({
|
||||
el: '#app',
|
||||
template: `<van-button>按钮</van-button>`,
|
||||
});
|
||||
|
||||
// 调用函数组件,弹出一个 Toast
|
||||
vant.Toast('提示');
|
||||
// 调用函数组件,弹出一个 Toast
|
||||
vant.Toast('提示');
|
||||
</script>
|
||||
```
|
||||
|
||||
@ -149,15 +151,15 @@ Vant 中的样式默认使用`px`作为单位,如果需要使用`rem`单位,
|
||||
```js
|
||||
module.exports = {
|
||||
plugins: {
|
||||
'autoprefixer': {
|
||||
browsers: ['Android >= 4.0', 'iOS >= 8']
|
||||
autoprefixer: {
|
||||
browsers: ['Android >= 4.0', 'iOS >= 8'],
|
||||
},
|
||||
'postcss-pxtorem': {
|
||||
rootValue: 37.5,
|
||||
propList: ['*']
|
||||
}
|
||||
}
|
||||
}
|
||||
propList: ['*'],
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
> 在配置 postcss-loader 时,应避免 ignore node_modules 目录,否则将导致 Vant 样式无法被编译
|
||||
@ -184,13 +186,16 @@ iPhone X 等机型底部存在底部指示条,指示条的操作区域与页
|
||||
|
||||
```html
|
||||
<!-- 在 head 标签中添加 meta 标签,并设置 viewport-fit=cover 值 -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
|
||||
/>
|
||||
|
||||
<!-- 开启 safe-area-inset-bottom 属性 -->
|
||||
<van-number-keyboard safe-area-inset-bottom />
|
||||
```
|
||||
|
||||
<img src="https://b.yzcdn.cn/vant/safearea.png" style="margin-top: 30px;">
|
||||
<img src="https://b.yzcdn.cn/vant/safearea.png">
|
||||
|
||||
### 组件实例方法
|
||||
|
||||
@ -207,12 +212,36 @@ Vant 中的许多组件提供了实例方法,调用实例方法时,我们需
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
checked: false
|
||||
checked: false,
|
||||
};
|
||||
},
|
||||
// 注意:组件挂载后才能访问到 ref 对象
|
||||
mounted() {
|
||||
this.$refs.checkbox.toggle();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 在 HTML 中无法正确渲染组件?
|
||||
|
||||
在 HTML 中使用 Vant 组件时,你可能会碰到部分示例代码无法正确渲染的情况,比如下面的用法:
|
||||
|
||||
```html
|
||||
<van-cell-group>
|
||||
<van-cell title="单元格" value="内容" />
|
||||
<van-cell title="单元格" value="内容" />
|
||||
</van-cell-group>
|
||||
```
|
||||
|
||||
这是因为 HTML 并不支持自闭合的自定义元素,也就是说 `<van-cell />` 这样的语法是不被识别的,使用完整的闭合标签可以避免这个问题:
|
||||
|
||||
```html
|
||||
<van-cell-group>
|
||||
<van-cell title="单元格" value="内容"></van-cell>
|
||||
<van-cell title="单元格" value="内容"></van-cell>
|
||||
</van-cell-group>
|
||||
```
|
||||
|
||||
在单文件组件、字符串模板和 JSX 中可以使用自闭合的自定义元素,因此不会出现这个问题。
|
||||
|
@ -12,18 +12,18 @@
|
||||
// bad
|
||||
export default {
|
||||
data: {
|
||||
foo: 'bar'
|
||||
}
|
||||
}
|
||||
foo: 'bar',
|
||||
},
|
||||
};
|
||||
|
||||
// good
|
||||
export default {
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
foo: 'bar'
|
||||
}
|
||||
}
|
||||
}
|
||||
foo: 'bar',
|
||||
};
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 单文件组件文件名称
|
||||
@ -78,16 +78,16 @@ components/
|
||||
// bad
|
||||
export default {
|
||||
props: {
|
||||
'greeting-text': String
|
||||
}
|
||||
'greeting-text': String,
|
||||
},
|
||||
};
|
||||
|
||||
// good
|
||||
export default {
|
||||
props: {
|
||||
greetingText: String
|
||||
}
|
||||
}
|
||||
greetingText: String,
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
```html
|
||||
@ -98,38 +98,16 @@ export default {
|
||||
<welcome-message greeting-text="hi" />
|
||||
```
|
||||
|
||||
### Props 换行
|
||||
|
||||
多个 Props 的元素应该分多行撰写,每个 Props 一行,闭合标签单起一行。
|
||||
|
||||
```html
|
||||
<!-- bad -->
|
||||
<my-component foo="a" bar="b" baz="c" />
|
||||
|
||||
<!-- good -->
|
||||
<my-component
|
||||
foo="a"
|
||||
bar="b"
|
||||
baz="c"
|
||||
/>
|
||||
```
|
||||
|
||||
### 指令缩写
|
||||
|
||||
指令缩写,用 `:` 表示 `v-bind:` ,用 `@` 表示 `v-on:`
|
||||
|
||||
```html
|
||||
<!-- bad -->
|
||||
<input
|
||||
v-bind:value="value"
|
||||
v-on:input="onInput"
|
||||
>
|
||||
<input v-bind:value="value" v-on:input="onInput" />
|
||||
|
||||
<!-- good -->
|
||||
<input
|
||||
:value="value"
|
||||
@input="onInput"
|
||||
>
|
||||
<input :value="value" @input="onInput" />
|
||||
```
|
||||
|
||||
### Props 顺序
|
||||
@ -175,7 +153,7 @@ export default {
|
||||
|
||||
destroyed() {},
|
||||
|
||||
methods: {}
|
||||
methods: {},
|
||||
};
|
||||
```
|
||||
|
||||
@ -192,7 +170,7 @@ export default {
|
||||
|
||||
styles() {
|
||||
// ...
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
@ -202,8 +180,8 @@ export default {
|
||||
|
||||
onChange() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@ -213,14 +191,14 @@ export default {
|
||||
|
||||
```html
|
||||
<template>
|
||||
...
|
||||
...
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* ... */
|
||||
/* ... */
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* ... */
|
||||
/* ... */
|
||||
</style>
|
||||
```
|
||||
|
@ -21,7 +21,6 @@ There are some basic variables below, all available variables could be found in
|
||||
|
||||
## 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.
|
||||
@ -39,11 +38,11 @@ module.exports = {
|
||||
libraryName: 'vant',
|
||||
libraryDirectory: 'es',
|
||||
// specify less file path
|
||||
style: name => `${name}/style/less`
|
||||
style: (name) => `${name}/style/less`,
|
||||
},
|
||||
'vant'
|
||||
]
|
||||
]
|
||||
'vant',
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
@ -78,11 +77,32 @@ module.exports = {
|
||||
'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: {
|
||||
modifyVars: {
|
||||
// overide with less vars
|
||||
'text-color': '#111',
|
||||
'border-color': '#eee',
|
||||
// or override with less file
|
||||
hack: `true; @import "your-less-file-path.less";`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
@ -42,11 +42,11 @@ module.exports = {
|
||||
libraryName: 'vant',
|
||||
libraryDirectory: 'es',
|
||||
// 指定样式路径
|
||||
style: name => `${name}/style/less`
|
||||
style: (name) => `${name}/style/less`,
|
||||
},
|
||||
'vant'
|
||||
]
|
||||
]
|
||||
'vant',
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
@ -78,14 +78,35 @@ module.exports = {
|
||||
modifyVars: {
|
||||
// 直接覆盖变量
|
||||
'text-color': '#111',
|
||||
'border-color': '#eee'
|
||||
'border-color': '#eee',
|
||||
// 或者可以通过 less 文件覆盖(文件路径为绝对路径)
|
||||
'hack': `true; @import "your-less-file-path.less";`
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
hack: `true; @import "your-less-file-path.less";`,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
如果 vue-cli 搭建的项目,可以在 `vue.config.js` 中进行配置。
|
||||
|
||||
```js
|
||||
// vue.config.js
|
||||
module.exports = {
|
||||
css: {
|
||||
loaderOptions: {
|
||||
less: {
|
||||
modifyVars: {
|
||||
// 直接覆盖变量
|
||||
'text-color': '#111',
|
||||
'border-color': '#eee',
|
||||
// 或者可以通过 less 文件覆盖(文件路径为绝对路径)
|
||||
hack: `true; @import "your-less-file-path.less";`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
@ -21,7 +21,7 @@ let demoUid = 0;
|
||||
// helper for demo locales
|
||||
Vue.mixin({
|
||||
computed: {
|
||||
$t() {
|
||||
t() {
|
||||
const { name } = this.$options;
|
||||
const { lang = 'zh-CN' } = (this.$route && this.$route.meta) || {};
|
||||
const prefix = name ? camelize(name) + '.' : '';
|
||||
@ -49,7 +49,7 @@ Vue.mixin({
|
||||
const locales = {};
|
||||
const camelizedName = camelize(name);
|
||||
|
||||
Object.keys(i18n).forEach(key => {
|
||||
Object.keys(i18n).forEach((key) => {
|
||||
locales[key] = { [camelizedName]: i18n[key] };
|
||||
});
|
||||
|
||||
@ -60,7 +60,7 @@ Vue.mixin({
|
||||
|
||||
// switch lang after routing
|
||||
if (window.vueRouter) {
|
||||
window.vueRouter.afterEach(to => {
|
||||
window.vueRouter.afterEach((to) => {
|
||||
const { lang } = to.meta || {};
|
||||
|
||||
if (lang) {
|
||||
|
16
package.json
16
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vant",
|
||||
"version": "2.5.3",
|
||||
"version": "2.6.2",
|
||||
"description": "Mobile UI Components built on Vue",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -15,7 +15,7 @@
|
||||
"scripts": {
|
||||
"bootstrap": "yarn || npm i",
|
||||
"dev": "vant-cli dev",
|
||||
"lint": "vant-cli lint",
|
||||
"lint": "vant-cli lint && ls-lint",
|
||||
"test": "vant-cli test",
|
||||
"build": "vant-cli build",
|
||||
"release": "vant-cli release",
|
||||
@ -25,11 +25,14 @@
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged",
|
||||
"pre-commit": "lint-staged && ls-lint",
|
||||
"commit-msg": "vant-cli commit-lint"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.md": [
|
||||
"prettier --write"
|
||||
],
|
||||
"*.{ts,tsx,js,vue,less}": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
@ -63,7 +66,9 @@
|
||||
"vue": ">= 2.5.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vant/cli": "^2.2.4",
|
||||
"@ls-lint/ls-lint": "^1.8.0",
|
||||
"@vant/cli": "^2.4.0",
|
||||
"prettier": "^2.0.4",
|
||||
"vue": "^2.6.11",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
},
|
||||
@ -77,6 +82,7 @@
|
||||
"tags": "vetur/tags.json",
|
||||
"attributes": "vetur/attributes.json"
|
||||
},
|
||||
"web-types": "vetur/web-types.json",
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"extends": [
|
||||
@ -90,7 +96,7 @@
|
||||
},
|
||||
"prettier": {
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5"
|
||||
"proseWrap": "never"
|
||||
},
|
||||
"browserslist": [
|
||||
"Android >= 4.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-vant-cli-app",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"description": "Create Vant Cli App",
|
||||
"main": "lib/index.js",
|
||||
"bin": {
|
||||
@ -24,17 +24,19 @@
|
||||
"author": "chenjiahan",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^8.0.1",
|
||||
"@types/fs-extra": "^8.1.0",
|
||||
"@types/yeoman-environment": "^2.3.3",
|
||||
"@types/yeoman-generator": "^3.1.4",
|
||||
"release-it": "^12.4.3",
|
||||
"typescript": "^3.7.4"
|
||||
"release-it": "^13.0.0",
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^3.0.0",
|
||||
"consola": "^2.11.3",
|
||||
"fs-extra": "^8.1.0",
|
||||
"inquirer": "^7.0.3",
|
||||
"yeoman-generator": "^4.4.0"
|
||||
"inquirer": "^7.0.6",
|
||||
"yeoman-environment": "^2.8.0",
|
||||
"yeoman-generator": "^4.6.0"
|
||||
},
|
||||
"release-it": {
|
||||
"git": {
|
||||
|
@ -2,6 +2,7 @@ import chalk from 'chalk';
|
||||
import consola from 'consola';
|
||||
import { join } from 'path';
|
||||
import { CWD, GENERATOR_DIR } from './constant';
|
||||
import Yeoman from 'yeoman-environment';
|
||||
import Generator from 'yeoman-generator';
|
||||
|
||||
const TEMPLATES = join(GENERATOR_DIR, 'templates');
|
||||
@ -23,9 +24,9 @@ export class VanGenerator extends Generator {
|
||||
|
||||
constructor(name: string) {
|
||||
super([], {
|
||||
env: {
|
||||
env: Yeoman.createEnv([], {
|
||||
cwd: join(CWD, name),
|
||||
},
|
||||
}),
|
||||
resolved: GENERATOR_DIR,
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import inquirer from 'inquirer';
|
||||
import consola from 'consola';
|
||||
import { ensureDir } from 'fs-extra';
|
||||
import { VanGenerator } from './generator';
|
||||
|
||||
@ -15,10 +16,14 @@ const PROMPTS = [
|
||||
export default async function run() {
|
||||
const { name } = await inquirer.prompt(PROMPTS);
|
||||
|
||||
ensureDir(name);
|
||||
try {
|
||||
await ensureDir(name);
|
||||
|
||||
const generator = new VanGenerator(name);
|
||||
generator.run();
|
||||
const generator = new VanGenerator(name);
|
||||
generator.run();
|
||||
} catch (e) {
|
||||
consola.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -45,14 +45,8 @@ yarn add @vant/cli --dev
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx,js,jsx,vue}": [
|
||||
"eslint",
|
||||
"git add"
|
||||
],
|
||||
"*.{vue,css,less,scss}": [
|
||||
"stylelint",
|
||||
"git add"
|
||||
]
|
||||
"*.{ts,tsx,js,jsx,vue}": ["eslint", "git add"],
|
||||
"*.{vue,css,less,scss}": ["stylelint", "git add"]
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
@ -68,36 +62,19 @@ yarn add @vant/cli --dev
|
||||
}
|
||||
```
|
||||
|
||||
## 命令
|
||||
## 详细文档
|
||||
|
||||
### dev
|
||||
- [命令](https://github.com/youzan/vant/tree/dev/packages/vant-cli/docs/commands.md)
|
||||
- [配置指南](https://github.com/youzan/vant/tree/dev/packages/vant-cli/docs/config.md)
|
||||
- [目录结构](https://github.com/youzan/vant/tree/dev/packages/vant-cli/docs/directory.md)
|
||||
- [更新日志](https://github.com/youzan/vant/tree/dev/packages/vant-cli/changelog.md)
|
||||
|
||||
本地开发,dev 命令会启动一个本地服务器,用于在开发过程中对文档和示例进行预览
|
||||
## 微信讨论群
|
||||
|
||||
### build
|
||||
扫码加入 Vant Cli 交流群,若群二维码过期,可以联系有赞前端小秘书加群
|
||||
|
||||
构建组件库,在`es`和`lib`目录生成可用于生产环境的组件代码
|
||||
<img src="https://img.yzcdn.cn/vant/wechat_20200413.jpg" width="220" height="285" >
|
||||
|
||||
### build-site
|
||||
## 关于桌面端组件
|
||||
|
||||
构建文档站点,在`site`目录生成可用于生产环境的文档站点代码
|
||||
|
||||
### release
|
||||
|
||||
发布组件库,发布前会自动执行 build 和 changelog 命令
|
||||
|
||||
### changelog
|
||||
|
||||
基于 commit 记录生成更新日志
|
||||
|
||||
### commit-lint
|
||||
|
||||
校验 commit message 的格式是否符合规范,需要配合`husky`在提交 commit 时触发
|
||||
|
||||
## 配置
|
||||
|
||||
参见[配置指南](https://github.com/youzan/vant/tree/dev/packages/vant-cli/docs/config.md)。
|
||||
|
||||
## 更新日志
|
||||
|
||||
参见[更新日志](https://github.com/youzan/vant/tree/dev/packages/vant-cli/changelog.md)。
|
||||
目前 Vant Cli 仅支持移动端组件的预览,桌面端组件暂不支持预览(欢迎 PR)。
|
||||
|
@ -1,37 +1,87 @@
|
||||
# 更新日志
|
||||
|
||||
### [v2.4.0]
|
||||
|
||||
`2020-04-02`
|
||||
|
||||
- 升级 prettier v2
|
||||
- 升级 html-webpack-plugin v4
|
||||
|
||||
### [v2.3.1]
|
||||
|
||||
`2020-03-29`
|
||||
|
||||
- 优化网站导航栏在大屏上的适配 ([#5928](https://github.com/youzan/vant/pull/5928))
|
||||
|
||||
### [v2.3.0]
|
||||
|
||||
`2020-03-25`
|
||||
|
||||
- build 命令支持编译 scoped 样式 ([#5910](https://github.com/youzan/vant/pull/5910))
|
||||
- build 命令支持生成 WebStorm 组件定义文件 ([#5899](https://github.com/youzan/vant/issues/5899))
|
||||
- clean 命令现在会移除而不是清空文件夹 ([#5895](https://github.com/youzan/vant/issues/5895))
|
||||
- 升级 @vant/markdown-vetur 2.0.0
|
||||
|
||||
### [v2.2.8]
|
||||
|
||||
`2020-03-20`
|
||||
|
||||
- 修复构建 changelog 可能失败的问题
|
||||
|
||||
### [v2.2.7]
|
||||
|
||||
`2020-03-19`
|
||||
|
||||
- 新增 process.env.VANT_CLI_VERSION 环境变量
|
||||
|
||||
### [v2.2.6]
|
||||
|
||||
`2020-03-18`
|
||||
|
||||
- 升级 commander 5
|
||||
- 修复右侧预览 iframe 链接可能错误的问题
|
||||
|
||||
### [v2.2.5]
|
||||
|
||||
`2020-03-08`
|
||||
|
||||
- 升级依赖
|
||||
- 优化代码块与底部文字之间的间距
|
||||
- 修复 create-vant-cli-app 初始化时报错的问题
|
||||
|
||||
### [v2.2.4]
|
||||
|
||||
`2020-02-14`
|
||||
|
||||
- 修复在 windows 上构建出的样式入口文件路径错误的问题 ([#5655](https://github.com/youzan/vant/pull/5655)
|
||||
|
||||
|
||||
### [v2.2.3]
|
||||
|
||||
`2020-02-13`
|
||||
|
||||
- 链接颜色调整为蓝色
|
||||
|
||||
|
||||
### [v2.2.2]
|
||||
|
||||
`2020-02-05`
|
||||
|
||||
- 修复在 windows 上获取 markdown 路径错误的问题 ([#5626](https://github.com/youzan/vant/pull/5626))
|
||||
|
||||
|
||||
### [v2.2.1]
|
||||
|
||||
`2020-02-04`
|
||||
|
||||
- 升级 babel@7.8
|
||||
- 修复切换版本时跳转 undefined 的问题 ([#5620](https://github.com/youzan/vant/pull/5620))
|
||||
|
||||
|
||||
### [v2.2.0]
|
||||
|
||||
`2020-01-19`
|
||||
|
||||
- 升级 @vant/eslint-config@2.0.0
|
||||
|
||||
|
||||
### [v2.1.8]
|
||||
|
||||
`2020-01-18`
|
||||
|
||||
- 新增 create-vant-cli-app 初始化命令
|
||||
@ -39,15 +89,15 @@
|
||||
- 优化站点导航栏颜色
|
||||
- 优化站点代码块颜色
|
||||
|
||||
|
||||
### [v2.1.7]
|
||||
|
||||
`2020-01-15`
|
||||
|
||||
- 优化 help 命令
|
||||
- 优化 help 命令
|
||||
- 优化控制台输出信息
|
||||
|
||||
|
||||
### [v2.1.6]
|
||||
|
||||
`2020-01-12`
|
||||
|
||||
- 支持自定义 Postcss 配置
|
||||
@ -55,23 +105,23 @@
|
||||
- 优化文档站点的 meta 字段
|
||||
- 新增 API 文档中的版本标签样式
|
||||
|
||||
|
||||
### [v2.1.5]
|
||||
|
||||
`2020-01-10`
|
||||
|
||||
- 修复编译时未替换 import 语句中的 CSS 后缀的问题
|
||||
- 升级 husky 版本到 4.0
|
||||
|
||||
|
||||
### [v2.1.4]
|
||||
|
||||
`2020-01-06`
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- 锁死 @vue/test-utils 版本为 1.0.0-beta.29
|
||||
|
||||
|
||||
### [v2.1.3]
|
||||
|
||||
`2020-01-06`
|
||||
|
||||
**Feature**
|
||||
@ -79,8 +129,8 @@
|
||||
- 增加 cache-loader,提高构建速度
|
||||
- 调整 jest setup 文件执行时机,延迟至 env 初始化后执行
|
||||
|
||||
|
||||
### [v2.1.2]
|
||||
|
||||
`2020-01-05`
|
||||
|
||||
**Feature**
|
||||
|
61
packages/vant-cli/docs/commands.md
Normal file
61
packages/vant-cli/docs/commands.md
Normal file
@ -0,0 +1,61 @@
|
||||
# 命令
|
||||
|
||||
Vant Cli 中内置了一系列的命令,可以将命令添加到 npm scripts 中进行使用。
|
||||
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
"scripts": {
|
||||
"dev": "vant-cli dev",
|
||||
"test": "vant-cli test",
|
||||
"lint": "vant-cli lint",
|
||||
"release": "vant-cli release",
|
||||
"build-site": "vant-cli build-site"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
也可以通过 npm 自带的 [npx](https://github.com/npm/npx) 直接执行某个命令:
|
||||
|
||||
```bash
|
||||
npx vant-cli dev
|
||||
```
|
||||
|
||||
### dev
|
||||
|
||||
运行本地开发环境。
|
||||
|
||||
运行 dev 命令时,Vant Cli 会通过 [webpack-dev-server](https://github.com/webpack/webpack-dev-server) 启动一个本地服务器,用于在开发过程中对文档和示例进行预览。
|
||||
|
||||
### build
|
||||
|
||||
构建组件库。
|
||||
|
||||
运行 build 命令会在 `es` 和 `lib` 目录下生成可用于生产环境的组件代码,详见 [目录结构](https://github.com/youzan/vant/tree/dev/packages/vant-cli/docs/directory.md)。
|
||||
|
||||
发布 npm 时,请将以下配置加入到 `package.json` 中,使 npm 包能被正确识别:
|
||||
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
"files": ["es", "lib"]
|
||||
}
|
||||
```
|
||||
|
||||
### build-site
|
||||
|
||||
构建文档站点,在 `site` 目录生成可用于生产环境的文档站点代码。
|
||||
|
||||
### release
|
||||
|
||||
发布组件库,发布前会自动执行 build 和 changelog 命令,并通过 [release-it](https://github.com/release-it/release-it) 发布 npm 包。
|
||||
|
||||
## changelog
|
||||
|
||||
基于 commit 记录生成更新日志,基于 [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) 实现。
|
||||
|
||||
## commit-lint
|
||||
|
||||
校验 commit message 的格式是否符合规范,需要配合 `husky` 在提交 commit 时触发。
|
81
packages/vant-cli/docs/directory.md
Normal file
81
packages/vant-cli/docs/directory.md
Normal file
@ -0,0 +1,81 @@
|
||||
# 目录结构
|
||||
|
||||
## 源代码目录
|
||||
|
||||
基于 Vant Cli 搭建的组件库的基本目录结构如下所示:
|
||||
|
||||
```
|
||||
project
|
||||
├─ src # 组件源代码
|
||||
│ ├─ button # button 组件源代码
|
||||
│ └─ dialog # dialog 组件源代码
|
||||
│
|
||||
├─ docs # 静态文档目录
|
||||
│ ├─ home.md # 文档首页
|
||||
│ └─ changelog.md # 更新日志
|
||||
│
|
||||
├─ babel.config.js # Babel 配置文件
|
||||
├─ vant.config.js # Vant Cli 配置文件
|
||||
├─ pacakge.json
|
||||
└─ README.md
|
||||
```
|
||||
|
||||
单个组件的目录如下:
|
||||
|
||||
```
|
||||
button
|
||||
├─ demo # 示例目录
|
||||
│ └─ index.vue # 组件示例
|
||||
├─ index.vue # 组件源码
|
||||
└─ README.md # 组件文档
|
||||
```
|
||||
|
||||
使用 .vue 文件编写组件时,编译后会生成对应的 JS 和 CSS 文件,且 JS 文件中会自动引入 CSS 文件。
|
||||
|
||||
如果需要将 JS 和 CSS 解耦,实现主题定制等功能,在编写代码时就要使用独立的 JS 和 CSS 文件,如下所示:
|
||||
|
||||
```
|
||||
button
|
||||
├─ demo # 组件示例
|
||||
│ └─ index.vue # 组件示例入口
|
||||
├─ index.js # 组件入口
|
||||
├─ index.less # 组件样式,可以为 less 或 scss
|
||||
└─ README.md # 组件文档
|
||||
```
|
||||
|
||||
采用这种目录结构时,组件的使用者需要分别引入 JS 和 CSS 文件,也可以通过 babel-plugin-import 自动引入样式。
|
||||
|
||||
通过引入样式源文件(less 或 scss)并修改样式变量,可以实现主题定制功能。
|
||||
|
||||
## 构建结果目录
|
||||
|
||||
运行 build 命令会在 `es` 和 `lib` 目录下生成可用于生产环境的组件代码,结构如下:
|
||||
|
||||
```
|
||||
project
|
||||
├─ es # es 目录下的代码遵循 esmodule 规范
|
||||
│ ├─ button # button 组件编译后的代码目录
|
||||
│ ├─ dialog # dialog 组件编译后的代码目录
|
||||
│ └─ index.js # 引入所有组件的入口,支持 tree shaking
|
||||
│
|
||||
└─ lib # lib 目录下的代码遵循 commonjs 规范
|
||||
├─ button # button 组件编译后的代码目录
|
||||
├─ dialog # dialog 组件编译后的代码目录
|
||||
├─ index.js # 引入所有组件的入口
|
||||
├─ index.less # 所有组件未编译的样式
|
||||
├─ index.css # 所有组件打包后的样式,用于 CDN 引入
|
||||
├─ name.js # 所有组件打包后的脚本,未压缩,用于 CDN 引入
|
||||
└─ name.min.js # 所有组件打包后的脚本,已压缩,用于 CDN 引入
|
||||
```
|
||||
|
||||
单个组件编译后的目录如下:
|
||||
|
||||
```
|
||||
button
|
||||
├─ index.js # 组件编译后的 JS 文件
|
||||
├─ index.css # 组件编译后的 CSS 文件
|
||||
├─ index.less # 组件编译前的 CSS 文件,可以为 less 或 scss
|
||||
└─ style # 按需引入样式的入口
|
||||
├─ index.js # 按需引入编译后的样式
|
||||
└─ less.js # 按需引入未编译的样式,可用于主题定制
|
||||
```
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vant/cli",
|
||||
"version": "2.2.4",
|
||||
"version": "2.4.0",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"typings": "lib/index.d.ts",
|
||||
@ -34,73 +34,71 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^8.1.0",
|
||||
"@types/html-webpack-plugin": "^3.2.2",
|
||||
"@types/lodash": "^4.14.149",
|
||||
"@types/postcss-load-config": "^2.0.1",
|
||||
"@types/sass": "^1.16.0",
|
||||
"@types/shelljs": "^0.8.6",
|
||||
"@types/webpack": "^4.41.6",
|
||||
"@types/webpack-dev-server": "^3.10.0",
|
||||
"@types/webpack": "^4.41.10",
|
||||
"@types/webpack-dev-server": "^3.10.1",
|
||||
"@types/webpack-merge": "^4.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.8.4",
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/plugin-syntax-jsx": "^7.8.3",
|
||||
"@babel/plugin-transform-object-assign": "^7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.8.3",
|
||||
"@babel/preset-env": "^7.8.4",
|
||||
"@babel/preset-typescript": "^7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.9.0",
|
||||
"@babel/preset-env": "^7.9.5",
|
||||
"@babel/preset-typescript": "^7.9.0",
|
||||
"@nuxt/friendly-errors-webpack-plugin": "^2.5.0",
|
||||
"@types/jest": "^25.1.3",
|
||||
"@types/jest": "^25.2.1",
|
||||
"@vant/eslint-config": "^2.0.0",
|
||||
"@vant/markdown-loader": "^2.3.0",
|
||||
"@vant/markdown-vetur": "^1.1.0",
|
||||
"@vant/stylelint-config": "^1.1.0",
|
||||
"@vant/markdown-vetur": "^2.0.1",
|
||||
"@vant/stylelint-config": "^1.3.0",
|
||||
"@vant/touch-emulator": "^1.2.0",
|
||||
"@vue/babel-preset-jsx": "^1.1.2",
|
||||
"@vue/component-compiler-utils": "^3.1.1",
|
||||
"@vue/component-compiler-utils": "^3.1.2",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"address": "^1.1.2",
|
||||
"autoprefixer": "^9.7.4",
|
||||
"babel-jest": "^25.1.0",
|
||||
"babel-loader": "^8.0.6",
|
||||
"autoprefixer": "^9.7.6",
|
||||
"babel-jest": "^25.3.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-plugin-import": "^1.13.0",
|
||||
"cache-loader": "^4.1.0",
|
||||
"chokidar": "^3.3.1",
|
||||
"clean-css": "^4.2.3",
|
||||
"codecov": "^3.6.5",
|
||||
"commander": "^4.1.1",
|
||||
"commander": "^5.0.0",
|
||||
"consola": "^2.11.3",
|
||||
"conventional-changelog": "^3.1.18",
|
||||
"cross-env": "^7.0.0",
|
||||
"css-loader": "^3.4.2",
|
||||
"cross-env": "^7.0.2",
|
||||
"css-loader": "^3.5.2",
|
||||
"eslint": "^6.8.0",
|
||||
"fast-glob": "^3.2.1",
|
||||
"gh-pages": "2.0.1",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"husky": "^4.2.3",
|
||||
"jest": "^25.1.0",
|
||||
"fast-glob": "^3.2.2",
|
||||
"gh-pages": "^2.2.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"html-webpack-plugin": "4.2.0",
|
||||
"husky": "^4.2.5",
|
||||
"jest": "^25.3.0",
|
||||
"jest-canvas-mock": "^2.2.0",
|
||||
"jest-serializer-vue": "^2.0.2",
|
||||
"less": "^3.11.1",
|
||||
"less-loader": "^5.0.0",
|
||||
"lint-staged": "^10.0.7",
|
||||
"lint-staged": "^10.1.3",
|
||||
"lodash": "^4.17.15",
|
||||
"ora": "^4.0.3",
|
||||
"portfinder": "^1.0.25",
|
||||
"postcss": "^7.0.27",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"release-it": "^12.6.0",
|
||||
"sass": "^1.25.0",
|
||||
"prettier": "^2.0.4",
|
||||
"release-it": "^13.5.2",
|
||||
"sass": "^1.26.3",
|
||||
"sass-loader": "^8.0.2",
|
||||
"shelljs": "^0.8.3",
|
||||
"style-loader": "^1.1.3",
|
||||
"stylelint": "^13.2.0",
|
||||
"typescript": "^3.8.2",
|
||||
"stylelint": "^13.3.1",
|
||||
"typescript": "^3.8.3",
|
||||
"vue-jest": "4.0.0-beta.2",
|
||||
"vue-loader": "^15.9.0",
|
||||
"vue-router": "^3.1.5",
|
||||
"webpack": "^4.41.6",
|
||||
"vue-loader": "^15.9.1",
|
||||
"vue-router": "^3.1.6",
|
||||
"webpack": "^4.42.1",
|
||||
"webpack-dev-server": "3.10.3",
|
||||
"webpack-merge": "^4.2.2",
|
||||
"webpackbar": "^4.0.0"
|
||||
|
@ -3,7 +3,6 @@
|
||||
code {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin-top: 20px;
|
||||
overflow-x: auto;
|
||||
color: @van-doc-code-color;
|
||||
font-weight: 400;
|
||||
@ -16,7 +15,11 @@ code {
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
margin: 20px 0 0;
|
||||
|
||||
+ p {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.hljs {
|
||||
|
@ -23,7 +23,7 @@ export default {
|
||||
},
|
||||
|
||||
data() {
|
||||
const path = location.pathname.replace('/index', '/');
|
||||
const path = location.pathname.replace(/\/index(\.html)?/, '/');
|
||||
|
||||
return {
|
||||
packageVersion,
|
||||
|
@ -140,6 +140,7 @@ export default {
|
||||
|
||||
.van-doc-header {
|
||||
width: 100%;
|
||||
background-color: #001938;
|
||||
user-select: none;
|
||||
|
||||
&__top {
|
||||
@ -148,7 +149,6 @@ export default {
|
||||
height: @van-doc-header-top-height;
|
||||
padding: 0 @van-doc-padding;
|
||||
line-height: @van-doc-header-top-height;
|
||||
background-color: #001938;
|
||||
|
||||
&-nav {
|
||||
flex: 1;
|
||||
|
@ -51,7 +51,7 @@ export default {
|
||||
},
|
||||
|
||||
watch: {
|
||||
// eslint-disable-next-line
|
||||
// eslint-disable-next-line object-shorthand
|
||||
'$route.path'() {
|
||||
this.setNav();
|
||||
},
|
||||
@ -88,7 +88,7 @@ export default {
|
||||
},
|
||||
|
||||
keyboardHandler() {
|
||||
window.addEventListener('keyup', event => {
|
||||
window.addEventListener('keyup', (event) => {
|
||||
switch (event.keyCode) {
|
||||
case 37: // left
|
||||
this.keyboardNav('prev');
|
||||
|
@ -26,7 +26,11 @@ export default {
|
||||
|
||||
methods: {
|
||||
onBack() {
|
||||
history.back();
|
||||
if (history.length > 1) {
|
||||
history.back();
|
||||
} else {
|
||||
this.$router.replace('/');
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -2,7 +2,6 @@ import { join } from 'path';
|
||||
import { ROOT } from '../common/constant';
|
||||
import { ora, slimPath } from '../common/logger';
|
||||
import { createWriteStream, readFileSync } from 'fs-extra';
|
||||
// @ts-ignore
|
||||
import conventionalChangelog from 'conventional-changelog';
|
||||
|
||||
const DIST_FILE = join(ROOT, './changelog.generated.md');
|
||||
@ -38,7 +37,7 @@ function transform(item: any) {
|
||||
|
||||
if (item.references.length) {
|
||||
item.references.forEach((ref: any) => {
|
||||
if (ref.issue) {
|
||||
if (ref.issue && item.subject) {
|
||||
item.subject = item.subject.replace(` (#${ref.issue})`, '');
|
||||
}
|
||||
});
|
||||
|
@ -1,11 +1,18 @@
|
||||
import { emptyDir } from 'fs-extra';
|
||||
import { ES_DIR, LIB_DIR, DIST_DIR, SITE_DIST_DIR } from '../common/constant';
|
||||
import { remove } from 'fs-extra';
|
||||
import {
|
||||
ES_DIR,
|
||||
LIB_DIR,
|
||||
DIST_DIR,
|
||||
VETUR_DIR,
|
||||
SITE_DIST_DIR,
|
||||
} from '../common/constant';
|
||||
|
||||
export async function clean() {
|
||||
await Promise.all([
|
||||
emptyDir(ES_DIR),
|
||||
emptyDir(LIB_DIR),
|
||||
emptyDir(DIST_DIR),
|
||||
emptyDir(SITE_DIST_DIR),
|
||||
remove(ES_DIR),
|
||||
remove(LIB_DIR),
|
||||
remove(DIST_DIR),
|
||||
remove(VETUR_DIR),
|
||||
remove(SITE_DIST_DIR),
|
||||
]);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
// @ts-ignore
|
||||
import execa from 'execa';
|
||||
import { ora } from '../common/logger';
|
||||
import { SCRIPT_EXTS } from '../common/constant';
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
// @ts-ignore
|
||||
import releaseIt from 'release-it';
|
||||
import { join } from 'path';
|
||||
|
||||
|
@ -23,6 +23,7 @@ export const ROOT = findRootDir(CWD);
|
||||
export const ES_DIR = join(ROOT, 'es');
|
||||
export const LIB_DIR = join(ROOT, 'lib');
|
||||
export const DOCS_DIR = join(ROOT, 'docs');
|
||||
export const VETUR_DIR = join(ROOT, 'vetur');
|
||||
export const SITE_DIST_DIR = join(ROOT, 'site');
|
||||
export const VANT_CONFIG_FILE = join(ROOT, 'vant.config.js');
|
||||
export const PACKAGE_JSON_FILE = join(ROOT, 'package.json');
|
||||
|
@ -1,4 +1,3 @@
|
||||
// @ts-ignore
|
||||
import execa from 'execa';
|
||||
import { consola } from './logger';
|
||||
import { execSync } from 'child_process';
|
||||
|
@ -1,4 +1,3 @@
|
||||
// @ts-ignore
|
||||
import { render, FileManager } from 'less';
|
||||
import { readFileSync } from 'fs-extra';
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as compiler from 'vue-template-compiler';
|
||||
import * as compileUtils from '@vue/component-compiler-utils';
|
||||
import hash from 'hash-sum';
|
||||
import { parse } from 'path';
|
||||
import { remove, writeFileSync, readFileSync } from 'fs-extra';
|
||||
import { replaceExt } from '../common';
|
||||
@ -34,6 +35,10 @@ function injectRender(script: string, render: string) {
|
||||
);
|
||||
}
|
||||
|
||||
function injectScopeId(script: string, scopeId: string) {
|
||||
return script.replace(EXPORT, `${EXPORT}\n _scopeId: '${scopeId}',\n\n`);
|
||||
}
|
||||
|
||||
function injectStyle(
|
||||
script: string,
|
||||
styles: compileUtils.SFCBlock[],
|
||||
@ -63,10 +68,6 @@ function compileTemplate(template: string) {
|
||||
return result.code;
|
||||
}
|
||||
|
||||
type CompileSfcOptions = {
|
||||
skipStyle?: boolean;
|
||||
};
|
||||
|
||||
export function parseSfc(filePath: string) {
|
||||
const source = readFileSync(filePath, 'utf-8');
|
||||
|
||||
@ -79,15 +80,16 @@ export function parseSfc(filePath: string) {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
export async function compileSfc(
|
||||
filePath: string,
|
||||
options: CompileSfcOptions = {}
|
||||
): Promise<any> {
|
||||
export async function compileSfc(filePath: string): Promise<any> {
|
||||
const tasks = [remove(filePath)];
|
||||
const source = readFileSync(filePath, 'utf-8');
|
||||
const jsFilePath = replaceExt(filePath, '.js');
|
||||
const descriptor = parseSfc(filePath);
|
||||
const { template, styles } = descriptor;
|
||||
|
||||
const hasScoped = styles.some(s => s.scoped);
|
||||
const scopeId = hasScoped ? `data-v-${hash(source)}` : '';
|
||||
|
||||
// compile js part
|
||||
if (descriptor.script) {
|
||||
tasks.push(
|
||||
@ -100,6 +102,10 @@ export async function compileSfc(
|
||||
script = injectRender(script, render);
|
||||
}
|
||||
|
||||
if (scopeId) {
|
||||
script = injectScopeId(script, scopeId);
|
||||
}
|
||||
|
||||
writeFileSync(jsFilePath, script);
|
||||
compileJs(jsFilePath)
|
||||
.then(resolve)
|
||||
@ -109,21 +115,27 @@ export async function compileSfc(
|
||||
}
|
||||
|
||||
// compile style part
|
||||
if (!options.skipStyle) {
|
||||
tasks.push(
|
||||
...styles.map((style, index: number) => {
|
||||
const cssFilePath = getSfcStylePath(
|
||||
filePath,
|
||||
style.lang || 'css',
|
||||
index
|
||||
);
|
||||
tasks.push(
|
||||
...styles.map((style, index: number) => {
|
||||
const cssFilePath = getSfcStylePath(filePath, style.lang || 'css', index);
|
||||
|
||||
writeFileSync(cssFilePath, trim(style.content));
|
||||
let styleSource = trim(style.content);
|
||||
|
||||
return compileStyle(cssFilePath);
|
||||
})
|
||||
);
|
||||
}
|
||||
if (style.scoped) {
|
||||
styleSource = compileUtils.compileStyle({
|
||||
id: scopeId,
|
||||
scoped: true,
|
||||
source: styleSource,
|
||||
filename: cssFilePath,
|
||||
preprocessLang: style.lang,
|
||||
}).code;
|
||||
}
|
||||
|
||||
writeFileSync(cssFilePath, styleSource);
|
||||
|
||||
return compileStyle(cssFilePath);
|
||||
})
|
||||
);
|
||||
|
||||
return Promise.all(tasks);
|
||||
}
|
||||
|
@ -1,19 +1,25 @@
|
||||
// @ts-ignore
|
||||
import markdownVetur from '@vant/markdown-vetur';
|
||||
import { join } from 'path';
|
||||
import { get } from 'lodash';
|
||||
import { SRC_DIR, getVantConfig, ROOT } from '../common/constant';
|
||||
import {
|
||||
SRC_DIR,
|
||||
VETUR_DIR,
|
||||
getVantConfig,
|
||||
getPackageJson,
|
||||
} from '../common/constant';
|
||||
|
||||
// generate vetur tags & attributes
|
||||
export function genVeturConfig() {
|
||||
const vantCongig = getVantConfig();
|
||||
const options = get(vantCongig, 'build.vetur');
|
||||
const pkgJson = getPackageJson();
|
||||
const vantConfig = getVantConfig();
|
||||
const options = get(vantConfig, 'build.vetur');
|
||||
|
||||
if (options) {
|
||||
markdownVetur.parseAndWrite({
|
||||
name: vantConfig.name,
|
||||
path: SRC_DIR,
|
||||
test: /zh-CN\.md/,
|
||||
outputDir: join(ROOT, 'vetur'),
|
||||
version: pkgJson.version,
|
||||
outputDir: VETUR_DIR,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
// @ts-ignore
|
||||
import releaseIt from 'release-it';
|
||||
import { build } from '../commands/build';
|
||||
import { changelog } from '../commands/changelog';
|
||||
|
@ -1,6 +1,5 @@
|
||||
// @ts-ignore
|
||||
import FriendlyErrorsPlugin from '@nuxt/friendly-errors-webpack-plugin';
|
||||
import sass from 'sass';
|
||||
import FriendlyErrorsPlugin from '@nuxt/friendly-errors-webpack-plugin';
|
||||
import { VueLoaderPlugin } from 'vue-loader';
|
||||
import {
|
||||
CACHE_DIR,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import merge from 'webpack-merge';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
// @ts-ignore
|
||||
import WebpackBar from 'webpackbar';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
import { get } from 'lodash';
|
||||
import { join } from 'path';
|
||||
import { baseConfig } from './webpack.base';
|
||||
|
@ -14,6 +14,10 @@ export function getSitePrdConfig() {
|
||||
{
|
||||
mode: 'production',
|
||||
stats: 'none',
|
||||
performance: {
|
||||
maxAssetSize: 5 * 1024 * 1024,
|
||||
maxEntrypointSize: 5 * 1024 * 1024,
|
||||
},
|
||||
output: {
|
||||
publicPath,
|
||||
path: outputDir,
|
||||
|
@ -17,6 +17,8 @@ import { commitLint } from './commands/commit-lint';
|
||||
|
||||
version(`@vant/cli ${packageJson.version}`);
|
||||
|
||||
process.env.VANT_CLI_VERSION = packageJson.version;
|
||||
|
||||
command('dev')
|
||||
.description('Run webpack dev server')
|
||||
.action(dev);
|
||||
@ -62,4 +64,4 @@ command('commit-lint')
|
||||
.description('Lint commit message')
|
||||
.action(commitLint);
|
||||
|
||||
parse(process.argv);
|
||||
parse();
|
||||
|
12
packages/vant-cli/src/module.d.ts
vendored
Normal file
12
packages/vant-cli/src/module.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// some modules with missing type definitions
|
||||
declare module 'less';
|
||||
declare module 'sass';
|
||||
declare module 'execa';
|
||||
declare module 'hash-sum';
|
||||
declare module 'clean-css';
|
||||
declare module 'webpackbar';
|
||||
declare module 'release-it';
|
||||
declare module 'html-webpack-plugin';
|
||||
declare module 'conventional-changelog';
|
||||
declare module '@vant/markdown-vetur';
|
||||
declare module '@nuxt/friendly-errors-webpack-plugin';
|
@ -1,4 +1,4 @@
|
||||
*{{#if scope}} {{scope}}:
|
||||
-{{#if scope}} {{scope}}:
|
||||
{{~/if}} {{#if subject}}
|
||||
{{~subject}}
|
||||
{{~else}}
|
||||
|
@ -1,2 +1,3 @@
|
||||
### [v{{version}}]({{~@root.repoUrl}}/compare/{{previousTag}}...{{currentTag}})
|
||||
|
||||
`{{date}}`
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,16 @@
|
||||
module.exports = {
|
||||
extends: ['airbnb-base', 'plugin:vue/recommended'],
|
||||
extends: [
|
||||
'airbnb-base',
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:vue/recommended',
|
||||
'prettier',
|
||||
'prettier/vue',
|
||||
],
|
||||
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
ecmaVersion: 2018,
|
||||
ecmaVersion: 2019,
|
||||
sourceType: 'module',
|
||||
extraFileExtensions: ['.vue'],
|
||||
},
|
||||
@ -17,70 +24,41 @@ module.exports = {
|
||||
browser: true,
|
||||
},
|
||||
|
||||
globals: {
|
||||
window: false,
|
||||
document: false,
|
||||
navigator: false,
|
||||
},
|
||||
|
||||
rules: {
|
||||
'no-new': 0,
|
||||
'no-shadow': 0,
|
||||
camelcase: 1,
|
||||
'no-bitwise': 0,
|
||||
'func-names': 0,
|
||||
'no-console': 0,
|
||||
'no-plusplus': 0,
|
||||
'arrow-parens': 0,
|
||||
'default-case': 0,
|
||||
'comma-dangle': [
|
||||
'error',
|
||||
{
|
||||
arrays: 'always-multiline',
|
||||
objects: 'always-multiline',
|
||||
imports: 'always-multiline',
|
||||
exports: 'always-multiline',
|
||||
functions: 'never',
|
||||
},
|
||||
],
|
||||
'prefer-template': 0,
|
||||
'consistent-return': 0,
|
||||
'no-param-reassign': 0,
|
||||
'no-nested-ternary': 0,
|
||||
'operator-linebreak': 0,
|
||||
'object-curly-newline': 0,
|
||||
'no-underscore-dangle': 1,
|
||||
'no-unused-expressions': 0,
|
||||
'no-restricted-globals': 0,
|
||||
'function-paren-newline': 0,
|
||||
'class-methods-use-this': 0,
|
||||
'implicit-arrow-linebreak': 0,
|
||||
'space-before-function-paren': 0,
|
||||
'max-len': ['error', { code: 150 }],
|
||||
'no-new': 'off',
|
||||
'no-shadow': 'off',
|
||||
'no-bitwise': 'off',
|
||||
'func-names': 'off',
|
||||
'no-console': 'off',
|
||||
'no-plusplus': 'off',
|
||||
'default-case': 'off',
|
||||
'prefer-template': 'off',
|
||||
'consistent-return': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'no-nested-ternary': 'off',
|
||||
'no-underscore-dangle': 'off',
|
||||
'no-unused-expressions': 'off',
|
||||
'no-restricted-globals': 'off',
|
||||
'class-methods-use-this': 'off',
|
||||
'prefer-destructuring': ['error', { object: true, array: false }],
|
||||
'import/order': 0,
|
||||
'import/extensions': 0,
|
||||
'import/no-unresolved': 0,
|
||||
'import/prefer-default-export': 0,
|
||||
'import/no-extraneous-dependencies': 0,
|
||||
'vue/no-v-html': 0,
|
||||
'vue/attributes-order': 0,
|
||||
'vue/require-v-for-key': 0,
|
||||
'vue/require-default-prop': 0,
|
||||
'vue/no-unused-components': 0,
|
||||
'vue/max-attributes-per-line': 0,
|
||||
'vue/singleline-html-element-content-newline': 0,
|
||||
// eslint-plugin-import
|
||||
'import/order': 'off',
|
||||
'import/extensions': 'off',
|
||||
'import/no-unresolved': 'off',
|
||||
'import/prefer-default-export': 'off',
|
||||
'import/no-extraneous-dependencies': 'off',
|
||||
// eslint-plugin-vue
|
||||
'vue/no-v-html': 'off',
|
||||
'vue/attributes-order': 'off',
|
||||
'vue/require-v-for-key': 'off',
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/no-unused-components': 'off',
|
||||
'vue/name-property-casing': ['error', 'kebab-case'],
|
||||
'vue/component-name-in-template-casing': ['error', 'kebab-case'],
|
||||
'vue/html-closing-bracket-newline': 2,
|
||||
'vue/html-self-closing': [
|
||||
'error',
|
||||
{
|
||||
html: {
|
||||
void: 'always',
|
||||
},
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-unused-vars': ['error'],
|
||||
// typescript-eslint
|
||||
'@typescript-eslint/camelcase': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
},
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vant/eslint-config",
|
||||
"version": "2.0.0",
|
||||
"version": "2.2.0",
|
||||
"description": "eslint config of vant",
|
||||
"main": "index.js",
|
||||
"publishConfig": {
|
||||
@ -9,14 +9,15 @@
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/youzan/vant/tree/dev/packages/vant-eslint-config",
|
||||
"peerDependencies": {
|
||||
"eslint": "^6.8.0"
|
||||
"eslint": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^2.16.0",
|
||||
"@typescript-eslint/parser": "^2.16.0",
|
||||
"eslint-config-airbnb-base": "^14.0.0",
|
||||
"eslint-plugin-import": "^2.20.0",
|
||||
"eslint-plugin-vue": "^6.1.2"
|
||||
"@typescript-eslint/eslint-plugin": "^2.28.0",
|
||||
"@typescript-eslint/parser": "^2.28.0",
|
||||
"eslint-config-airbnb-base": "^14.1.0",
|
||||
"eslint-config-prettier": "^6.10.1",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-vue": "^6.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^6.8.0"
|
||||
|
@ -28,67 +28,58 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
|
||||
integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^2.12.0":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.npm.taobao.org/@typescript-eslint/eslint-plugin/download/@typescript-eslint/eslint-plugin-2.12.0.tgz?cache=0&sync_timestamp=1576629441087&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40typescript-eslint%2Feslint-plugin%2Fdownload%2F%40typescript-eslint%2Feslint-plugin-2.12.0.tgz#0da7cbca7b24f4c6919e9eb31c704bfb126f90ad"
|
||||
integrity sha1-DafLynsk9MaRnp6zHHBL+xJvkK0=
|
||||
"@typescript-eslint/eslint-plugin@^2.28.0":
|
||||
version "2.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.28.0.tgz#4431bc6d3af41903e5255770703d4e55a0ccbdec"
|
||||
integrity sha512-w0Ugcq2iatloEabQP56BRWJowliXUP5Wv6f9fKzjJmDW81hOTBxRoJ4LoEOxRpz9gcY51Libytd2ba3yLmSOfg==
|
||||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "2.12.0"
|
||||
eslint-utils "^1.4.3"
|
||||
"@typescript-eslint/experimental-utils" "2.28.0"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
regexpp "^3.0.0"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
"@typescript-eslint/experimental-utils@2.12.0":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.npm.taobao.org/@typescript-eslint/experimental-utils/download/@typescript-eslint/experimental-utils-2.12.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40typescript-eslint%2Fexperimental-utils%2Fdownload%2F%40typescript-eslint%2Fexperimental-utils-2.12.0.tgz#e0a76ffb6293e058748408a191921e453c31d40d"
|
||||
integrity sha1-4Kdv+2KT4Fh0hAihkZIeRTwx1A0=
|
||||
"@typescript-eslint/experimental-utils@2.28.0":
|
||||
version "2.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz#1fd0961cd8ef6522687b4c562647da6e71f8833d"
|
||||
integrity sha512-4SL9OWjvFbHumM/Zh/ZeEjUFxrYKtdCi7At4GyKTbQlrj1HcphIDXlje4Uu4cY+qzszR5NdVin4CCm6AXCjd6w==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.3"
|
||||
"@typescript-eslint/typescript-estree" "2.12.0"
|
||||
"@typescript-eslint/typescript-estree" "2.28.0"
|
||||
eslint-scope "^5.0.0"
|
||||
eslint-utils "^2.0.0"
|
||||
|
||||
"@typescript-eslint/parser@^2.12.0":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.npm.taobao.org/@typescript-eslint/parser/download/@typescript-eslint/parser-2.12.0.tgz?cache=0&sync_timestamp=1576629583072&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40typescript-eslint%2Fparser%2Fdownload%2F%40typescript-eslint%2Fparser-2.12.0.tgz#393f1604943a4ca570bb1a45bc8834e9b9158884"
|
||||
integrity sha1-OT8WBJQ6TKVwuxpFvIg06bkViIQ=
|
||||
"@typescript-eslint/parser@^2.28.0":
|
||||
version "2.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.28.0.tgz#bb761286efd2b0714761cab9d0ee5847cf080385"
|
||||
integrity sha512-RqPybRDquui9d+K86lL7iPqH6Dfp9461oyqvlXMNtap+PyqYbkY5dB7LawQjDzot99fqzvS0ZLZdfe+1Bt3Jgw==
|
||||
dependencies:
|
||||
"@types/eslint-visitor-keys" "^1.0.0"
|
||||
"@typescript-eslint/experimental-utils" "2.12.0"
|
||||
"@typescript-eslint/typescript-estree" "2.12.0"
|
||||
"@typescript-eslint/experimental-utils" "2.28.0"
|
||||
"@typescript-eslint/typescript-estree" "2.28.0"
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@2.12.0":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.npm.taobao.org/@typescript-eslint/typescript-estree/download/@typescript-eslint/typescript-estree-2.12.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40typescript-eslint%2Ftypescript-estree%2Fdownload%2F%40typescript-eslint%2Ftypescript-estree-2.12.0.tgz#bd9e547ccffd17dfab0c3ab0947c80c8e2eb914c"
|
||||
integrity sha1-vZ5UfM/9F9+rDDqwlHyAyOLrkUw=
|
||||
"@typescript-eslint/typescript-estree@2.28.0":
|
||||
version "2.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz#d34949099ff81092c36dc275b6a1ea580729ba00"
|
||||
integrity sha512-HDr8MP9wfwkiuqzRVkuM3BeDrOC4cKbO5a6BymZBHUt5y/2pL0BXD6I/C/ceq2IZoHWhcASk+5/zo+dwgu9V8Q==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
glob "^7.1.6"
|
||||
is-glob "^4.0.1"
|
||||
lodash.unescape "4.0.1"
|
||||
lodash "^4.17.15"
|
||||
semver "^6.3.0"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
acorn-jsx@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e"
|
||||
|
||||
acorn-jsx@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384"
|
||||
integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==
|
||||
|
||||
acorn@^6.0.7:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.npm.taobao.org/acorn/download/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784"
|
||||
integrity sha1-tlnS/7r6JLr12xzbsslKmD7NJ4Q=
|
||||
|
||||
acorn@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c"
|
||||
integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf"
|
||||
integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==
|
||||
|
||||
ajv@^6.10.0, ajv@^6.10.2:
|
||||
version "6.10.2"
|
||||
@ -212,10 +203,10 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
confusing-browser-globals@^1.0.7:
|
||||
confusing-browser-globals@^1.0.9:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd"
|
||||
integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==
|
||||
resolved "https://registry.npm.taobao.org/confusing-browser-globals/download/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd"
|
||||
integrity sha1-crwTtIPAJ2gBaBhx1ImFFvj1T90=
|
||||
|
||||
contains-path@^0.1.0:
|
||||
version "0.1.0"
|
||||
@ -338,14 +329,21 @@ escape-string-regexp@^1.0.5:
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
eslint-config-airbnb-base@^14.0.0:
|
||||
version "14.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz#8a7bcb9643d13c55df4dd7444f138bf4efa61e17"
|
||||
integrity sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA==
|
||||
eslint-config-airbnb-base@^14.1.0:
|
||||
version "14.1.0"
|
||||
resolved "https://registry.npm.taobao.org/eslint-config-airbnb-base/download/eslint-config-airbnb-base-14.1.0.tgz?cache=0&sync_timestamp=1584079908616&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-config-airbnb-base%2Fdownload%2Feslint-config-airbnb-base-14.1.0.tgz#2ba4592dd6843258221d9bff2b6831bd77c874e4"
|
||||
integrity sha1-K6RZLdaEMlgiHZv/K2gxvXfIdOQ=
|
||||
dependencies:
|
||||
confusing-browser-globals "^1.0.7"
|
||||
confusing-browser-globals "^1.0.9"
|
||||
object.assign "^4.1.0"
|
||||
object.entries "^1.1.0"
|
||||
object.entries "^1.1.1"
|
||||
|
||||
eslint-config-prettier@^6.10.1:
|
||||
version "6.10.1"
|
||||
resolved "https://registry.npm.taobao.org/eslint-config-prettier/download/eslint-config-prettier-6.10.1.tgz?cache=0&sync_timestamp=1584871355061&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-config-prettier%2Fdownload%2Feslint-config-prettier-6.10.1.tgz#129ef9ec575d5ddc0e269667bf09defcd898642a"
|
||||
integrity sha1-Ep757FddXdwOJpZnvwne/NiYZCo=
|
||||
dependencies:
|
||||
get-stdin "^6.0.0"
|
||||
|
||||
eslint-import-resolver-node@^0.3.2:
|
||||
version "0.3.2"
|
||||
@ -363,10 +361,10 @@ eslint-module-utils@^2.4.1:
|
||||
debug "^2.6.9"
|
||||
pkg-dir "^2.0.0"
|
||||
|
||||
eslint-plugin-import@^2.19.1:
|
||||
version "2.19.1"
|
||||
resolved "https://registry.npm.taobao.org/eslint-plugin-import/download/eslint-plugin-import-2.19.1.tgz#5654e10b7839d064dd0d46cd1b88ec2133a11448"
|
||||
integrity sha1-VlThC3g50GTdDUbNG4jsITOhFEg=
|
||||
eslint-plugin-import@^2.20.2:
|
||||
version "2.20.2"
|
||||
resolved "https://registry.npm.taobao.org/eslint-plugin-import/download/eslint-plugin-import-2.20.2.tgz#91fc3807ce08be4837141272c8b99073906e588d"
|
||||
integrity sha1-kfw4B84Ivkg3FBJyyLmQc5BuWI0=
|
||||
dependencies:
|
||||
array-includes "^3.0.3"
|
||||
array.prototype.flat "^1.2.1"
|
||||
@ -381,19 +379,14 @@ eslint-plugin-import@^2.19.1:
|
||||
read-pkg-up "^2.0.0"
|
||||
resolve "^1.12.0"
|
||||
|
||||
eslint-plugin-vue@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npm.taobao.org/eslint-plugin-vue/download/eslint-plugin-vue-6.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-vue%2Fdownload%2Feslint-plugin-vue-6.0.1.tgz#166d3eb24cf290f3ff24d44fe9fca496f3924fc2"
|
||||
integrity sha1-Fm0+skzykPP/JNRP6fyklvOST8I=
|
||||
eslint-plugin-vue@^6.2.2:
|
||||
version "6.2.2"
|
||||
resolved "https://registry.npm.taobao.org/eslint-plugin-vue/download/eslint-plugin-vue-6.2.2.tgz#27fecd9a3a24789b0f111ecdd540a9e56198e0fe"
|
||||
integrity sha1-J/7NmjokeJsPER7N1UCp5WGY4P4=
|
||||
dependencies:
|
||||
vue-eslint-parser "^6.0.5"
|
||||
|
||||
eslint-scope@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172"
|
||||
dependencies:
|
||||
esrecurse "^4.1.0"
|
||||
estraverse "^4.1.1"
|
||||
natural-compare "^1.4.0"
|
||||
semver "^5.6.0"
|
||||
vue-eslint-parser "^7.0.0"
|
||||
|
||||
eslint-scope@^5.0.0:
|
||||
version "5.0.0"
|
||||
@ -410,15 +403,22 @@ eslint-utils@^1.4.3:
|
||||
dependencies:
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
||||
eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
|
||||
eslint-utils@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npm.taobao.org/eslint-utils/download/eslint-utils-2.0.0.tgz?cache=0&sync_timestamp=1577351142754&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-utils%2Fdownload%2Feslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd"
|
||||
integrity sha1-e+HMcPJ6cqds0UqmmLyr7WiQ4c0=
|
||||
dependencies:
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
||||
eslint-visitor-keys@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
|
||||
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
|
||||
|
||||
eslint@^6.7.2:
|
||||
version "6.7.2"
|
||||
resolved "https://registry.npm.taobao.org/eslint/download/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1"
|
||||
integrity sha1-wXcHykrXstivmGoz/rpx4Yqf7NE=
|
||||
eslint@^6.8.0:
|
||||
version "6.8.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb"
|
||||
integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
ajv "^6.10.0"
|
||||
@ -458,15 +458,6 @@ eslint@^6.7.2:
|
||||
text-table "^0.2.0"
|
||||
v8-compile-cache "^2.0.3"
|
||||
|
||||
espree@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npm.taobao.org/espree/download/espree-5.0.1.tgz?cache=0&sync_timestamp=1571624368510&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fespree%2Fdownload%2Fespree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a"
|
||||
integrity sha1-XWUm+k/H8HiKXPdbFfMDI+L4H3o=
|
||||
dependencies:
|
||||
acorn "^6.0.7"
|
||||
acorn-jsx "^5.0.0"
|
||||
eslint-visitor-keys "^1.0.0"
|
||||
|
||||
espree@^6.1.2:
|
||||
version "6.1.2"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d"
|
||||
@ -580,6 +571,11 @@ functional-red-black-tree@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
||||
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
|
||||
|
||||
get-stdin@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npm.taobao.org/get-stdin/download/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
|
||||
integrity sha1-ngm/cSs2CrkiXoEgSPcf3pyJZXs=
|
||||
|
||||
glob-parent@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2"
|
||||
@ -816,12 +812,7 @@ locate-path@^2.0.0:
|
||||
p-locate "^2.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
lodash.unescape@4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
|
||||
integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=
|
||||
|
||||
lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15:
|
||||
lodash@^4.17.14, lodash@^4.17.15:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
@ -906,13 +897,13 @@ object.assign@^4.1.0:
|
||||
has-symbols "^1.0.0"
|
||||
object-keys "^1.0.11"
|
||||
|
||||
object.entries@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519"
|
||||
integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==
|
||||
object.entries@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npm.taobao.org/object.entries/download/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b"
|
||||
integrity sha1-7hzwQVPeArsJP+wzaDkA9XzlOZs=
|
||||
dependencies:
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.12.0"
|
||||
es-abstract "^1.17.0-next.1"
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
|
||||
@ -1117,7 +1108,7 @@ rxjs@^6.4.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
||||
|
||||
semver@^5.5.0:
|
||||
semver@^5.5.0, semver@^5.6.0:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
@ -1312,17 +1303,17 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
vue-eslint-parser@^6.0.5:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.npm.taobao.org/vue-eslint-parser/download/vue-eslint-parser-6.0.5.tgz?cache=0&sync_timestamp=1573306349811&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-eslint-parser%2Fdownload%2Fvue-eslint-parser-6.0.5.tgz#c1c067c2755748e28f3872cd42e8c1c4c1a8059f"
|
||||
integrity sha1-wcBnwnVXSOKPOHLNQujBxMGoBZ8=
|
||||
vue-eslint-parser@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.0.0.tgz#a4ed2669f87179dedd06afdd8736acbb3a3864d6"
|
||||
integrity sha512-yR0dLxsTT7JfD2YQo9BhnQ6bUTLsZouuzt9SKRP7XNaZJV459gvlsJo4vT2nhZ/2dH9j3c53bIx9dnqU2prM9g==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
eslint-scope "^4.0.0"
|
||||
eslint-visitor-keys "^1.0.0"
|
||||
espree "^5.0.0"
|
||||
eslint-scope "^5.0.0"
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
espree "^6.1.2"
|
||||
esquery "^1.0.1"
|
||||
lodash "^4.17.11"
|
||||
lodash "^4.17.15"
|
||||
|
||||
which@^1.2.9:
|
||||
version "1.3.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Vant Markdown Vetur
|
||||
|
||||
将 .md 文件转换成能描述 vue 组件的 .json 文件,供 vscode 插件 *vetur* 读取,从而可以在 vue 模版语法中拥有自动补全的功能。
|
||||
将 .md 文件转换成能描述 vue 组件的 .json 文件,供 WebStorm 和 vscode 的 `vetur` 插件读取,从而可以在 vue 模版语法中拥有自动补全的功能。
|
||||
|
||||
## Install
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vant/markdown-vetur",
|
||||
"version": "1.1.0",
|
||||
"version": "2.0.1",
|
||||
"description": "simple parse markdown to vue component description for vetur auto-completion",
|
||||
"main": "lib/index.js",
|
||||
"license": "MIT",
|
||||
@ -16,5 +16,12 @@
|
||||
"dev": "tsc --watch",
|
||||
"build": "tsc",
|
||||
"release": "npm run build && npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"fast-glob": "^3.2.2",
|
||||
"fs-extra": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^8.1.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,89 +0,0 @@
|
||||
/* eslint-disable no-continue */
|
||||
import { Artical } from './md-parser';
|
||||
|
||||
const FLAG_REG = /(.*?)\s*(Props|Event)/i;
|
||||
|
||||
export type Tag = {
|
||||
attributes: Record<string, Attribute>;
|
||||
description: string;
|
||||
defaults?: Array<string>;
|
||||
subtags?: Array<string>;
|
||||
};
|
||||
|
||||
export type Attribute = {
|
||||
description: string;
|
||||
type?: string;
|
||||
options?: Array<string>;
|
||||
};
|
||||
|
||||
function camelCaseToKebabCase(input: string): string {
|
||||
return input.replace(
|
||||
/[A-Z]/g,
|
||||
(val, index) => (index === 0 ? '' : '-') + val.toLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
function removeVersionTag(str: string) {
|
||||
return str.replace(/`(\w|\.)+`/g, '').trim();
|
||||
}
|
||||
|
||||
function getDescription(td: string[], isProp: boolean) {
|
||||
const desc = td[1] ? td[1].replace('<br>', '') : '';
|
||||
const type = td[2] ? td[2].replace(/\*/g, '') : '';
|
||||
const defaultVal = td[3] ? td[3].replace(/`/g, '') : '';
|
||||
|
||||
if (isProp) {
|
||||
return `${desc}, 默认值: ${defaultVal}, 类型: ${type}`;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
export function codegen(artical: Artical) {
|
||||
const tags: Record<string, Tag> = {};
|
||||
let tagDescription = '';
|
||||
|
||||
for (let i = 0, len = artical.length; i < len; i++) {
|
||||
const item = artical[i];
|
||||
if (item.type === 'title' && item.level === 2) {
|
||||
if (item.content) {
|
||||
tagDescription = item.content;
|
||||
}
|
||||
} else if (item.type === 'table') {
|
||||
const before = artical[i - 1];
|
||||
if (!before || !before.content) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { table } = item;
|
||||
const match = FLAG_REG.exec(before.content);
|
||||
|
||||
if (!match || !table) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const key = camelCaseToKebabCase(match[1] || 'default');
|
||||
const tag: Tag = tags[key] || {
|
||||
description: tagDescription,
|
||||
attributes: {},
|
||||
};
|
||||
|
||||
tags[key] = tag;
|
||||
|
||||
const isProp = /Props/i.test(match[2]);
|
||||
|
||||
table.body.forEach(td => {
|
||||
const name = removeVersionTag(td[0]);
|
||||
|
||||
const attr: Attribute = {
|
||||
description: getDescription(td, isProp),
|
||||
type: isProp ? td[2].replace(/`/g, '').toLowerCase() : 'event',
|
||||
};
|
||||
|
||||
tag.attributes[name] = attr;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
77
packages/vant-markdown-vetur/src/formatter.ts
Normal file
77
packages/vant-markdown-vetur/src/formatter.ts
Normal file
@ -0,0 +1,77 @@
|
||||
/* eslint-disable no-continue */
|
||||
import { Artical, Articals } from './parser';
|
||||
import { formatType, removeVersion, toKebabCase } from './utils';
|
||||
import { VueTag } from './type';
|
||||
|
||||
function getComponentName(artical: Artical, tagPrefix: string) {
|
||||
if (artical.content) {
|
||||
return tagPrefix + toKebabCase(artical.content.split(' ')[0]);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
export function formatter(articals: Articals, tagPrefix: string = '') {
|
||||
if (!articals.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tag: VueTag = {
|
||||
name: getComponentName(articals[0], tagPrefix),
|
||||
slots: [],
|
||||
events: [],
|
||||
attributes: [],
|
||||
};
|
||||
|
||||
const tables = articals.filter(artical => artical.type === 'table');
|
||||
|
||||
tables.forEach(item => {
|
||||
const { table } = item;
|
||||
const prevIndex = articals.indexOf(item) - 1;
|
||||
const prevArtical = articals[prevIndex];
|
||||
|
||||
if (!prevArtical || !prevArtical.content || !table || !table.body) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tableTitle = prevArtical.content;
|
||||
|
||||
if (tableTitle.includes('Props')) {
|
||||
table.body.forEach(line => {
|
||||
const [name, desc, type, defaultVal] = line;
|
||||
tag.attributes!.push({
|
||||
name: removeVersion(name),
|
||||
default: defaultVal,
|
||||
description: desc,
|
||||
value: {
|
||||
type: formatType(type),
|
||||
kind: 'expression',
|
||||
},
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (tableTitle.includes('Events')) {
|
||||
table.body.forEach(line => {
|
||||
const [name, desc] = line;
|
||||
tag.events!.push({
|
||||
name: removeVersion(name),
|
||||
description: desc,
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (tableTitle.includes('Slots')) {
|
||||
table.body.forEach(line => {
|
||||
const [name, desc] = line;
|
||||
tag.slots!.push({
|
||||
name: removeVersion(name),
|
||||
description: desc,
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return tag;
|
||||
}
|
@ -1,140 +1,46 @@
|
||||
import glob from 'fast-glob';
|
||||
import { join } from 'path';
|
||||
import { mdParser } from './md-parser';
|
||||
import { codegen, Tag, Attribute } from './codegen';
|
||||
import {
|
||||
PathLike,
|
||||
statSync,
|
||||
mkdirSync,
|
||||
existsSync,
|
||||
readdirSync,
|
||||
readFileSync,
|
||||
writeFileSync,
|
||||
} from 'fs';
|
||||
import { mdParser } from './parser';
|
||||
import { formatter } from './formatter';
|
||||
import { genWebTypes } from './web-types';
|
||||
import { readFileSync, outputFileSync } from 'fs-extra';
|
||||
import { Options, VueTag } from './type';
|
||||
import { normalizePath } from './utils';
|
||||
import { genVeturTags, genVeturAttributes } from './vetur';
|
||||
|
||||
export function parseText(input: string) {
|
||||
const ast = mdParser(input);
|
||||
|
||||
return codegen(ast);
|
||||
async function readMarkdown(options: Options) {
|
||||
const mds = await glob(normalizePath(`${options.path}/**/*.md`));
|
||||
return mds
|
||||
.filter(md => options.test.test(md))
|
||||
.map(path => readFileSync(path, 'utf-8'));
|
||||
}
|
||||
|
||||
export type Options = {
|
||||
// 需要解析的文件夹路径
|
||||
path: PathLike;
|
||||
// 文件匹配正则
|
||||
test: RegExp;
|
||||
// 输出目录
|
||||
outputDir?: string;
|
||||
// 递归的目录最大深度
|
||||
maxDeep?: number;
|
||||
// 解析出来的组件名前缀
|
||||
tagPrefix?: string;
|
||||
};
|
||||
|
||||
export type ParseResult = {
|
||||
tags: Record<
|
||||
string,
|
||||
{
|
||||
description: string;
|
||||
attributes: string[];
|
||||
}
|
||||
>;
|
||||
attributes: Record<string, Attribute>;
|
||||
};
|
||||
|
||||
const defaultOptions = {
|
||||
maxDeep: Infinity,
|
||||
tagPrefix: '',
|
||||
};
|
||||
|
||||
export function parse(options: Options) {
|
||||
options = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
};
|
||||
|
||||
const result: ParseResult = {
|
||||
tags: {},
|
||||
attributes: {},
|
||||
};
|
||||
|
||||
function putResult(componentName: string, component: Tag) {
|
||||
componentName = options.tagPrefix + componentName;
|
||||
const attributes = Object.keys(component.attributes);
|
||||
const tag = {
|
||||
description: component.description,
|
||||
attributes,
|
||||
};
|
||||
|
||||
result.tags[componentName] = tag;
|
||||
attributes.forEach(key => {
|
||||
result.attributes[`${componentName}/${key}`] = component.attributes[key];
|
||||
});
|
||||
}
|
||||
|
||||
function recursiveParse(options: Options, deep: number) {
|
||||
if (options.maxDeep && deep > options.maxDeep) {
|
||||
return;
|
||||
}
|
||||
|
||||
deep++;
|
||||
const files = readdirSync(options.path);
|
||||
files.forEach(item => {
|
||||
const currentPath = join(options.path.toString(), item);
|
||||
const stats = statSync(currentPath);
|
||||
if (stats.isDirectory()) {
|
||||
recursiveParse(
|
||||
{
|
||||
...options,
|
||||
path: currentPath,
|
||||
},
|
||||
deep
|
||||
);
|
||||
} else if (stats.isFile() && options.test.test(item)) {
|
||||
const file = readFileSync(currentPath);
|
||||
|
||||
const tags = parseText(file.toString());
|
||||
|
||||
if (tags.default) {
|
||||
// one tag
|
||||
putResult(currentPath.split('/').slice(-2)[0], tags.default);
|
||||
} else {
|
||||
Object.keys(tags).forEach(key => {
|
||||
putResult(key, tags[key]);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
recursiveParse(options, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function parseAndWrite(options: Options) {
|
||||
const { tags, attributes } = parse(options);
|
||||
|
||||
export async function parseAndWrite(options: Options) {
|
||||
if (!options.outputDir) {
|
||||
return;
|
||||
throw new Error('outputDir can not be empty.');
|
||||
}
|
||||
|
||||
const isExist = existsSync(options.outputDir);
|
||||
if (!isExist) {
|
||||
mkdirSync(options.outputDir);
|
||||
}
|
||||
const mds = await readMarkdown(options);
|
||||
const datas = mds
|
||||
.map(md => formatter(mdParser(md), options.tagPrefix))
|
||||
.filter(item => !!item) as VueTag[];
|
||||
|
||||
writeFileSync(
|
||||
const webTypes = genWebTypes(datas, options);
|
||||
const veturTags = genVeturTags(datas);
|
||||
const veturAttributes = genVeturAttributes(datas);
|
||||
|
||||
outputFileSync(
|
||||
join(options.outputDir, 'tags.json'),
|
||||
JSON.stringify(tags, null, 2)
|
||||
JSON.stringify(veturTags, null, 2)
|
||||
);
|
||||
writeFileSync(
|
||||
outputFileSync(
|
||||
join(options.outputDir, 'attributes.json'),
|
||||
JSON.stringify(attributes, null, 2)
|
||||
JSON.stringify(veturAttributes, null, 2)
|
||||
);
|
||||
outputFileSync(
|
||||
join(options.outputDir, 'web-types.json'),
|
||||
JSON.stringify(webTypes, null, 2)
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
parse,
|
||||
parseText,
|
||||
parseAndWrite,
|
||||
};
|
||||
export default { parseAndWrite };
|
||||
|
@ -4,19 +4,19 @@ const TABLE_REG = /^\|.+\n\|\s*-+/;
|
||||
const TD_REG = /\s*`[^`]+`\s*|([^|`]+)/g;
|
||||
const TABLE_SPLIT_LINE_REG = /^\|\s*-/;
|
||||
|
||||
interface TableContent {
|
||||
head: Array<string>;
|
||||
body: Array<Array<string>>;
|
||||
}
|
||||
type TableContent = {
|
||||
head: string[];
|
||||
body: string[][];
|
||||
};
|
||||
|
||||
interface SimpleMdAst {
|
||||
export type Artical = {
|
||||
type: string;
|
||||
content?: string;
|
||||
table?: TableContent;
|
||||
level?: number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface Artical extends Array<SimpleMdAst> {}
|
||||
export type Articals = Artical[];
|
||||
|
||||
function readLine(input: string) {
|
||||
const end = input.indexOf('\n');
|
||||
@ -73,7 +73,7 @@ function tableParse(input: string) {
|
||||
};
|
||||
}
|
||||
|
||||
export function mdParser(input: string): Array<SimpleMdAst> {
|
||||
export function mdParser(input: string): Articals {
|
||||
const artical = [];
|
||||
let start = 0;
|
||||
const end = input.length;
|
63
packages/vant-markdown-vetur/src/type.ts
Normal file
63
packages/vant-markdown-vetur/src/type.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { PathLike } from 'fs';
|
||||
|
||||
export type VueSlot = {
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export type VueEventArgument = {
|
||||
name: string;
|
||||
type: string;
|
||||
};
|
||||
|
||||
export type VueEvent = {
|
||||
name: string;
|
||||
description?: string;
|
||||
arguments?: VueEventArgument[];
|
||||
};
|
||||
|
||||
export type VueAttribute = {
|
||||
name: string;
|
||||
default: string;
|
||||
description: string;
|
||||
value: {
|
||||
kind: 'expression';
|
||||
type: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type VueTag = {
|
||||
name: string;
|
||||
slots?: VueSlot[];
|
||||
events?: VueEvent[];
|
||||
attributes?: VueAttribute[];
|
||||
description?: string;
|
||||
};
|
||||
|
||||
export type VeturTag = {
|
||||
description?: string;
|
||||
attributes: string[];
|
||||
};
|
||||
|
||||
export type VeturTags = Record<string, VeturTag>;
|
||||
|
||||
export type VeturAttribute = {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export type VeturAttributes = Record<string, VeturAttribute>;
|
||||
|
||||
export type VeturResult = {
|
||||
tags: VeturTags;
|
||||
attributes: VeturAttributes;
|
||||
};
|
||||
|
||||
export type Options = {
|
||||
name: string;
|
||||
path: PathLike;
|
||||
test: RegExp;
|
||||
version: string;
|
||||
outputDir?: string;
|
||||
tagPrefix?: string;
|
||||
};
|
22
packages/vant-markdown-vetur/src/utils.ts
Normal file
22
packages/vant-markdown-vetur/src/utils.ts
Normal file
@ -0,0 +1,22 @@
|
||||
// myName -> my-name
|
||||
export function toKebabCase(input: string): string {
|
||||
return input.replace(
|
||||
/[A-Z]/g,
|
||||
(val, index) => (index === 0 ? '' : '-') + val.toLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
// name `v2.0.0` -> name
|
||||
export function removeVersion(str: string) {
|
||||
return str.replace(/`(\w|\.)+`/g, '').trim();
|
||||
}
|
||||
|
||||
// *boolean* -> boolean
|
||||
// _boolean_ -> boolean
|
||||
export function formatType(type: string) {
|
||||
return type.replace(/(^(\*|_))|((\*|_)$)/g, '');
|
||||
}
|
||||
|
||||
export function normalizePath(path: string): string {
|
||||
return path.replace(/\\/g, '/');
|
||||
}
|
30
packages/vant-markdown-vetur/src/vetur.ts
Normal file
30
packages/vant-markdown-vetur/src/vetur.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { VueTag, VeturTags, VeturAttributes } from './type';
|
||||
|
||||
export function genVeturTags(tags: VueTag[]) {
|
||||
const veturTags: VeturTags = {};
|
||||
|
||||
tags.forEach(tag => {
|
||||
veturTags[tag.name] = {
|
||||
attributes: tag.attributes ? tag.attributes.map(item => item.name) : [],
|
||||
};
|
||||
});
|
||||
|
||||
return veturTags;
|
||||
}
|
||||
|
||||
export function genVeturAttributes(tags: VueTag[]) {
|
||||
const veturAttributes: VeturAttributes = {};
|
||||
|
||||
tags.forEach(tag => {
|
||||
if (tag.attributes) {
|
||||
tag.attributes.forEach(attr => {
|
||||
veturAttributes[`${tag.name}/${attr.name}`] = {
|
||||
type: attr.value.type,
|
||||
description: `${attr.description}, 默认值: ${attr.default}`,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return veturAttributes;
|
||||
}
|
19
packages/vant-markdown-vetur/src/web-types.ts
Normal file
19
packages/vant-markdown-vetur/src/web-types.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { VueTag, Options } from './type';
|
||||
|
||||
// create web-types.json to provide autocomplete in JetBrains IDEs
|
||||
export function genWebTypes(tags: VueTag[], options: Options) {
|
||||
return {
|
||||
$schema:
|
||||
'https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json',
|
||||
framework: 'vue',
|
||||
name: options.name,
|
||||
version: options.version,
|
||||
contributions: {
|
||||
html: {
|
||||
tags,
|
||||
attributes: [],
|
||||
'types-syntax': 'typescript',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"include": ["src/*"],
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"outDir": "./lib",
|
||||
"module": "commonjs",
|
||||
"outDir": "lib",
|
||||
"noEmit": false
|
||||
}
|
||||
"strict": true,
|
||||
"declaration": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"]
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
|
162
packages/vant-markdown-vetur/yarn.lock
Normal file
162
packages/vant-markdown-vetur/yarn.lock
Normal file
@ -0,0 +1,162 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@nodelib/fs.scandir@2.1.3":
|
||||
version "2.1.3"
|
||||
resolved "http://registry.npm.qima-inc.com/@nodelib/fs.scandir/download/@nodelib/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
|
||||
integrity sha1-Olgr21OATGum0UZXnEblITDPSjs=
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "2.0.3"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2":
|
||||
version "2.0.3"
|
||||
resolved "http://registry.npm.qima-inc.com/@nodelib/fs.stat/download/@nodelib/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3"
|
||||
integrity sha1-NNxfTKu8cg9OYPdadH5+zWwXW9M=
|
||||
|
||||
"@nodelib/fs.walk@^1.2.3":
|
||||
version "1.2.4"
|
||||
resolved "http://registry.npm.qima-inc.com/@nodelib/fs.walk/download/@nodelib/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976"
|
||||
integrity sha1-ARuSAqcKY2bkNspcBlhEUoqwSXY=
|
||||
dependencies:
|
||||
"@nodelib/fs.scandir" "2.1.3"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@types/fs-extra@^8.1.0":
|
||||
version "8.1.0"
|
||||
resolved "http://registry.npm.qima-inc.com/@types/fs-extra/download/@types/fs-extra-8.1.0.tgz#1114834b53c3914806cd03b3304b37b3bd221a4d"
|
||||
integrity sha1-ERSDS1PDkUgGzQOzMEs3s70iGk0=
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*":
|
||||
version "13.9.3"
|
||||
resolved "http://registry.npm.qima-inc.com/@types/node/download/@types/node-13.9.3.tgz#6356df2647de9eac569f9a52eda3480fa9e70b4d"
|
||||
integrity sha1-Y1bfJkfenqxWn5pS7aNID6nnC00=
|
||||
|
||||
at-least-node@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "http://registry.npm.qima-inc.com/at-least-node/download/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
|
||||
integrity sha1-YCzUtG6EStTv/JKoARo8RuAjjcI=
|
||||
|
||||
braces@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "http://registry.npm.qima-inc.com/braces/download/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha1-NFThpGLujVmeI23zNs2epPiv4Qc=
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
fast-glob@^3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "http://registry.npm.qima-inc.com/fast-glob/download/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d"
|
||||
integrity sha1-reGp2RFIll1L98UfcuHKZi0y5j0=
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "^2.0.2"
|
||||
"@nodelib/fs.walk" "^1.2.3"
|
||||
glob-parent "^5.1.0"
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.2"
|
||||
picomatch "^2.2.1"
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.6.1"
|
||||
resolved "http://registry.npm.qima-inc.com/fastq/download/fastq-1.6.1.tgz#4570c74f2ded173e71cf0beb08ac70bb85826791"
|
||||
integrity sha1-RXDHTy3tFz5xzwvrCKxwu4WCZ5E=
|
||||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "http://registry.npm.qima-inc.com/fill-range/download/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
integrity sha1-GRmmp8df44ssfHflGYU12prN2kA=
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
fs-extra@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "http://registry.npm.qima-inc.com/fs-extra/download/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3"
|
||||
integrity sha1-tq/DEDbiR7JGbcmcKa55fV1FgKM=
|
||||
dependencies:
|
||||
at-least-node "^1.0.0"
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^1.0.0"
|
||||
|
||||
glob-parent@^5.1.0:
|
||||
version "5.1.1"
|
||||
resolved "http://registry.npm.qima-inc.com/glob-parent/download/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
|
||||
integrity sha1-tsHvQXxOVmPqSY8cRa+saRa7wik=
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
version "4.2.3"
|
||||
resolved "http://registry.npm.qima-inc.com/graceful-fs/download/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
|
||||
integrity sha1-ShL/G2A3bvCYYsIJPt2Qgyi+hCM=
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "http://registry.npm.qima-inc.com/is-extglob/download/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
|
||||
is-glob@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "http://registry.npm.qima-inc.com/is-glob/download/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
|
||||
integrity sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=
|
||||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-number@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "http://registry.npm.qima-inc.com/is-number/download/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "http://registry.npm.qima-inc.com/jsonfile/download/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179"
|
||||
integrity sha1-mJZsuiFDeMjIS4LghZB7QL9hQXk=
|
||||
dependencies:
|
||||
universalify "^1.0.0"
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
merge2@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "http://registry.npm.qima-inc.com/merge2/download/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
|
||||
integrity sha1-WzZu6DsvFYLEj4fkfPGpNSEDyoE=
|
||||
|
||||
micromatch@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "http://registry.npm.qima-inc.com/micromatch/download/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
|
||||
integrity sha1-T8sJmb+fvC/L3SEvbWKbmlbDklk=
|
||||
dependencies:
|
||||
braces "^3.0.1"
|
||||
picomatch "^2.0.5"
|
||||
|
||||
picomatch@^2.0.5, picomatch@^2.2.1:
|
||||
version "2.2.2"
|
||||
resolved "http://registry.npm.qima-inc.com/picomatch/download/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
|
||||
integrity sha1-IfMz6ba46v8CRo9RRupAbTRfTa0=
|
||||
|
||||
reusify@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "http://registry.npm.qima-inc.com/reusify/download/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
integrity sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY=
|
||||
|
||||
run-parallel@^1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "http://registry.npm.qima-inc.com/run-parallel/download/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679"
|
||||
integrity sha1-yd06fPn0ssS2JE4XOm7YZuYd1nk=
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "http://registry.npm.qima-inc.com/to-regex-range/download/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
integrity sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
universalify@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "http://registry.npm.qima-inc.com/universalify/download/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
|
||||
integrity sha1-thodoXPoQ1sv48Z9Kbmt+FlL0W0=
|
@ -1,11 +1,16 @@
|
||||
module.exports = {
|
||||
extends: ['stylelint-config-standard', 'stylelint-config-rational-order'],
|
||||
extends: [
|
||||
'stylelint-config-standard',
|
||||
'stylelint-config-rational-order',
|
||||
'stylelint-config-prettier',
|
||||
],
|
||||
rules: {
|
||||
'order/properties-order': [],
|
||||
'at-rule-no-unknown': null,
|
||||
'number-leading-zero': null,
|
||||
'no-descending-specificity': null,
|
||||
'declaration-colon-newline-after': null,
|
||||
'font-family-no-missing-generic-family-keyword': null,
|
||||
'selector-pseudo-element-no-unknown': [
|
||||
true,
|
||||
{
|
||||
ignorePseudoElements: ['v-deep'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vant/stylelint-config",
|
||||
"version": "1.1.0",
|
||||
"version": "1.3.0",
|
||||
"description": "stylelint config of vant.",
|
||||
"main": "index.js",
|
||||
"publishConfig": {
|
||||
@ -9,11 +9,12 @@
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/youzan/vant/tree/dev/packages/vant-stylelint-config",
|
||||
"peerDependencies": {
|
||||
"stylelint": "^12.0.0"
|
||||
"stylelint": "^13.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"stylelint-config-prettier": "^8.0.1",
|
||||
"stylelint-config-rational-order": "^0.1.2",
|
||||
"stylelint-config-standard": "^19.0.0",
|
||||
"stylelint-order": "^3.1.1"
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"stylelint-order": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -1717,6 +1717,15 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.1
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^7.0.26:
|
||||
version "7.0.27"
|
||||
resolved "https://registry.npm.taobao.org/postcss/download/postcss-7.0.27.tgz?cache=0&sync_timestamp=1581994853208&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9"
|
||||
integrity sha1-zGfNxrDao3UQW3xCSoVWc0X8VNk=
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
@ -2084,6 +2093,11 @@ style-search@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
|
||||
integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=
|
||||
|
||||
stylelint-config-prettier@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.npm.taobao.org/stylelint-config-prettier/download/stylelint-config-prettier-8.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstylelint-config-prettier%2Fdownload%2Fstylelint-config-prettier-8.0.1.tgz#ec7cdd7faabaff52ebfa56c28fed3d995ebb8cab"
|
||||
integrity sha1-7Hzdf6q6/1Lr+lbCj+09mV67jKs=
|
||||
|
||||
stylelint-config-rational-order@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/stylelint-config-rational-order/-/stylelint-config-rational-order-0.1.2.tgz#4e98e390783d437f0ec41fb73bc41992e78d02a0"
|
||||
@ -2097,10 +2111,10 @@ stylelint-config-recommended@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-3.0.0.tgz#e0e547434016c5539fe2650afd58049a2fd1d657"
|
||||
integrity sha512-F6yTRuc06xr1h5Qw/ykb2LuFynJ2IxkKfCMf+1xqPffkxh0S09Zc902XCffcsw/XMFq/OzQ1w54fLIDtmRNHnQ==
|
||||
|
||||
stylelint-config-standard@^19.0.0:
|
||||
version "19.0.0"
|
||||
resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-19.0.0.tgz#66f0cf13f33b8a9e34965881493b38fc1313693a"
|
||||
integrity sha512-VvcODsL1PryzpYteWZo2YaA5vU/pWfjqBpOvmeA8iB2MteZ/ZhI1O4hnrWMidsS4vmEJpKtjdhLdfGJmmZm6Cg==
|
||||
stylelint-config-standard@^20.0.0:
|
||||
version "20.0.0"
|
||||
resolved "https://registry.npm.taobao.org/stylelint-config-standard/download/stylelint-config-standard-20.0.0.tgz#06135090c9e064befee3d594289f50e295b5e20d"
|
||||
integrity sha1-BhNQkMngZL7+49WUKJ9Q4pW14g0=
|
||||
dependencies:
|
||||
stylelint-config-recommended "^3.0.0"
|
||||
|
||||
@ -2113,13 +2127,13 @@ stylelint-order@^2.2.1:
|
||||
postcss "^7.0.2"
|
||||
postcss-sorting "^4.1.0"
|
||||
|
||||
stylelint-order@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/stylelint-order/-/stylelint-order-3.1.1.tgz#ba9ea6844d1482f97f31204e7c9605c7b792c294"
|
||||
integrity sha512-4gP/r8j/6JGZ/LL41b2sYtQqfwZl4VSqTp7WeIwI67v/OXNQ08dnn64BGXNwAUSgb2+YIvIOxQaMzqMyQMzoyQ==
|
||||
stylelint-order@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npm.taobao.org/stylelint-order/download/stylelint-order-4.0.0.tgz#2a945c2198caac3ff44687d7c8582c81d044b556"
|
||||
integrity sha1-KpRcIZjKrD/0RofXyFgsgdBEtVY=
|
||||
dependencies:
|
||||
lodash "^4.17.15"
|
||||
postcss "^7.0.17"
|
||||
postcss "^7.0.26"
|
||||
postcss-sorting "^5.0.1"
|
||||
|
||||
stylelint@^9.10.1:
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vant/waterfall",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "vant waterfall component",
|
||||
"main": "lib/index.js",
|
||||
"publishConfig": {
|
||||
@ -12,7 +12,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/youzan/vant/tree/dev/packages/vant-waterfall",
|
||||
"dependencies": {
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.4.4",
|
||||
"@babel/core": "^7.4.4",
|
||||
"@babel/plugin-transform-object-assign": "^7.2.0",
|
||||
|
@ -70,7 +70,7 @@ function doBindEvent() {
|
||||
const disabledExpr = this.el.getAttribute('waterfall-disabled');
|
||||
let disabled = false;
|
||||
if (disabledExpr) {
|
||||
this.vm.$watch(disabledExpr, value => {
|
||||
this.vm.$watch(disabledExpr, (value) => {
|
||||
this.disabled = value;
|
||||
this.scrollEventListener();
|
||||
});
|
||||
@ -99,7 +99,6 @@ function startBind(el) {
|
||||
function doCheckStartBind(el) {
|
||||
const context = el[CONTEXT];
|
||||
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
if (context.vm._isMounted) {
|
||||
startBind(el);
|
||||
} else {
|
||||
@ -109,7 +108,7 @@ function doCheckStartBind(el) {
|
||||
}
|
||||
}
|
||||
|
||||
export default function(type) {
|
||||
export default function (type) {
|
||||
return {
|
||||
bind(el, binding, vnode) {
|
||||
if (!el[CONTEXT]) {
|
||||
|
@ -29,16 +29,16 @@ export default {
|
||||
actions: [
|
||||
{ name: 'Option' },
|
||||
{ name: 'Option' },
|
||||
{ name: 'Option', subname: 'Description' }
|
||||
]
|
||||
{ name: 'Option', subname: 'Description' },
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onSelect(item) {
|
||||
this.show = false;
|
||||
Toast(item.name);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@ -59,15 +59,15 @@ import { Toast } from 'vant';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onCancel() {
|
||||
this.show = false;
|
||||
Toast('cancel');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@ -96,10 +96,10 @@ export default {
|
||||
actions: [
|
||||
{ name: 'Option', color: '#07c160' },
|
||||
{ loading: true },
|
||||
{ name: 'Disabled Option', disabled: true }
|
||||
]
|
||||
{ name: 'Disabled Option', disabled: true },
|
||||
],
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@ -111,9 +111,9 @@ export default {
|
||||
</van-action-sheet>
|
||||
|
||||
<style>
|
||||
.content {
|
||||
padding: 16px 16px 160px;
|
||||
}
|
||||
.content {
|
||||
padding: 16px 16px 160px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@ -122,40 +122,41 @@ export default {
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
| actions | Options | *Action[]* | `[]` |
|
||||
| title | Title | *string* | - |
|
||||
| cancel-text | Text of cancel button | *string* | - |
|
||||
| description `v2.2.8` | Description above the options | *string* | - |
|
||||
| close-icon `v2.2.13` | Close icon name | *string* | `cross` |
|
||||
| duration `v2.0.3` | Transition duration, unit second | *number \| string* | `0.3` |
|
||||
| round `v2.0.9` | Whether to show round corner | *boolean* | `true` |
|
||||
| overlay | Whether to show overlay | *boolean* | `true` |
|
||||
| lock-scroll | Whether to lock background scroll | *boolean* | `true` |
|
||||
| lazy-render | Whether to lazy render util appeared | *boolean* | `true` |
|
||||
| close-on-popstate `v2.5.3` | Whether to close when popstate | *boolean* | `false` |
|
||||
| close-on-click-action | Whether to close when click action | *boolean* | `false` |
|
||||
| close-on-click-overlay | Whether to close when click overlay | *boolean* | `true` |
|
||||
| safe-area-inset-bottom | Whether to enable bottom safe area adaptation | *boolean* | `true` |
|
||||
| get-container | Return the mount node for ActionSheet | *string \| () => Element* | - |
|
||||
| --- | --- | --- | --- |
|
||||
| v-model (value) | Whether to show ActionSheet | _boolean_ | `false` |
|
||||
| actions | Options | _Action[]_ | `[]` |
|
||||
| title | Title | _string_ | - |
|
||||
| cancel-text | Text of cancel button | _string_ | - |
|
||||
| description `v2.2.8` | Description above the options | _string_ | - |
|
||||
| close-icon `v2.2.13` | Close icon name | _string_ | `cross` |
|
||||
| duration `v2.0.3` | Transition duration, unit second | _number \| string_ | `0.3` |
|
||||
| round `v2.0.9` | Whether to show round corner | _boolean_ | `true` |
|
||||
| overlay | Whether to show overlay | _boolean_ | `true` |
|
||||
| lock-scroll | Whether to lock background scroll | _boolean_ | `true` |
|
||||
| lazy-render | Whether to lazy render util appeared | _boolean_ | `true` |
|
||||
| close-on-popstate `v2.5.3` | Whether to close when popstate | _boolean_ | `false` |
|
||||
| close-on-click-action | Whether to close when click action | _boolean_ | `false` |
|
||||
| close-on-click-overlay | Whether to close when click overlay | _boolean_ | `true` |
|
||||
| safe-area-inset-bottom | Whether to enable bottom safe area adaptation | _boolean_ | `true` |
|
||||
| get-container | Return the mount node for ActionSheet | _string \| () => Element_ | - |
|
||||
|
||||
### Data Structure of Action
|
||||
|
||||
| Key | Description | Type |
|
||||
|------|------|------|
|
||||
| name | Title | *string* |
|
||||
| subname | Subtitle | *string* |
|
||||
| color | Text color | *string* |
|
||||
| className | className for the option | *any* |
|
||||
| loading | Whether to be loading status | *boolean* |
|
||||
| disabled | Whether to be disabled | *boolean* |
|
||||
| Key | Description | Type |
|
||||
| --------- | ---------------------------- | --------- |
|
||||
| name | Title | _string_ |
|
||||
| subname | Subtitle | _string_ |
|
||||
| color | Text color | _string_ |
|
||||
| className | className for the option | _any_ |
|
||||
| loading | Whether to be loading status | _boolean_ |
|
||||
| disabled | Whether to be disabled | _boolean_ |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|------|------|------|
|
||||
| select | Triggered when click option | *action: Action, index: number* |
|
||||
| cancel | Triggered when cancel click | - |
|
||||
| --- | --- | --- |
|
||||
| select | Triggered when click option | _action: Action, index: number_ |
|
||||
| cancel | Triggered when click cancel button | - |
|
||||
| open | Triggered when open ActionSheet | - |
|
||||
| close | Triggered when close ActionSheet | - |
|
||||
| opened | Triggered when opened ActionSheet | - |
|
||||
|
@ -1,4 +1,8 @@
|
||||
# ActionSheet 上拉菜单
|
||||
# ActionSheet 动作面板
|
||||
|
||||
### 介绍
|
||||
|
||||
底部弹起的模态面板,包含与当前情境相关的多个选项。
|
||||
|
||||
### 引入
|
||||
|
||||
@ -13,7 +17,7 @@ Vue.use(ActionSheet);
|
||||
|
||||
### 基础用法
|
||||
|
||||
`ActionSheet`通过`actions`数组来定义展示的选项,数组的每一项是一个对象,对象属性见文档下方表格。
|
||||
动作面板通过`actions`属性来定义选项,数组的每一项是一个对象,对象格式见文档下方表格。
|
||||
|
||||
```html
|
||||
<van-action-sheet v-model="show" :actions="actions" @select="onSelect" />
|
||||
@ -29,8 +33,8 @@ export default {
|
||||
actions: [
|
||||
{ name: '选项' },
|
||||
{ name: '选项' },
|
||||
{ name: '选项', subname: '描述信息' }
|
||||
]
|
||||
{ name: '选项', subname: '描述信息' },
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@ -39,14 +43,14 @@ export default {
|
||||
// 可以通过 close-on-click-action 属性开启自动收起
|
||||
this.show = false;
|
||||
Toast(item.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 展示取消按钮
|
||||
|
||||
设置`cancel-text`属性后,会在底部展示取消按钮,点击后关闭当前菜单
|
||||
设置`cancel-text`属性后,会在底部展示取消按钮,点击后关闭当前面板
|
||||
|
||||
```html
|
||||
<van-action-sheet
|
||||
@ -63,16 +67,16 @@ import { Toast } from 'vant';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onCancel() {
|
||||
this.show = false;
|
||||
Toast('cancel');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 展示描述信息
|
||||
@ -108,16 +112,16 @@ export default {
|
||||
actions: [
|
||||
{ name: '选项', color: '#07c160' },
|
||||
{ loading: true },
|
||||
{ name: '禁用选项', disabled: true }
|
||||
]
|
||||
{ name: '禁用选项', disabled: true },
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 自定义面板
|
||||
|
||||
通过插槽可以自定义菜单的展示内容,同时可以使用`title`属性展示标题栏
|
||||
通过插槽可以自定义面板的展示内容,同时可以使用`title`属性展示标题栏
|
||||
|
||||
```html
|
||||
<van-action-sheet v-model="show" title="标题">
|
||||
@ -125,9 +129,9 @@ export default {
|
||||
</van-action-sheet>
|
||||
|
||||
<style>
|
||||
.content {
|
||||
padding: 16px 16px 160px;
|
||||
}
|
||||
.content {
|
||||
padding: 16px 16px 160px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@ -136,50 +140,51 @@ export default {
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------|------|------|------|
|
||||
| actions | 菜单选项 | *Action[]* | `[]` |
|
||||
| title | 顶部标题 | *string* | - |
|
||||
| cancel-text | 取消按钮文字 | *string* | - |
|
||||
| description `v2.2.8` | 选项上方的描述信息 | *string* | - |
|
||||
| close-icon `v2.2.13` | 关闭[图标名称](#/zh-CN/icon)或图片链接 | *string* | `cross` |
|
||||
| duration `v2.0.3` | 动画时长,单位秒 | *number \| string* | `0.3` |
|
||||
| round `v2.0.9` | 是否显示圆角 | *boolean* | `true` |
|
||||
| overlay | 是否显示遮罩层 | *boolean* | `true` |
|
||||
| lock-scroll | 是否锁定背景滚动 | *boolean* | `true` |
|
||||
| lazy-render | 是否在显示弹层时才渲染节点 | *boolean* | `true` |
|
||||
| close-on-popstate `v2.5.3` | 是否在页面回退时自动关闭 | *boolean* | `false` |
|
||||
| close-on-click-action | 是否在点击选项后关闭 | *boolean* | `false` |
|
||||
| close-on-click-overlay | 是否在点击遮罩层后关闭 | *boolean* | `true` |
|
||||
| safe-area-inset-bottom | 是否开启[底部安全区适配](#/zh-CN/quickstart#di-bu-an-quan-qu-gua-pei) | *boolean* | `true` |
|
||||
| get-container | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | *string \| () => Element* | - |
|
||||
| --- | --- | --- | --- |
|
||||
| v-model (value) | 是否显示动作面板 | _boolean_ | `false` |
|
||||
| actions | 面板选项列表 | _Action[]_ | `[]` |
|
||||
| title | 顶部标题 | _string_ | - |
|
||||
| cancel-text | 取消按钮文字 | _string_ | - |
|
||||
| description `v2.2.8` | 选项上方的描述信息 | _string_ | - |
|
||||
| close-icon `v2.2.13` | 关闭[图标名称](#/zh-CN/icon)或图片链接 | _string_ | `cross` |
|
||||
| duration `v2.0.3` | 动画时长,单位秒 | _number \| string_ | `0.3` |
|
||||
| round `v2.0.9` | 是否显示圆角 | _boolean_ | `true` |
|
||||
| overlay | 是否显示遮罩层 | _boolean_ | `true` |
|
||||
| lock-scroll | 是否锁定背景滚动 | _boolean_ | `true` |
|
||||
| lazy-render | 是否在显示弹层时才渲染节点 | _boolean_ | `true` |
|
||||
| close-on-popstate `v2.5.3` | 是否在页面回退时自动关闭 | _boolean_ | `false` |
|
||||
| close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `false` |
|
||||
| close-on-click-overlay | 是否在点击遮罩层后关闭 | _boolean_ | `true` |
|
||||
| safe-area-inset-bottom | 是否开启[底部安全区适配](#/zh-CN/quickstart#di-bu-an-quan-qu-gua-pei) | _boolean_ | `true` |
|
||||
| get-container | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | _string \| () => Element_ | - |
|
||||
|
||||
### Action 数据结构
|
||||
|
||||
`actions`属性为一个对象数组,数组中的每个对象配置一列,对象可以包含以下值:
|
||||
|
||||
| 键名 | 说明 | 类型 |
|
||||
|------|------|------|
|
||||
| name | 标题 | *string* |
|
||||
| subname | 二级标题 | *string* |
|
||||
| color | 选项文字颜色 | *string* |
|
||||
| className | 为对应列添加额外的 class | *any* |
|
||||
| loading | 是否为加载状态 | *boolean* |
|
||||
| disabled | 是否为禁用状态 | *boolean* |
|
||||
| 键名 | 说明 | 类型 |
|
||||
| --------- | ------------------------ | --------- |
|
||||
| name | 标题 | _string_ |
|
||||
| subname | 二级标题 | _string_ |
|
||||
| color | 选项文字颜色 | _string_ |
|
||||
| className | 为对应列添加额外的 class | _any_ |
|
||||
| loading | 是否为加载状态 | _boolean_ |
|
||||
| disabled | 是否为禁用状态 | _boolean_ |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
|------|------|------|
|
||||
| select | 选中选项时触发,禁用或加载状态下不会触发 | *action: Action, index: number* |
|
||||
| cancel | 取消按钮点击时触发 | - |
|
||||
| open | 打开菜单时触发 | - |
|
||||
| close | 关闭菜单时触发 | - |
|
||||
| opened | 打开菜单且动画结束后触发 | - |
|
||||
| closed | 关闭菜单且动画结束后触发 | - |
|
||||
| --- | --- | --- |
|
||||
| select | 点击选项时触发,禁用或加载状态下不会触发 | _action: Action, index: number_ |
|
||||
| cancel | 点击取消按钮时触发 | - |
|
||||
| open | 打开面板时触发 | - |
|
||||
| close | 关闭面板时触发 | - |
|
||||
| opened | 打开面板且动画结束后触发 | - |
|
||||
| closed | 关闭面板且动画结束后触发 | - |
|
||||
| click-overlay | 点击遮罩层时触发 | - |
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 引入时提示 dependencies not found?
|
||||
|
||||
在 1.x 版本中,上拉菜单的组件名为`Actionsheet`,从 2.0 版本开始更名为`ActionSheet`,请注意区分。
|
||||
在 1.x 版本中,动作面板的组件名为`Actionsheet`,从 2.0 版本开始更名为`ActionSheet`,请注意区分。
|
||||
|
@ -1,25 +1,25 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="$t('basicUsage')">
|
||||
<van-cell is-link :title="$t('basicUsage')" @click="show.basic = true" />
|
||||
<van-cell is-link :title="$t('showCancel')" @click="show.cancel = true" />
|
||||
<demo-block :title="t('basicUsage')">
|
||||
<van-cell is-link :title="t('basicUsage')" @click="show.basic = true" />
|
||||
<van-cell is-link :title="t('showCancel')" @click="show.cancel = true" />
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('showDescription')"
|
||||
:title="t('showDescription')"
|
||||
@click="show.description = true"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('optionStatus')">
|
||||
<demo-block :title="t('optionStatus')">
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('optionStatus')"
|
||||
:title="t('optionStatus')"
|
||||
@click="show.status = true"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('customPanel')">
|
||||
<van-cell is-link :title="$t('customPanel')" @click="show.title = true" />
|
||||
<demo-block :title="t('customPanel')">
|
||||
<van-cell is-link :title="t('customPanel')" @click="show.title = true" />
|
||||
</demo-block>
|
||||
|
||||
<van-action-sheet
|
||||
@ -32,14 +32,14 @@
|
||||
v-model="show.status"
|
||||
close-on-click-action
|
||||
:actions="statusActions"
|
||||
:cancel-text="$t('cancel')"
|
||||
:cancel-text="t('cancel')"
|
||||
/>
|
||||
|
||||
<van-action-sheet
|
||||
v-model="show.cancel"
|
||||
:actions="simpleActions"
|
||||
close-on-click-action
|
||||
:cancel-text="$t('cancel')"
|
||||
:cancel-text="t('cancel')"
|
||||
@cancel="onCancel"
|
||||
/>
|
||||
|
||||
@ -47,11 +47,11 @@
|
||||
v-model="show.description"
|
||||
:actions="simpleActions"
|
||||
close-on-click-action
|
||||
:description="$t('description')"
|
||||
:description="t('description')"
|
||||
/>
|
||||
|
||||
<van-action-sheet v-model="show.title" :title="$t('title')">
|
||||
<div class="demo-action-sheet-content">{{ $t('content') }}</div>
|
||||
<van-action-sheet v-model="show.title" :title="t('title')">
|
||||
<div class="demo-action-sheet-content">{{ t('content') }}</div>
|
||||
</van-action-sheet>
|
||||
</demo-section>
|
||||
</template>
|
||||
@ -98,17 +98,17 @@ export default {
|
||||
computed: {
|
||||
simpleActions() {
|
||||
return [
|
||||
{ name: this.$t('option') },
|
||||
{ name: this.$t('option') },
|
||||
{ name: this.$t('option'), subname: this.$t('subname') },
|
||||
{ name: this.t('option') },
|
||||
{ name: this.t('option') },
|
||||
{ name: this.t('option'), subname: this.t('subname') },
|
||||
];
|
||||
},
|
||||
|
||||
statusActions() {
|
||||
return [
|
||||
{ name: this.$t('option'), color: GREEN },
|
||||
{ name: this.t('option'), color: GREEN },
|
||||
{ loading: true },
|
||||
{ name: this.$t('disabledOption'), disabled: true },
|
||||
{ name: this.t('disabledOption'), disabled: true },
|
||||
];
|
||||
},
|
||||
},
|
||||
|
@ -53,7 +53,7 @@ export default createComponent({
|
||||
genSearchResult() {
|
||||
const { value, shouldShowSearchResult, searchResult } = this;
|
||||
if (shouldShowSearchResult) {
|
||||
return searchResult.map(express => (
|
||||
return searchResult.map((express) => (
|
||||
<Cell
|
||||
key={express.name + express.address}
|
||||
clickable
|
||||
|
@ -35,8 +35,8 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
areaList,
|
||||
searchResult: []
|
||||
}
|
||||
searchResult: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onSave() {
|
||||
@ -47,16 +47,18 @@ export default {
|
||||
},
|
||||
onChangeDetail(val) {
|
||||
if (val) {
|
||||
this.searchResult = [{
|
||||
name: '黄龙万科中心',
|
||||
address: '杭州市西湖区'
|
||||
}];
|
||||
this.searchResult = [
|
||||
{
|
||||
name: '黄龙万科中心',
|
||||
address: '杭州市西湖区',
|
||||
},
|
||||
];
|
||||
} else {
|
||||
this.searchResult = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
@ -64,76 +66,78 @@ export default {
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
| area-list | Area List | *object* | - |
|
||||
| area-columns-placeholder `v2.2.5` | placeholder of area columns | *string[]* | `[]` |
|
||||
| address-info | Address Info | *AddressInfo* | `{}` |
|
||||
| search-result | Address search result | *SearchResult[]* | `[]` |
|
||||
| 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` |
|
||||
| show-area | Whether to show area cell | *boolean* | `true` |
|
||||
| show-detail | Whether to show detail field | *boolean* | `true` |
|
||||
| disable-area `v2.5.0` | Whether to disable area select | *boolean* | `false` |
|
||||
| save-button-text | Save button text | *string* | `Save` |
|
||||
| delete-button-text | Delete button text | *string* | `Delete` |
|
||||
| detail-rows | Detail input rows | *number \| string* | `1` |
|
||||
| detail-maxlength `v2.0.4` | Detail maxlength | *number \| string* | `200` |
|
||||
| is-saving | Whether to show save button loading status | *boolean* | `false` |
|
||||
| is-deleting | Whether to show delete button loading status | *boolean* | `false` |
|
||||
| tel-validator | The method to validate tel | *(tel: string) => boolean* | - |
|
||||
| postal-validator `v2.1.2` | The method to validate postal | *(tel: string) => boolean* | - |
|
||||
| validator | Custom validator | *(key, val) => string* | - |
|
||||
| --- | --- | --- | --- |
|
||||
| area-list | Area List | _object_ | - |
|
||||
| area-columns-placeholder `v2.2.5` | placeholder of area columns | _string[]_ | `[]` |
|
||||
| area-placeholder `v2.6.1` | placeholder of area input field | _string_ | `Area` |
|
||||
| address-info | Address Info | _AddressInfo_ | `{}` |
|
||||
| search-result | Address search result | _SearchResult[]_ | `[]` |
|
||||
| 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` |
|
||||
| show-area | Whether to show area cell | _boolean_ | `true` |
|
||||
| show-detail | Whether to show detail field | _boolean_ | `true` |
|
||||
| disable-area `v2.5.0` | Whether to disable area select | _boolean_ | `false` |
|
||||
| save-button-text | Save button text | _string_ | `Save` |
|
||||
| delete-button-text | Delete button text | _string_ | `Delete` |
|
||||
| detail-rows | Detail input rows | _number \| string_ | `1` |
|
||||
| detail-maxlength `v2.0.4` | Detail maxlength | _number \| string_ | `200` |
|
||||
| is-saving | Whether to show save button loading status | _boolean_ | `false` |
|
||||
| is-deleting | Whether to show delete button loading status | _boolean_ | `false` |
|
||||
| tel-validator | The method to validate tel | _(tel: string) => boolean_ | - |
|
||||
| postal-validator `v2.1.2` | The method to validate postal | _(tel: string) => boolean_ | - |
|
||||
| validator | Custom validator | _(key, val) => string_ | - |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|------|------|------|
|
||||
| --- | --- | --- |
|
||||
| save | Triggered when click save button | content:form content |
|
||||
| focus | Triggered when focus field | key: field name |
|
||||
| delete | Triggered when confirm delete | content:form content |
|
||||
| cancel-delete | Triggered when cancel delete | content:form content |
|
||||
| select-search | Triggered when select search result | value: search content |
|
||||
| click-area `v2.5.9` | Triggered when click area | - |
|
||||
| change-area | Triggered when change area | values: area values |
|
||||
| change-detail | Triggered when address detail changed | value: address detail |
|
||||
| change-default | Triggered when switch default address | value: checked |
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
|------|------|
|
||||
| Name | Description |
|
||||
| ------- | --------------------------- |
|
||||
| default | Custom content below postal |
|
||||
|
||||
### Methods
|
||||
|
||||
Use [ref](https://vuejs.org/v2/api/#ref) to get AddressEdit instance and call instance methods
|
||||
|
||||
| Name | Description | Attribute | Return value |
|
||||
|------|------|------|------|
|
||||
| setAddressDetail | Set address detail | addressDetail: string | - |
|
||||
| Name | Description | Attribute | Return value |
|
||||
| ---------------- | ------------------ | --------------------- | ------------ |
|
||||
| setAddressDetail | Set address detail | addressDetail: string | - |
|
||||
|
||||
### AddressInfo Data Structure
|
||||
|
||||
| key | Description | Type |
|
||||
|------|------|------|
|
||||
| id | Address Id | *number \| string* |
|
||||
| name | Name | *string* |
|
||||
| tel | Phone | *string* |
|
||||
| province | Province | *string* |
|
||||
| city | City | *string* |
|
||||
| county | County | *string* |
|
||||
| addressDetail | Detailed Address | *string* |
|
||||
| areaCode | Area code | *string* |
|
||||
| postalCode | Postal code | *string* |
|
||||
| isDefault | Is default address | *boolean* |
|
||||
| key | Description | Type |
|
||||
| ------------- | ------------------ | ------------------ |
|
||||
| id | Address Id | _number \| string_ |
|
||||
| name | Name | _string_ |
|
||||
| tel | Phone | _string_ |
|
||||
| province | Province | _string_ |
|
||||
| city | City | _string_ |
|
||||
| county | County | _string_ |
|
||||
| addressDetail | Detailed Address | _string_ |
|
||||
| areaCode | Area code | _string_ |
|
||||
| postalCode | Postal code | _string_ |
|
||||
| isDefault | Is default address | _boolean_ |
|
||||
|
||||
### SearchResult Data Structure
|
||||
|
||||
| key | Description | Type |
|
||||
|------|------|------|
|
||||
| name | Name | *string* |
|
||||
| address | Address | *string* |
|
||||
| key | Description | Type |
|
||||
| ------- | ----------- | -------- |
|
||||
| name | Name | _string_ |
|
||||
| address | Address | _string_ |
|
||||
|
||||
### Area Data Structure
|
||||
|
||||
|
@ -35,8 +35,8 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
areaList,
|
||||
searchResult: []
|
||||
}
|
||||
searchResult: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onSave() {
|
||||
@ -47,16 +47,18 @@ export default {
|
||||
},
|
||||
onChangeDetail(val) {
|
||||
if (val) {
|
||||
this.searchResult = [{
|
||||
name: '黄龙万科中心',
|
||||
address: '杭州市西湖区'
|
||||
}];
|
||||
this.searchResult = [
|
||||
{
|
||||
name: '黄龙万科中心',
|
||||
address: '杭州市西湖区',
|
||||
},
|
||||
];
|
||||
} else {
|
||||
this.searchResult = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
@ -64,78 +66,80 @@ export default {
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------|------|------|------|
|
||||
| area-list | 地区列表 | *object* | - |
|
||||
| area-columns-placeholder `v2.2.5` | 地区选择列占位提示文字 | *string[]* | `[]` |
|
||||
| address-info | 收货人信息初始值 | *AddressInfo* | `{}` |
|
||||
| search-result | 详细地址搜索结果 | *SearchResult[]* | `[]` |
|
||||
| show-postal | 是否显示邮政编码 | *boolean* | `false` |
|
||||
| show-delete | 是否显示删除按钮 | *boolean* | `false` |
|
||||
| show-set-default | 是否显示默认地址栏 | *boolean* | `false` |
|
||||
| show-search-result | 是否显示搜索结果 | *boolean* | `false` |
|
||||
| show-area | 是否显示地区 | *boolean* | `true` |
|
||||
| show-detail | 是否显示详细地址 | *boolean* | `true` |
|
||||
| disable-area `v2.5.0` | 是否禁用地区选择 | *boolean* | `false` |
|
||||
| save-button-text | 保存按钮文字 | *string* | `保存` |
|
||||
| delete-button-text | 删除按钮文字 | *string* | `删除` |
|
||||
| detail-rows | 详细地址输入框行数 | *number \| string* | `1` |
|
||||
| detail-maxlength `v2.0.4` | 详细地址最大长度 | *number \| string* | `200` |
|
||||
| is-saving | 是否显示保存按钮加载动画 | *boolean* | `false` |
|
||||
| is-deleting | 是否显示删除按钮加载动画 | *boolean* | `false` |
|
||||
| tel-validator | 手机号格式校验函数 | *string => boolean* | - |
|
||||
| postal-validator `v2.1.2` | 邮政编码格式校验函数 | *string => boolean* | - |
|
||||
| validator | 自定义校验函数 | *(key, val) => string* | - |
|
||||
| --- | --- | --- | --- |
|
||||
| area-list | 地区列表 | _object_ | - |
|
||||
| area-columns-placeholder `v2.2.5` | 地区选择列占位提示文字 | _string[]_ | `[]` |
|
||||
| area-placeholder `v2.6.1` | 地区输入框占位提示文字 | _string_ | `选择省 / 市 / 区` |
|
||||
| address-info | 收货人信息初始值 | _AddressInfo_ | `{}` |
|
||||
| search-result | 详细地址搜索结果 | _SearchResult[]_ | `[]` |
|
||||
| show-postal | 是否显示邮政编码 | _boolean_ | `false` |
|
||||
| show-delete | 是否显示删除按钮 | _boolean_ | `false` |
|
||||
| show-set-default | 是否显示默认地址栏 | _boolean_ | `false` |
|
||||
| show-search-result | 是否显示搜索结果 | _boolean_ | `false` |
|
||||
| show-area | 是否显示地区 | _boolean_ | `true` |
|
||||
| show-detail | 是否显示详细地址 | _boolean_ | `true` |
|
||||
| disable-area `v2.5.0` | 是否禁用地区选择 | _boolean_ | `false` |
|
||||
| save-button-text | 保存按钮文字 | _string_ | `保存` |
|
||||
| delete-button-text | 删除按钮文字 | _string_ | `删除` |
|
||||
| detail-rows | 详细地址输入框行数 | _number \| string_ | `1` |
|
||||
| detail-maxlength `v2.0.4` | 详细地址最大长度 | _number \| string_ | `200` |
|
||||
| is-saving | 是否显示保存按钮加载动画 | _boolean_ | `false` |
|
||||
| is-deleting | 是否显示删除按钮加载动画 | _boolean_ | `false` |
|
||||
| tel-validator | 手机号格式校验函数 | _string => boolean_ | - |
|
||||
| postal-validator `v2.1.2` | 邮政编码格式校验函数 | _string => boolean_ | - |
|
||||
| validator | 自定义校验函数 | _(key, val) => string_ | - |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
|------|------|------|
|
||||
| --- | --- | --- |
|
||||
| save | 点击保存按钮时触发 | content:表单内容 |
|
||||
| focus | 输入框聚焦时触发 | key: 聚焦的输入框对应的 key |
|
||||
| delete | 确认删除地址时触发 | content:表单内容 |
|
||||
| cancel-delete | 取消删除地址时触发 | content:表单内容 |
|
||||
| select-search | 选中搜索结果时触发 | value: 搜索结果 |
|
||||
| click-area `v2.5.9` | 点击收件地区时触发 | - |
|
||||
| change-area | 修改收件地区时触发 | values: 地区信息 |
|
||||
| change-detail | 修改详细地址时触发 | value: 详细地址内容 |
|
||||
| change-default | 切换是否使用默认地址时触发 | value: 是否选中 |
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|------|------|
|
||||
| 名称 | 说明 |
|
||||
| ------- | ---------------------- |
|
||||
| default | 在邮政编码下方插入内容 |
|
||||
|
||||
### 方法
|
||||
|
||||
通过 ref 可以获取到 AddressEdit 实例并调用实例方法,详见[组件实例方法](#/zh-CN/quickstart#zu-jian-shi-li-fang-fa)
|
||||
|
||||
| 方法名 | 说明 | 参数 | 返回值 |
|
||||
|------|------|------|------|
|
||||
| setAddressDetail | 设置详细地址 | addressDetail: string | - |
|
||||
| 方法名 | 说明 | 参数 | 返回值 |
|
||||
| ---------------- | ------------ | --------------------- | ------ |
|
||||
| setAddressDetail | 设置详细地址 | addressDetail: string | - |
|
||||
|
||||
### AddressInfo 数据格式
|
||||
|
||||
注意:AddressInfo 仅作为初始值传入,表单最终内容可以在 save 事件中获取
|
||||
|
||||
| key | 说明 | 类型 |
|
||||
|------|------|------|
|
||||
| id | 每条地址的唯一标识 | *number \| string* |
|
||||
| name | 收货人姓名 | *string* |
|
||||
| tel | 收货人手机号 | *string* |
|
||||
| province | 省份 | *string* |
|
||||
| city | 城市 | *string* |
|
||||
| county | 区县 | *string* |
|
||||
| addressDetail | 详细地址 | *string* |
|
||||
| areaCode | 地区编码,通过`省市区选择`获取(必填) | *string* |
|
||||
| postalCode | 邮政编码 | *string* |
|
||||
| isDefault | 是否为默认地址 | *boolean* |
|
||||
| key | 说明 | 类型 |
|
||||
| ------------- | -------------------------------------- | ------------------ |
|
||||
| id | 每条地址的唯一标识 | _number \| string_ |
|
||||
| name | 收货人姓名 | _string_ |
|
||||
| tel | 收货人手机号 | _string_ |
|
||||
| province | 省份 | _string_ |
|
||||
| city | 城市 | _string_ |
|
||||
| county | 区县 | _string_ |
|
||||
| addressDetail | 详细地址 | _string_ |
|
||||
| areaCode | 地区编码,通过`省市区选择`获取(必填) | _string_ |
|
||||
| postalCode | 邮政编码 | _string_ |
|
||||
| isDefault | 是否为默认地址 | _boolean_ |
|
||||
|
||||
### SearchResult 数据格式
|
||||
|
||||
| key | 说明 | 类型 |
|
||||
|------|------|------|
|
||||
| name | 地名 | *string* |
|
||||
| address | 详细地址 | *string* |
|
||||
| key | 说明 | 类型 |
|
||||
| ------- | -------- | -------- |
|
||||
| name | 地名 | _string_ |
|
||||
| address | 详细地址 | _string_ |
|
||||
|
||||
### 省市县列表数据格式
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="$t('basicUsage')">
|
||||
<demo-block :title="t('basicUsage')">
|
||||
<van-address-edit
|
||||
:area-list="areaList"
|
||||
show-postal
|
||||
@ -8,7 +8,7 @@
|
||||
show-set-default
|
||||
show-search-result
|
||||
:search-result="searchResult"
|
||||
:area-columns-placeholder="$t('areaColumnsPlaceholder')"
|
||||
:area-columns-placeholder="t('areaColumnsPlaceholder')"
|
||||
@save="onSave"
|
||||
@delete="onDelete"
|
||||
@change-detail="onChangeDetail"
|
||||
@ -65,15 +65,15 @@ export default {
|
||||
|
||||
methods: {
|
||||
onSave() {
|
||||
this.$toast(this.$t('save'));
|
||||
this.$toast(this.t('save'));
|
||||
},
|
||||
|
||||
onDelete() {
|
||||
this.$toast(this.$t('delete'));
|
||||
this.$toast(this.t('delete'));
|
||||
},
|
||||
|
||||
onChangeDetail(val) {
|
||||
this.searchResult = val ? this.$t('searchResult') : [];
|
||||
this.searchResult = val ? this.t('searchResult') : [];
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -44,6 +44,7 @@ export default createComponent({
|
||||
showSearchResult: Boolean,
|
||||
saveButtonText: String,
|
||||
deleteButtonText: String,
|
||||
areaPlaceholder: String,
|
||||
showArea: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
@ -106,7 +107,7 @@ export default createComponent({
|
||||
if (province && province === city) {
|
||||
arr.splice(1, 1);
|
||||
}
|
||||
return arr.filter(text => text).join('/');
|
||||
return arr.filter((text) => text).join('/');
|
||||
}
|
||||
return '';
|
||||
},
|
||||
@ -144,9 +145,9 @@ export default createComponent({
|
||||
},
|
||||
|
||||
onAreaConfirm(values) {
|
||||
values = values.filter(value => !!value);
|
||||
values = values.filter((value) => !!value);
|
||||
|
||||
if (values.some(value => !value.code)) {
|
||||
if (values.some((value) => !value.code)) {
|
||||
Toast(t('areaEmpty'));
|
||||
return;
|
||||
}
|
||||
@ -168,13 +169,21 @@ export default createComponent({
|
||||
},
|
||||
|
||||
onSave() {
|
||||
const items = ['name', 'tel', 'areaCode', 'addressDetail'];
|
||||
const items = ['name', 'tel'];
|
||||
|
||||
if (this.showArea) {
|
||||
items.push('areaCode');
|
||||
}
|
||||
|
||||
if (this.showDetail) {
|
||||
items.push('addressDetail');
|
||||
}
|
||||
|
||||
if (this.showPostal) {
|
||||
items.push('postalCode');
|
||||
}
|
||||
|
||||
const isValid = items.every(item => {
|
||||
const isValid = items.every((item) => {
|
||||
const msg = this.getErrorMessage(item);
|
||||
if (msg) {
|
||||
this.errorInfo[item] = msg;
|
||||
@ -252,7 +261,7 @@ export default createComponent({
|
||||
|
||||
render() {
|
||||
const { data, errorInfo, searchResult, disableArea } = this;
|
||||
const onFocus = name => () => this.onFocus(name);
|
||||
const onFocus = (name) => () => this.onFocus(name);
|
||||
|
||||
// hide bottom field when use search && detail get focused
|
||||
const hideBottomFields =
|
||||
@ -283,12 +292,13 @@ export default createComponent({
|
||||
readonly
|
||||
clickable={!disableArea}
|
||||
label={t('area')}
|
||||
placeholder={t('areaPlaceholder')}
|
||||
placeholder={this.areaPlaceholder || t('areaPlaceholder')}
|
||||
errorMessage={errorInfo.areaCode}
|
||||
rightIcon={!disableArea ? 'arrow' : null}
|
||||
value={this.areaText}
|
||||
onFocus={onFocus('areaCode')}
|
||||
onClick={() => {
|
||||
this.$emit('click-area');
|
||||
this.showAreaPopup = !disableArea;
|
||||
}}
|
||||
/>
|
||||
@ -304,7 +314,7 @@ export default createComponent({
|
||||
onFocus={onFocus('addressDetail')}
|
||||
onBlur={this.onDetailBlur}
|
||||
onInput={this.onChangeDetail}
|
||||
onSelect-search={event => {
|
||||
onSelect-search={(event) => {
|
||||
this.$emit('select-search', event);
|
||||
}}
|
||||
/>
|
||||
@ -328,7 +338,7 @@ export default createComponent({
|
||||
vModel={data.isDefault}
|
||||
vShow={!hideBottomFields}
|
||||
title={t('defaultAddress')}
|
||||
onChange={event => {
|
||||
onChange={(event) => {
|
||||
this.$emit('change-default', event);
|
||||
}}
|
||||
/>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import AddressEdit from '..';
|
||||
import areaList from '../../area/demo/area.simple';
|
||||
import areaList from '../../area/demo/area-simple';
|
||||
import { mount, later } from '../../../test';
|
||||
|
||||
const addressInfo = {
|
||||
@ -123,7 +123,7 @@ test('valid name', () => {
|
||||
expect(errorInfo.name).toBeFalsy();
|
||||
});
|
||||
|
||||
it('valid tel', () => {
|
||||
test('valid tel', () => {
|
||||
const { data, field, button, errorInfo } = createComponent();
|
||||
data.tel = '';
|
||||
button.trigger('click');
|
||||
@ -132,7 +132,7 @@ it('valid tel', () => {
|
||||
expect(errorInfo.tel).toBeFalsy();
|
||||
});
|
||||
|
||||
it('valid areaCode', () => {
|
||||
test('valid areaCode', () => {
|
||||
const { data, button, errorInfo } = createComponent();
|
||||
// areaCode empty
|
||||
data.areaCode = '';
|
||||
@ -145,7 +145,7 @@ it('valid areaCode', () => {
|
||||
expect(errorInfo.areaCode).toBeTruthy();
|
||||
});
|
||||
|
||||
it('valid addressDetail', () => {
|
||||
test('valid addressDetail', () => {
|
||||
const { data, field, button, errorInfo } = createComponent();
|
||||
data.addressDetail = '';
|
||||
button.trigger('click');
|
||||
@ -294,3 +294,15 @@ test('select area', () => {
|
||||
wrapper.find('.van-picker__confirm').trigger('click');
|
||||
expect(data.areaCode).toEqual('110101');
|
||||
});
|
||||
|
||||
test('click-area event', () => {
|
||||
const wrapper = mount(AddressEdit, {
|
||||
propsData: {
|
||||
disableArea: true,
|
||||
},
|
||||
});
|
||||
|
||||
const field = wrapper.findAll('.van-field').at(2);
|
||||
field.trigger('click');
|
||||
expect(wrapper.emitted('click-area')[0]).toBeTruthy();
|
||||
});
|
||||
|
@ -37,24 +37,24 @@ export default {
|
||||
id: '1',
|
||||
name: 'John Snow',
|
||||
tel: '13000000000',
|
||||
address: 'Somewhere'
|
||||
address: 'Somewhere',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Ned Stark',
|
||||
tel: '1310000000',
|
||||
address: 'Somewhere'
|
||||
}
|
||||
address: 'Somewhere',
|
||||
},
|
||||
],
|
||||
disabledList: [
|
||||
{
|
||||
id: '3',
|
||||
name: 'Tywin',
|
||||
tel: '1320000000',
|
||||
address: 'Somewhere'
|
||||
}
|
||||
]
|
||||
}
|
||||
address: 'Somewhere',
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onAdd() {
|
||||
@ -62,9 +62,9 @@ export default {
|
||||
},
|
||||
onEdit(item, index) {
|
||||
Toast('Edit:' + index);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
@ -72,19 +72,19 @@ export default {
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
| v-model | Id of chosen address | *string* | - |
|
||||
| list | Address list | *Address[]* | `[]` |
|
||||
| disabled-list | Disabled address list | *Address[]* | `[]` |
|
||||
| disabled-text | Disabled text | *string* | - |
|
||||
| switchable | Whether to allow switch address | *boolean* | `true` |
|
||||
| add-button-text | Add button text | *string* | `Add new address` |
|
||||
| default-tag-text `v2.3.0` | Default tag text | *string* | - |
|
||||
| --- | --- | --- | --- |
|
||||
| v-model | Id of chosen address | _string_ | - |
|
||||
| list | Address list | _Address[]_ | `[]` |
|
||||
| disabled-list | Disabled address list | _Address[]_ | `[]` |
|
||||
| disabled-text | Disabled text | _string_ | - |
|
||||
| switchable | Whether to allow switch address | _boolean_ | `true` |
|
||||
| add-button-text | Add button text | _string_ | `Add new address` |
|
||||
| default-tag-text `v2.3.0` | Default tag text | _string_ | - |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|------|------|------|
|
||||
| --- | --- | --- |
|
||||
| add | Triggered when click add button | - |
|
||||
| edit | Triggered when edit address | item: address object,index |
|
||||
| select | Triggered when select address | item: address object,index |
|
||||
@ -94,18 +94,18 @@ export default {
|
||||
|
||||
### Data Structure of Address
|
||||
|
||||
| Key | Description | Type |
|
||||
|------|------|------|
|
||||
| id | Id | *number \| string* |
|
||||
| name | Name | *string* |
|
||||
| tel | Phone | *number \| string* |
|
||||
| address | Address | *string* |
|
||||
| isDefault | Is default address | *boolean* |
|
||||
| Key | Description | Type |
|
||||
| --------- | ------------------ | ------------------ |
|
||||
| id | Id | _number \| string_ |
|
||||
| name | Name | _string_ |
|
||||
| tel | Phone | _number \| string_ |
|
||||
| address | Address | _string_ |
|
||||
| isDefault | Is default address | _boolean_ |
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description | SlotProps |
|
||||
|------|------|------|
|
||||
| default | Custom content after list | - |
|
||||
| top | Custom content before list | - |
|
||||
| item-bottom `v2.5.0` | Custom content after list item | item |
|
||||
| Name | Description | SlotProps |
|
||||
| -------------------- | ------------------------------ | --------- |
|
||||
| default | Custom content after list | - |
|
||||
| top | Custom content before list | - |
|
||||
| item-bottom `v2.5.0` | Custom content after list item | item |
|
||||
|
@ -37,24 +37,24 @@ export default {
|
||||
id: '1',
|
||||
name: '张三',
|
||||
tel: '13000000000',
|
||||
address: '浙江省杭州市西湖区文三路 138 号东方通信大厦 7 楼 501 室'
|
||||
address: '浙江省杭州市西湖区文三路 138 号东方通信大厦 7 楼 501 室',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '李四',
|
||||
tel: '1310000000',
|
||||
address: '浙江省杭州市拱墅区莫干山路 50 号'
|
||||
}
|
||||
address: '浙江省杭州市拱墅区莫干山路 50 号',
|
||||
},
|
||||
],
|
||||
disabledList: [
|
||||
{
|
||||
id: '3',
|
||||
name: '王五',
|
||||
tel: '1320000000',
|
||||
address: '浙江省杭州市滨江区江南大道 15 号'
|
||||
}
|
||||
]
|
||||
}
|
||||
address: '浙江省杭州市滨江区江南大道 15 号',
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onAdd() {
|
||||
@ -62,50 +62,50 @@ export default {
|
||||
},
|
||||
onEdit(item, index) {
|
||||
Toast('编辑地址:' + index);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------|------|------|------|
|
||||
| v-model | 当前选中地址的 id | *string* | - |
|
||||
| list | 地址列表 | *Address[]* | `[]` |
|
||||
| disabled-list | 不可配送地址列表 | *Address[]* | `[]` |
|
||||
| disabled-text | 不可配送提示文案 | *string* | - |
|
||||
| switchable | 是否允许切换地址 | *boolean* | `true` |
|
||||
| add-button-text | 底部按钮文字 | *string* | `新增地址` |
|
||||
| default-tag-text `v2.3.0` | 默认地址标签文字 | *string* | - |
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| ------------------------- | ----------------- | ----------- | ---------- |
|
||||
| v-model | 当前选中地址的 id | _string_ | - |
|
||||
| list | 地址列表 | _Address[]_ | `[]` |
|
||||
| disabled-list | 不可配送地址列表 | _Address[]_ | `[]` |
|
||||
| disabled-text | 不可配送提示文案 | _string_ | - |
|
||||
| switchable | 是否允许切换地址 | _boolean_ | `true` |
|
||||
| add-button-text | 底部按钮文字 | _string_ | `新增地址` |
|
||||
| default-tag-text `v2.3.0` | 默认地址标签文字 | _string_ | - |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
|------|------|------|------|
|
||||
| add | 点击新增按钮时触发 | - |
|
||||
| edit | 点击编辑按钮时触发 | item: 地址对象,index: 索引 |
|
||||
| select | 切换选中的地址时触发 | item: 地址对象,index: 索引 |
|
||||
| edit-disabled | 编辑不可配送的地址时触发 | item: 地址对象,index: 索引 |
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
| --------------- | ------------------------ | --------------------------- |
|
||||
| add | 点击新增按钮时触发 | - |
|
||||
| edit | 点击编辑按钮时触发 | item: 地址对象,index: 索引 |
|
||||
| select | 切换选中的地址时触发 | item: 地址对象,index: 索引 |
|
||||
| edit-disabled | 编辑不可配送的地址时触发 | item: 地址对象,index: 索引 |
|
||||
| select-disabled | 选中不可配送的地址时触发 | item: 地址对象,index: 索引 |
|
||||
| click-item | 点击任意地址时触发 | item: 地址对象,index: 索引 |
|
||||
| click-item | 点击任意地址时触发 | item: 地址对象,index: 索引 |
|
||||
|
||||
### Address 数据结构
|
||||
|
||||
| 键名 | 说明 | 类型 |
|
||||
|------|------|------|
|
||||
| id | 每条地址的唯一标识 | *number \| string* |
|
||||
| name | 收货人姓名 | *string* |
|
||||
| tel | 收货人手机号 | *number \| string* |
|
||||
| address | 收货地址 | *string* |
|
||||
| isDefault | 是否为默认地址 | *boolean* |
|
||||
| 键名 | 说明 | 类型 |
|
||||
| --------- | ------------------ | ------------------ |
|
||||
| id | 每条地址的唯一标识 | _number \| string_ |
|
||||
| name | 收货人姓名 | _string_ |
|
||||
| tel | 收货人手机号 | _number \| string_ |
|
||||
| address | 收货地址 | _string_ |
|
||||
| isDefault | 是否为默认地址 | _boolean_ |
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 | SlotProps |
|
||||
|------|------|------|
|
||||
| default | 在列表下方插入内容 | - |
|
||||
| top | 在顶部插入内容 | - |
|
||||
| 名称 | 说明 | SlotProps |
|
||||
| -------------------- | -------------------- | ---------- |
|
||||
| default | 在列表下方插入内容 | - |
|
||||
| top | 在顶部插入内容 | - |
|
||||
| item-bottom `v2.5.0` | 在列表项底部插入内容 | 列表项的值 |
|
||||
|
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="$t('basicUsage')">
|
||||
<demo-block :title="t('basicUsage')">
|
||||
<van-address-list
|
||||
v-model="chosenAddressId"
|
||||
:list="$t('list')"
|
||||
:disabled-list="$t('disabledList')"
|
||||
:disabled-text="$t('disabledText')"
|
||||
:default-tag-text="$t('defaultTagText')"
|
||||
:list="t('list')"
|
||||
:disabled-list="t('disabledList')"
|
||||
:disabled-text="t('disabledText')"
|
||||
:default-tag-text="t('defaultTagText')"
|
||||
@add="onAdd"
|
||||
@edit="onEdit"
|
||||
/>
|
||||
@ -85,11 +85,11 @@ export default {
|
||||
|
||||
methods: {
|
||||
onAdd() {
|
||||
this.$toast(this.$t('add'));
|
||||
this.$toast(this.t('add'));
|
||||
},
|
||||
|
||||
onEdit(item, index) {
|
||||
this.$toast(`${this.$t('edit')}:${index}`);
|
||||
this.$toast(`${this.t('edit')}:${index}`);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -17,7 +17,7 @@ Vue.use(Area);
|
||||
|
||||
### Basic Usage
|
||||
|
||||
To initailize `Area` component, `area-list` property is required. Data structure will be introduced later.
|
||||
To initailize `Area` component, `area-list` property is required. Data structure will be introduced later.
|
||||
|
||||
```html
|
||||
<van-area :area-list="areaList" />
|
||||
@ -33,8 +33,7 @@ To have a selected value,simply pass the `code` of target area to `value` prop
|
||||
|
||||
### Columns Number
|
||||
|
||||
`columns-num` property is used to config number of columns to be displayed. This component has 3 columns corresponding to a 3 level picker by default.
|
||||
Set `columns-num` with 2, you'll have a 2 level picker.
|
||||
`columns-num` property is used to config number of columns to be displayed. This component has 3 columns corresponding to a 3 level picker by default. Set `columns-num` with 2, you'll have a 2 level picker.
|
||||
|
||||
```html
|
||||
<van-area :area-list="areaList" :columns-num="2" title="Title" />
|
||||
@ -57,48 +56,47 @@ Set `columns-num` with 2, you'll have a 2 level picker.
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
| value | the `code` of selected area | *string* | - |
|
||||
| title | Toolbar title | *string* | - |
|
||||
| confirm-button-text | Text of confirm button | *string* | `Confirm` |
|
||||
| cancel-button-text | Text of cancel button | *string* | `Cancel` |
|
||||
| area-list | Area list data | *object* | - |
|
||||
| columns-placeholder `v2.2.5` | Placeholder of columns | *string[]* | `[]` |
|
||||
| loading | Whether to show loading prompt | *boolean* | `false` |
|
||||
| item-height | Option height | *number \| string* | `44` |
|
||||
| columns-num | Level of picker | *number \| string* | `3` |
|
||||
| visible-item-count | Count of visible columns | *number \| string* | `5` |
|
||||
| swipe-duration `v2.2.13` | Duration of the momentum animation,unit `ms` | *number \| string* | `1000` |
|
||||
| is-oversea-code `v2.1.4` | The method to validate oversea code | *() => boolean* | - |
|
||||
| --- | --- | --- | --- |
|
||||
| value | the `code` of selected area | _string_ | - |
|
||||
| title | Toolbar title | _string_ | - |
|
||||
| confirm-button-text | Text of confirm button | _string_ | `Confirm` |
|
||||
| cancel-button-text | Text of cancel button | _string_ | `Cancel` |
|
||||
| area-list | Area list data | _object_ | - |
|
||||
| columns-placeholder `v2.2.5` | Placeholder of columns | _string[]_ | `[]` |
|
||||
| loading | Whether to show loading prompt | _boolean_ | `false` |
|
||||
| item-height | Option height | _number \| string_ | `44` |
|
||||
| columns-num | Level of picker | _number \| string_ | `3` |
|
||||
| visible-item-count | Count of visible columns | _number \| string_ | `5` |
|
||||
| swipe-duration `v2.2.13` | Duration of the momentum animation,unit `ms` | _number \| string_ | `1000` |
|
||||
| is-oversea-code `v2.1.4` | The method to validate oversea code | _() => boolean_ | - |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|------|------|------|
|
||||
| --- | --- | --- |
|
||||
| confirm | triggers when clicking the confirm button | an array |
|
||||
| cancel | triggers when clicking the cancel button | - |
|
||||
| change | Triggered when current option changed | Picker instance, current values,column index |
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
|------|------|
|
||||
| title `v2.5.3` | Custom title |
|
||||
| columns-top `v2.5.3` | Custom content above columns |
|
||||
| Name | Description |
|
||||
| ----------------------- | ---------------------------- |
|
||||
| title `v2.5.3` | Custom title |
|
||||
| columns-top `v2.5.3` | Custom content above columns |
|
||||
| columns-bottom `v2.5.3` | Custom content below columns |
|
||||
|
||||
### Methods
|
||||
|
||||
Use [ref](https://vuejs.org/v2/api/#ref) to get Area instance and call instance methods
|
||||
|
||||
| Name | Description | Attribute | Return value |
|
||||
|------|------|------|------|
|
||||
| reset | Reset all options by code | code?: string | - |
|
||||
| Name | Description | Attribute | Return value |
|
||||
| ----- | ------------------------- | ------------- | ------------ |
|
||||
| reset | Reset all options by code | code?: string | - |
|
||||
|
||||
### areaList Data Structure
|
||||
|
||||
An object contains three properties: `province_list`, `city_list` and `county_list`.
|
||||
Each property is a simple key-value object, key is a 6-bit code of the area of which first two bits stand for the province or state, middle two bits are used as city code and the last two are district code, value is the name of the area. If the code stands for an area that has sub-areas, lower bits of it will be filled with 0.
|
||||
An object contains three properties: `province_list`, `city_list` and `county_list`. Each property is a simple key-value object, key is a 6-bit code of the area of which first two bits stand for the province or state, middle two bits are used as city code and the last two are district code, value is the name of the area. If the code stands for an area that has sub-areas, lower bits of it will be filled with 0.
|
||||
|
||||
Example of `AreaList`
|
||||
|
||||
@ -131,15 +129,20 @@ All code of China: [Area.json](https://github.com/youzan/vant/blob/dev/src/area/
|
||||
An array contains selected area objects.
|
||||
|
||||
`code` - code of selected area, `name` - name of selected area
|
||||
|
||||
```js
|
||||
[{
|
||||
code: '330000',
|
||||
name: 'Zhejiang Province'
|
||||
}, {
|
||||
code: '330100',
|
||||
name: 'Hangzhou'
|
||||
},{
|
||||
code: '330105',
|
||||
name: 'Xihu District'
|
||||
}]
|
||||
[
|
||||
{
|
||||
code: '330000',
|
||||
name: 'Zhejiang Province',
|
||||
},
|
||||
{
|
||||
code: '330100',
|
||||
name: 'Hangzhou',
|
||||
},
|
||||
{
|
||||
code: '330105',
|
||||
name: 'Xihu District',
|
||||
},
|
||||
];
|
||||
```
|
||||
|
@ -56,34 +56,34 @@ Vue.use(Area);
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------|------|------|------|
|
||||
| value | 当前选中的省市区`code` | *string* | - |
|
||||
| title | 顶部栏标题 | *string* | - |
|
||||
| confirm-button-text | 确认按钮文字 | *string* | `确认` |
|
||||
| cancel-button-text | 取消按钮文字 | *string* | `取消` |
|
||||
| area-list | 省市区数据,格式见下方 | *object* | - |
|
||||
| columns-placeholder `v2.2.5` | 列占位提示文字 | *string[]* | `[]` |
|
||||
| loading | 是否显示加载状态 | *boolean* | `false` |
|
||||
| item-height | 选项高度 | *number \| string* | `44` |
|
||||
| columns-num | 显示列数,3-省市区,2-省市,1-省 | *number \| string* | `3` |
|
||||
| visible-item-count | 可见的选项个数 | *number \| string* | `5` |
|
||||
| swipe-duration `v2.2.13` | 快速滑动时惯性滚动的时长,单位`ms` | *number \| string* | `1000` |
|
||||
| is-oversea-code `v2.1.4` | 根据`code`校验海外地址,海外地址会划分至单独的分类 | *() => boolean* | - |
|
||||
| --- | --- | --- | --- |
|
||||
| value | 当前选中的省市区`code` | _string_ | - |
|
||||
| title | 顶部栏标题 | _string_ | - |
|
||||
| confirm-button-text | 确认按钮文字 | _string_ | `确认` |
|
||||
| cancel-button-text | 取消按钮文字 | _string_ | `取消` |
|
||||
| area-list | 省市区数据,格式见下方 | _object_ | - |
|
||||
| columns-placeholder `v2.2.5` | 列占位提示文字 | _string[]_ | `[]` |
|
||||
| loading | 是否显示加载状态 | _boolean_ | `false` |
|
||||
| item-height | 选项高度 | _number \| string_ | `44` |
|
||||
| columns-num | 显示列数,3-省市区,2-省市,1-省 | _number \| string_ | `3` |
|
||||
| visible-item-count | 可见的选项个数 | _number \| string_ | `5` |
|
||||
| swipe-duration `v2.2.13` | 快速滑动时惯性滚动的时长,单位`ms` | _number \| string_ | `1000` |
|
||||
| is-oversea-code `v2.1.4` | 根据`code`校验海外地址,海外地址会划分至单独的分类 | _() => boolean_ | - |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件 | 说明 | 回调参数 |
|
||||
| --- | --- | --- |
|
||||
| confirm | 点击右上方完成按钮 | 一个数组参数,具体格式看下方数据格式章节 |
|
||||
| cancel | 点击取消按钮时 | - |
|
||||
| change | 选项改变时触发 | Picker 实例,所有列选中值,当前列对应的索引 |
|
||||
| 事件 | 说明 | 回调参数 |
|
||||
| ------- | ------------------ | ------------------------------------------- |
|
||||
| confirm | 点击右上方完成按钮 | 一个数组参数,具体格式看下方数据格式章节 |
|
||||
| cancel | 点击取消按钮时 | - |
|
||||
| change | 选项改变时触发 | Picker 实例,所有列选中值,当前列对应的索引 |
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|------|------|
|
||||
| title `v2.5.3` | 自定义标题内容 |
|
||||
| columns-top `v2.5.3` | 自定义选项上方内容 |
|
||||
| 名称 | 说明 |
|
||||
| ----------------------- | ------------------ |
|
||||
| title `v2.5.3` | 自定义标题内容 |
|
||||
| columns-top `v2.5.3` | 自定义选项上方内容 |
|
||||
| columns-bottom `v2.5.3` | 自定义选项下方内容 |
|
||||
|
||||
### 方法
|
||||
@ -91,7 +91,7 @@ Vue.use(Area);
|
||||
通过 ref 可以获取到 Area 实例并调用实例方法,详见[组件实例方法](#/zh-CN/quickstart#zu-jian-shi-li-fang-fa)
|
||||
|
||||
| 方法名 | 说明 | 参数 | 返回值 |
|
||||
|------|------|------|------|
|
||||
| --- | --- | --- | --- |
|
||||
| reset | 根据 code 重置所有选项,若不传 code,则重置到第一项 | code?: string | - |
|
||||
|
||||
### 省市区列表数据格式
|
||||
@ -141,16 +141,16 @@ Vue.use(Area);
|
||||
[
|
||||
{
|
||||
code: '110000',
|
||||
name: '北京市'
|
||||
name: '北京市',
|
||||
},
|
||||
{
|
||||
code: '110100',
|
||||
name: '北京市'
|
||||
name: '北京市',
|
||||
},
|
||||
{
|
||||
code: '110101',
|
||||
name: '东城区'
|
||||
}
|
||||
name: '东城区',
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
|
@ -1,26 +1,26 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="$t('basicUsage')">
|
||||
<van-area :area-list="$t('areaList')" />
|
||||
<demo-block :title="t('basicUsage')">
|
||||
<van-area :area-list="t('areaList')" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('title2')">
|
||||
<van-area :area-list="$t('areaList')" :value="value" />
|
||||
<demo-block :title="t('title2')">
|
||||
<van-area :area-list="t('areaList')" :value="value" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('title3')">
|
||||
<demo-block :title="t('title3')">
|
||||
<van-area
|
||||
:area-list="$t('areaList')"
|
||||
:area-list="t('areaList')"
|
||||
:columns-num="2"
|
||||
:title="$t('title')"
|
||||
:title="t('title')"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('title4')">
|
||||
<demo-block :title="t('title4')">
|
||||
<van-area
|
||||
:area-list="$t('areaList')"
|
||||
:columns-placeholder="$t('columnsPlaceholder')"
|
||||
:title="$t('title')"
|
||||
:area-list="t('areaList')"
|
||||
:columns-placeholder="t('columnsPlaceholder')"
|
||||
:title="t('title')"
|
||||
/>
|
||||
</demo-block>
|
||||
</demo-section>
|
||||
|
@ -14,7 +14,7 @@ function pickSlots(instance, keys) {
|
||||
const { $slots, $scopedSlots } = instance;
|
||||
const scopedSlots = {};
|
||||
|
||||
keys.forEach(key => {
|
||||
keys.forEach((key) => {
|
||||
if ($scopedSlots[key]) {
|
||||
scopedSlots[key] = $scopedSlots[key];
|
||||
} else if ($slots[key]) {
|
||||
@ -111,7 +111,7 @@ export default createComponent({
|
||||
}
|
||||
|
||||
const list = this[type];
|
||||
result = Object.keys(list).map(listCode => ({
|
||||
result = Object.keys(list).map((listCode) => ({
|
||||
code: listCode,
|
||||
name: list[listCode],
|
||||
}));
|
||||
@ -122,7 +122,7 @@ export default createComponent({
|
||||
code = '9';
|
||||
}
|
||||
|
||||
result = result.filter(item => item.code.indexOf(code) === 0);
|
||||
result = result.filter((item) => item.code.indexOf(code) === 0);
|
||||
}
|
||||
|
||||
if (this.placeholderMap[type] && result.length) {
|
||||
@ -239,7 +239,9 @@ export default createComponent({
|
||||
|
||||
getValues() {
|
||||
const { picker } = this.$refs;
|
||||
let getValues = picker ? picker.getValues().filter(value => !!value) : [];
|
||||
let getValues = picker
|
||||
? picker.getValues().filter((value) => !!value)
|
||||
: [];
|
||||
getValues = this.parseOutputValues(getValues);
|
||||
return getValues;
|
||||
},
|
||||
@ -258,8 +260,8 @@ export default createComponent({
|
||||
return area;
|
||||
}
|
||||
|
||||
const names = values.map(item => item.name);
|
||||
const validValues = values.filter(value => !!value.code);
|
||||
const names = values.map((item) => item.name);
|
||||
const validValues = values.filter((value) => !!value.code);
|
||||
|
||||
area.code = validValues.length
|
||||
? validValues[validValues.length - 1].code
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Area from '..';
|
||||
import areaList from '../demo/area.simple';
|
||||
import areaList from '../demo/area-simple';
|
||||
import { mount, later, triggerDrag } from '../../../test';
|
||||
|
||||
const firstOption = [
|
||||
@ -70,17 +70,11 @@ test('change option', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
triggerDrag(columns.at(0), 0, -100);
|
||||
columns
|
||||
.at(0)
|
||||
.find('ul')
|
||||
.trigger('transitionend');
|
||||
columns.at(0).find('ul').trigger('transitionend');
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
triggerDrag(columns.at(2), 0, -100);
|
||||
columns
|
||||
.at(2)
|
||||
.find('ul')
|
||||
.trigger('transitionend');
|
||||
columns.at(2).find('ul').trigger('transitionend');
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
expect(onChange.mock.calls[0][1]).toEqual(secondOption);
|
||||
|
@ -44,7 +44,7 @@ Vue.use(Button);
|
||||
|
||||
### Loading
|
||||
|
||||
```html
|
||||
```html
|
||||
<van-button loading type="primary" />
|
||||
<van-button loading type="primary" loading-type="spinner" />
|
||||
<van-button loading type="info" loading-text="Loading..." />
|
||||
@ -52,22 +52,24 @@ Vue.use(Button);
|
||||
|
||||
### Shape
|
||||
|
||||
```html
|
||||
```html
|
||||
<van-button square type="primary">Square</van-button>
|
||||
<van-button round type="info">Round</van-button>
|
||||
```
|
||||
|
||||
### Icon
|
||||
|
||||
```html
|
||||
```html
|
||||
<van-button icon="star-o" type="primary" />
|
||||
<van-button icon="star-o" type="primary">Button</van-button>
|
||||
<van-button icon="https://img.yzcdn.cn/vant/logo.png" type="info">Button</van-button>
|
||||
<van-button icon="https://img.yzcdn.cn/vant/logo.png" type="info"
|
||||
>Button</van-button
|
||||
>
|
||||
```
|
||||
|
||||
### Size
|
||||
|
||||
```html
|
||||
```html
|
||||
<van-button type="primary" size="large">Large</van-button>
|
||||
<van-button type="primary" size="normal">Normal</van-button>
|
||||
<van-button type="primary" size="small">Small</van-button>
|
||||
@ -92,7 +94,9 @@ Vue.use(Button);
|
||||
```html
|
||||
<van-button color="#7232dd">Pure</van-button>
|
||||
<van-button color="#7232dd" plain>Pure</van-button>
|
||||
<van-button color="linear-gradient(to right, #4bb0ff, #6149f6)">Gradient</van-button>
|
||||
<van-button color="linear-gradient(to right, #4bb0ff, #6149f6)"
|
||||
>Gradient</van-button
|
||||
>
|
||||
```
|
||||
|
||||
## API
|
||||
@ -100,31 +104,31 @@ Vue.use(Button);
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
| type | Can be set to `primary` `info` `warning` `danger` | *string* | `default` |
|
||||
| size | Can be set to `large` `small` `mini` | *string* | `normal` |
|
||||
| text | Text | *string* | - |
|
||||
| color `v2.1.8` | Color, support linear-gradient | *string* | - |
|
||||
| icon | Left Icon | *string* | - |
|
||||
| icon-prefix `v2.5.3` | Icon className prefix | *string* | `van-icon` |
|
||||
| tag | HTML Tag | *string* | `button` |
|
||||
| native-type | Native Type Attribute | *string* | `''` |
|
||||
| plain | Whether to be plain button | *boolean* | `false` |
|
||||
| block | Whether to set display block | *boolean* | `false` |
|
||||
| round | Whether to be round button | *boolean* | `false` |
|
||||
| square | Whether to be square button | *boolean* | `false` |
|
||||
| disabled | Whether to disable button | *boolean* | `false` |
|
||||
| loading | Whether show loading status | *boolean* | `false` |
|
||||
| loading-text | Loading text | *string* | - |
|
||||
| loading-type | Loading type, can be set to `spinner` | *string* | `circular` |
|
||||
| loading-size | Loading icon size | *string* | `20px` |
|
||||
| url | Link URL | *string* | - |
|
||||
| to | Target route of the link, same as to of vue-router | *string \| object* | - |
|
||||
| replace | If true, the navigation will not leave a history record | *boolean* | `false` |
|
||||
| --- | --- | --- | --- |
|
||||
| type | Can be set to `primary` `info` `warning` `danger` | _string_ | `default` |
|
||||
| size | Can be set to `large` `small` `mini` | _string_ | `normal` |
|
||||
| text | Text | _string_ | - |
|
||||
| color `v2.1.8` | Color, support linear-gradient | _string_ | - |
|
||||
| icon | Left Icon | _string_ | - |
|
||||
| icon-prefix `v2.6.0` | Icon className prefix | _string_ | `van-icon` |
|
||||
| tag | HTML Tag | _string_ | `button` |
|
||||
| native-type | Native Type Attribute | _string_ | `''` |
|
||||
| plain | Whether to be plain button | _boolean_ | `false` |
|
||||
| block | Whether to set display block | _boolean_ | `false` |
|
||||
| round | Whether to be round button | _boolean_ | `false` |
|
||||
| square | Whether to be square button | _boolean_ | `false` |
|
||||
| disabled | Whether to disable button | _boolean_ | `false` |
|
||||
| loading | Whether show loading status | _boolean_ | `false` |
|
||||
| loading-text | Loading text | _string_ | - |
|
||||
| loading-type | Loading type, can be set to `spinner` | _string_ | `circular` |
|
||||
| loading-size | Loading icon size | _string_ | `20px` |
|
||||
| url | Link URL | _string_ | - |
|
||||
| to | Target route of the link, same as to of vue-router | _string \| object_ | - |
|
||||
| replace | If true, the navigation will not leave a history record | _boolean_ | `false` |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|------|------|------|
|
||||
| click | Triggered when click button and not disabled or loading | *event: Event* |
|
||||
| touchstart | Triggered when touch start | *event: TouchEvent* |
|
||||
| --- | --- | --- |
|
||||
| click | Triggered when click button and not disabled or loading | _event: Event_ |
|
||||
| touchstart | Triggered when touch start | _event: TouchEvent_ |
|
||||
|
@ -54,7 +54,7 @@ Vue.use(Button);
|
||||
|
||||
通过`loading`属性设置按钮为加载状态,加载状态下默认会隐藏按钮文字,可以通过`loading-text`设置加载状态下的文字
|
||||
|
||||
```html
|
||||
```html
|
||||
<van-button loading type="primary" />
|
||||
<van-button loading type="primary" loading-type="spinner" />
|
||||
<van-button loading type="info" loading-text="加载中..." />
|
||||
@ -64,7 +64,7 @@ Vue.use(Button);
|
||||
|
||||
通过`square`设置方形按钮,通过`round`设置圆形按钮
|
||||
|
||||
```html
|
||||
```html
|
||||
<van-button square type="primary">方形按钮</van-button>
|
||||
<van-button round type="info">圆形按钮</van-button>
|
||||
```
|
||||
@ -73,17 +73,19 @@ Vue.use(Button);
|
||||
|
||||
通过`icon`属性设置按钮图标,支持 Icon 组件里的所有图标,也可以传入图标 URL
|
||||
|
||||
```html
|
||||
```html
|
||||
<van-button icon="star-o" type="primary" />
|
||||
<van-button icon="star-o" type="primary">按钮</van-button>
|
||||
<van-button icon="https://img.yzcdn.cn/vant/logo.png" type="info">按钮</van-button>
|
||||
<van-button icon="https://img.yzcdn.cn/vant/logo.png" type="info"
|
||||
>按钮</van-button
|
||||
>
|
||||
```
|
||||
|
||||
### 按钮尺寸
|
||||
|
||||
支持`large`、`normal`、`small`、`mini`四种尺寸,默认为`normal`
|
||||
|
||||
```html
|
||||
```html
|
||||
<van-button type="primary" size="large">大号按钮</van-button>
|
||||
<van-button type="primary" size="normal">普通按钮</van-button>
|
||||
<van-button type="primary" size="small">小型按钮</van-button>
|
||||
@ -114,7 +116,9 @@ Vue.use(Button);
|
||||
```html
|
||||
<van-button color="#7232dd">单色按钮</van-button>
|
||||
<van-button color="#7232dd" plain>单色按钮</van-button>
|
||||
<van-button color="linear-gradient(to right, #4bb0ff, #6149f6)">渐变色按钮</van-button>
|
||||
<van-button color="linear-gradient(to right, #4bb0ff, #6149f6)"
|
||||
>渐变色按钮</van-button
|
||||
>
|
||||
```
|
||||
|
||||
## API
|
||||
@ -122,32 +126,32 @@ Vue.use(Button);
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------|------|------|------|
|
||||
| type | 类型,可选值为 `primary` `info` `warning` `danger` | *string* | `default` |
|
||||
| size | 尺寸,可选值为 `large` `small` `mini` | *string* | `normal` |
|
||||
| text | 按钮文字 | *string* | - |
|
||||
| color `v2.1.8` | 按钮颜色,支持传入`linear-gradient`渐变色 | *string* | - |
|
||||
| icon | 左侧[图标名称](#/zh-CN/icon)或图片链接 | *string* | - |
|
||||
| icon-prefix `v2.5.3` | 图标类名前缀,同 Icon 组件的 [class-prefix 属性](#/zh-CN/icon#props) | *string* | `van-icon` |
|
||||
| tag | 根节点的 HTML 标签 | *string* | `button` |
|
||||
| native-type | 原生 button 标签的 type 属性 | *string* | - |
|
||||
| block | 是否为块级元素 | *boolean* | `false` |
|
||||
| plain | 是否为朴素按钮 | *boolean* | `false` |
|
||||
| square | 是否为方形按钮 | *boolean* | `false` |
|
||||
| round | 是否为圆形按钮 | *boolean* | `false` |
|
||||
| disabled | 是否禁用按钮 | *boolean* | `false` |
|
||||
| hairline | 是否使用 0.5px 边框 | *boolean* | `false` |
|
||||
| loading | 是否显示为加载状态 | *boolean* | `false` |
|
||||
| loading-text | 加载状态提示文字 | *string* | - |
|
||||
| loading-type | [加载图标类型](#/zh-CN/loading),可选值为`spinner` | *string* | `circular` |
|
||||
| loading-size | 加载图标大小 | *string* | `20px` |
|
||||
| url | 点击后跳转的链接地址 | *string* | - |
|
||||
| to | 点击后跳转的目标路由对象,同 vue-router 的 [to 属性](https://router.vuejs.org/zh/api/#to) | *string \| object* | - |
|
||||
| replace | 是否在跳转时替换当前页面历史 | *boolean* | `false` |
|
||||
| --- | --- | --- | --- |
|
||||
| type | 类型,可选值为 `primary` `info` `warning` `danger` | _string_ | `default` |
|
||||
| size | 尺寸,可选值为 `large` `small` `mini` | _string_ | `normal` |
|
||||
| text | 按钮文字 | _string_ | - |
|
||||
| color `v2.1.8` | 按钮颜色,支持传入`linear-gradient`渐变色 | _string_ | - |
|
||||
| icon | 左侧[图标名称](#/zh-CN/icon)或图片链接 | _string_ | - |
|
||||
| icon-prefix `v2.6.0` | 图标类名前缀,同 Icon 组件的 [class-prefix 属性](#/zh-CN/icon#props) | _string_ | `van-icon` |
|
||||
| tag | 根节点的 HTML 标签 | _string_ | `button` |
|
||||
| native-type | 原生 button 标签的 type 属性 | _string_ | - |
|
||||
| block | 是否为块级元素 | _boolean_ | `false` |
|
||||
| plain | 是否为朴素按钮 | _boolean_ | `false` |
|
||||
| square | 是否为方形按钮 | _boolean_ | `false` |
|
||||
| round | 是否为圆形按钮 | _boolean_ | `false` |
|
||||
| disabled | 是否禁用按钮 | _boolean_ | `false` |
|
||||
| hairline | 是否使用 0.5px 边框 | _boolean_ | `false` |
|
||||
| loading | 是否显示为加载状态 | _boolean_ | `false` |
|
||||
| loading-text | 加载状态提示文字 | _string_ | - |
|
||||
| loading-type | [加载图标类型](#/zh-CN/loading),可选值为`spinner` | _string_ | `circular` |
|
||||
| loading-size | 加载图标大小 | _string_ | `20px` |
|
||||
| url | 点击后跳转的链接地址 | _string_ | - |
|
||||
| to | 点击后跳转的目标路由对象,同 vue-router 的 [to 属性](https://router.vuejs.org/zh/api/#to) | _string \| object_ | - |
|
||||
| replace | 是否在跳转时替换当前页面历史 | _boolean_ | `false` |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
|------|------|------|
|
||||
| click | 点击按钮,且按钮状态不为加载或禁用时触发 | *event: Event* |
|
||||
| touchstart | 开始触摸按钮时触发 | *event: TouchEvent* |
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
| ---------- | ---------------------------------------- | ------------------- |
|
||||
| click | 点击按钮,且按钮状态不为加载或禁用时触发 | _event: Event_ |
|
||||
| touchstart | 开始触摸按钮时触发 | _event: TouchEvent_ |
|
||||
|
@ -1,78 +1,78 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="$t('type')">
|
||||
<demo-block :title="t('type')">
|
||||
<div class="demo-button-row">
|
||||
<van-button type="default">{{ $t('default') }}</van-button>
|
||||
<van-button type="primary">{{ $t('primary') }}</van-button>
|
||||
<van-button type="info">{{ $t('info') }}</van-button>
|
||||
<van-button type="default">{{ t('default') }}</van-button>
|
||||
<van-button type="primary">{{ t('primary') }}</van-button>
|
||||
<van-button type="info">{{ t('info') }}</van-button>
|
||||
</div>
|
||||
<van-button type="danger">{{ $t('danger') }}</van-button>
|
||||
<van-button type="warning">{{ $t('warning') }}</van-button>
|
||||
<van-button type="danger">{{ t('danger') }}</van-button>
|
||||
<van-button type="warning">{{ t('warning') }}</van-button>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('plain')">
|
||||
<van-button plain type="primary" :text="$t('plain')" />
|
||||
<van-button plain type="info" :text="$t('plain')" />
|
||||
<demo-block :title="t('plain')">
|
||||
<van-button plain type="primary" :text="t('plain')" />
|
||||
<van-button plain type="info" :text="t('plain')" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('hairline')">
|
||||
<van-button plain hairline type="primary" :text="$t('hairlineButton')" />
|
||||
<van-button plain hairline type="info" :text="$t('hairlineButton')" />
|
||||
<demo-block :title="t('hairline')">
|
||||
<van-button plain hairline type="primary" :text="t('hairlineButton')" />
|
||||
<van-button plain hairline type="info" :text="t('hairlineButton')" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('disabled')">
|
||||
<van-button disabled type="primary" :text="$t('disabled')" />
|
||||
<van-button disabled type="info" :text="$t('disabled')" />
|
||||
<demo-block :title="t('disabled')">
|
||||
<van-button disabled type="primary" :text="t('disabled')" />
|
||||
<van-button disabled type="info" :text="t('disabled')" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('loadingStatus')">
|
||||
<demo-block :title="t('loadingStatus')">
|
||||
<van-button loading type="primary" />
|
||||
<van-button loading type="primary" loading-type="spinner" />
|
||||
<van-button loading :loading-text="$t('loadingText')" type="info" />
|
||||
<van-button loading :loading-text="t('loadingText')" type="info" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('shape')">
|
||||
<van-button type="primary" square :text="$t('square')" />
|
||||
<van-button type="info" round :text="$t('round')" />
|
||||
<demo-block :title="t('shape')">
|
||||
<van-button type="primary" square :text="t('square')" />
|
||||
<van-button type="info" round :text="t('round')" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('icon')">
|
||||
<demo-block :title="t('icon')">
|
||||
<van-button type="primary" icon="star-o" />
|
||||
<van-button type="primary" icon="star-o" :text="$t('button')" />
|
||||
<van-button type="primary" icon="star-o" :text="t('button')" />
|
||||
<van-button
|
||||
plain
|
||||
type="primary"
|
||||
icon="https://img.yzcdn.cn/vant/logo.png"
|
||||
:text="$t('button')"
|
||||
:text="t('button')"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('size')">
|
||||
<van-button type="primary" size="large">{{ $t('large') }}</van-button>
|
||||
<van-button type="primary" size="normal">{{ $t('normal') }}</van-button>
|
||||
<van-button type="primary" size="small">{{ $t('small') }}</van-button>
|
||||
<van-button type="primary" size="mini">{{ $t('mini') }}</van-button>
|
||||
<demo-block :title="t('size')">
|
||||
<van-button type="primary" size="large">{{ t('large') }}</van-button>
|
||||
<van-button type="primary" size="normal">{{ t('normal') }}</van-button>
|
||||
<van-button type="primary" size="small">{{ t('small') }}</van-button>
|
||||
<van-button type="primary" size="mini">{{ t('mini') }}</van-button>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('blockElement')">
|
||||
<van-button type="primary" block>{{ $t('blockElement') }}</van-button>
|
||||
<demo-block :title="t('blockElement')">
|
||||
<van-button type="primary" block>{{ t('blockElement') }}</van-button>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('router')">
|
||||
<demo-block v-if="!isWeapp" :title="t('router')">
|
||||
<van-button
|
||||
:text="$t('urlRoute')"
|
||||
:text="t('urlRoute')"
|
||||
type="primary"
|
||||
url="/vant/mobile.html"
|
||||
/>
|
||||
<van-button :text="$t('vueRoute')" type="primary" to="index" />
|
||||
<van-button :text="t('vueRoute')" type="primary" to="index" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('customColor')">
|
||||
<van-button color="#7232dd" :text="$t('pure')" />
|
||||
<van-button plain color="#7232dd" :text="$t('pure')" />
|
||||
<demo-block :title="t('customColor')">
|
||||
<van-button color="#7232dd" :text="t('pure')" />
|
||||
<van-button plain color="#7232dd" :text="t('pure')" />
|
||||
<van-button
|
||||
color="linear-gradient(to right, #4bb0ff, #6149f6)"
|
||||
:text="$t('gradient')"
|
||||
:text="t('gradient')"
|
||||
/>
|
||||
</demo-block>
|
||||
</demo-section>
|
||||
|
@ -166,6 +166,7 @@ Button.props = {
|
||||
loading: Boolean,
|
||||
hairline: Boolean,
|
||||
disabled: Boolean,
|
||||
iconPrefix: String,
|
||||
nativeType: String,
|
||||
loadingText: String,
|
||||
loadingType: String,
|
||||
|
@ -1,6 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`loading size 1`] = `
|
||||
exports[`icon-prefix prop 1`] = `
|
||||
<button class="van-button van-button--default van-button--normal"><i class="my-icon my-icon-success van-button__icon">
|
||||
<!----></i></button>
|
||||
`;
|
||||
|
||||
exports[`loading-size prop 1`] = `
|
||||
<button class="van-button van-button--default van-button--normal van-button--loading">
|
||||
<div class="van-loading van-loading--circular van-button__loading"><span class="van-loading__spinner van-loading__spinner--circular" style="color: currentColor; width: 10px; height: 10px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
|
||||
</button>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { mount } from '../../../test';
|
||||
import Button from '..';
|
||||
|
||||
test('loading size', () => {
|
||||
test('loading-size prop', () => {
|
||||
const wrapper = mount(Button, {
|
||||
propsData: {
|
||||
loading: true,
|
||||
@ -82,3 +82,14 @@ test('hide border when color is gradient', () => {
|
||||
|
||||
expect(wrapper.element.style.border).toEqual('0px');
|
||||
});
|
||||
|
||||
test('icon-prefix prop', () => {
|
||||
const wrapper = mount(Button, {
|
||||
propsData: {
|
||||
icon: 'success',
|
||||
iconPrefix: 'my-icon',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
@ -29,7 +29,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
date: '',
|
||||
show: false
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@ -39,14 +39,38 @@ export default {
|
||||
onConfirm(date) {
|
||||
this.show = false;
|
||||
this.date = this.formatDate(date);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Select Multiple Date
|
||||
|
||||
```html
|
||||
<van-cell title="Select Multiple Date" :value="text" @click="show = true" />
|
||||
<van-calendar v-model="show" type="multiple" @confirm="onConfirm" />
|
||||
```
|
||||
|
||||
```js
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
text: '',
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onConfirm(date) {
|
||||
this.show = false;
|
||||
this.text = `${date.length} dates selected`;
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Select Date Range
|
||||
|
||||
You can select a date range after setting `type` to` range`. In range mode, the date returned by the `confirm` event is an array, the first item in the array is the start time and the second item is the end time.
|
||||
You can select a date range after setting `type` to`range`. In range mode, the date returned by the `confirm` event is an array, the first item in the array is the start time and the second item is the end time.
|
||||
|
||||
```html
|
||||
<van-cell title="Select Date Range" :value="date" @click="show = true" />
|
||||
@ -58,7 +82,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
date: '',
|
||||
show: false
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@ -69,14 +93,14 @@ export default {
|
||||
const [start, end] = date;
|
||||
this.show = false;
|
||||
this.date = `${this.formatDate(start)} - ${this.formatDate(end)}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Quick Select
|
||||
|
||||
Set `show-confirm` to` false` to hide the confirm button. In this case, the `confirm` event will be triggered immediately after the selection is completed.
|
||||
Set `show-confirm` to `false` to hide the confirm button. In this case, the `confirm` event will be triggered immediately after the selection is completed.
|
||||
|
||||
```html
|
||||
<van-calendar v-model="show" :show-confirm="false" />
|
||||
@ -95,11 +119,7 @@ Use `color` prop to custom calendar color
|
||||
Use `min-date` and `max-date` to custom date range
|
||||
|
||||
```html
|
||||
<van-calendar
|
||||
v-model="show"
|
||||
:min-date="minDate"
|
||||
:max-date="maxDate"
|
||||
/>
|
||||
<van-calendar v-model="show" :min-date="minDate" :max-date="maxDate" />
|
||||
```
|
||||
|
||||
```js
|
||||
@ -108,9 +128,9 @@ export default {
|
||||
return {
|
||||
show: false,
|
||||
minDate: new Date(2010, 0, 1),
|
||||
maxDate: new Date(2010, 0, 31)
|
||||
maxDate: new Date(2010, 0, 31),
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@ -132,11 +152,7 @@ Use `confirm-text` and `confirm-disabled-text` to custom confirm text
|
||||
Use `formatter` to custom day text
|
||||
|
||||
```html
|
||||
<van-calendar
|
||||
v-model="show"
|
||||
type="range"
|
||||
:formatter="formatter"
|
||||
/>
|
||||
<van-calendar v-model="show" type="range" :formatter="formatter" />
|
||||
```
|
||||
|
||||
```js
|
||||
@ -163,9 +179,9 @@ export default {
|
||||
}
|
||||
|
||||
return day;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Position
|
||||
@ -173,11 +189,7 @@ export default {
|
||||
Use `position` to custom popup position,can be set to `top`、`left`、`right`
|
||||
|
||||
```html
|
||||
<van-calendar
|
||||
v-model="show"
|
||||
:round="false"
|
||||
position="right"
|
||||
/>
|
||||
<van-calendar v-model="show" :round="false" position="right" />
|
||||
```
|
||||
|
||||
### Max Range
|
||||
@ -185,11 +197,7 @@ Use `position` to custom popup position,can be set to `top`、`left`、`right`
|
||||
When selecting a date range, you can use the `max-range` prop to specify the maximum number of selectable days
|
||||
|
||||
```html
|
||||
<van-calendar
|
||||
type="range"
|
||||
:max-range="3"
|
||||
:style="{ height: '500px' }"
|
||||
/>
|
||||
<van-calendar type="range" :max-range="3" :style="{ height: '500px' }" />
|
||||
```
|
||||
|
||||
### Tiled display
|
||||
@ -210,47 +218,64 @@ Set `poppable` to `false`, the calendar will be displayed directly on the page i
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
| v-model | Whether to show calendar | *boolean* | `false` |
|
||||
| type | Type,can be set to `single` `range` | *string* | `single` |
|
||||
| title | Title of calendar | *string* | `Calendar` |
|
||||
| color | Color for the bottom button and selected date | *string* | `#ee0a24` |
|
||||
| min-date | Min date | *Date* | Today |
|
||||
| max-date | Max date | *Date* | Six months after the today |
|
||||
| default-date | Default selected date | *Date \| Date[]* | Today |
|
||||
| row-height | Row height | *number \| string* | `64` |
|
||||
| formatter | Day formatter | *(day: Day) => Day* | - |
|
||||
| position | Popup position, can be set to `top` `right` `left` | *string* | `bottom` |
|
||||
| poppable | Whether to show the calendar inside a popup | *boolean* | `true` |
|
||||
| round | Whether to show round corner | *boolean* | `true` |
|
||||
| show-mark | Whether to show background month mark | *boolean* | `true` |
|
||||
| show-confirm | Whether to show confirm button | *boolean* | `true` |
|
||||
| close-on-popstate `v2.4.4` | Whether to close when popstate | *boolean* | `false` |
|
||||
| close-on-click-overlay | Whether to close when click overlay | *boolean* | `true` |
|
||||
| safe-area-inset-bottom | Whether to enable bottom safe area adaptation | *boolean* | `true` |
|
||||
| confirm-text | Confirm button text | *string* | `Confirm` |
|
||||
| confirm-disabled-text | Confirm button text when disabled | *string* | `Confirm` |
|
||||
| max-range `v2.4.3` | Number of selectable days | *number \| string* | - |
|
||||
| range-prompt `v2.4.3` | Error message when exceeded max range | *string* | `Choose no more than xx days` |
|
||||
| --- | --- | --- | --- |
|
||||
| type `v2.5.4` | Type,can be set to `range` `multiple` | _string_ | `single` |
|
||||
| title | Title of calendar | _string_ | `Calendar` |
|
||||
| color | Color for the bottom button and selected date | _string_ | `#ee0a24` |
|
||||
| min-date | Min date | _Date_ | Today |
|
||||
| max-date | Max date | _Date_ | Six months after the today |
|
||||
| default-date | Default selected date | _Date \| Date[]_ | Today |
|
||||
| row-height | Row height | _number \| string_ | `64` |
|
||||
| formatter | Day formatter | _(day: Day) => Day_ | - |
|
||||
| poppable | Whether to show the calendar inside a popup | _boolean_ | `true` |
|
||||
| show-mark | Whether to show background month mark | _boolean_ | `true` |
|
||||
| show-title `v2.5.5` | Whether to show title | _boolean_ | `true` |
|
||||
| show-subtitle `v2.5.5` | Whether to show subtitle | _boolean_ | `true` |
|
||||
| show-confirm | Whether to show confirm button | _boolean_ | `true` |
|
||||
| confirm-text | Confirm button text | _string_ | `Confirm` |
|
||||
| confirm-disabled-text | Confirm button text when disabled | _string_ | `Confirm` |
|
||||
|
||||
### Poppable Props
|
||||
|
||||
Following props are supported when the poppable is true
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| v-model | Whether to show calendar | _boolean_ | `false` |
|
||||
| position | Popup position, can be set to `top` `right` `left` | _string_ | `bottom` |
|
||||
| round | Whether to show round corner | _boolean_ | `true` |
|
||||
| close-on-popstate `v2.4.4` | Whether to close when popstate | _boolean_ | `false` |
|
||||
| close-on-click-overlay | Whether to close when click overlay | _boolean_ | `true` |
|
||||
| safe-area-inset-bottom | Whether to enable bottom safe area adaptation | _boolean_ | `true` |
|
||||
| get-container `v2.4.4` | Return the mount node for Calendar | _string \| () => Element_ | - |
|
||||
|
||||
### Range Props
|
||||
|
||||
Following props are supported when the type is range
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| max-range `v2.4.3` | Number of selectable days | _number \| string_ | - |
|
||||
| range-prompt `v2.4.3` | Error message when exceeded max range | _string_ | `Choose no more than xx days` |
|
||||
| allow-same-day `v2.5.6` | Whether the start and end time of the range is allowed on the same day | _boolean_ | `fasle` |
|
||||
|
||||
### Data Structure of Day
|
||||
|
||||
| Key | Description | Type |
|
||||
|------|------|------|
|
||||
| date | Date | *Date* |
|
||||
| type | Type, can be set to `selected`、`start`、`middle`、`end`、`disabled` | *string* |
|
||||
| text | Text | *string* |
|
||||
| topInfo | Top info | *string* |
|
||||
| bottomInfo | Bottom info | *string* |
|
||||
| className | Extra className | *string* |
|
||||
| --- | --- | --- |
|
||||
| date | Date | _Date_ |
|
||||
| type | Type, can be set to `selected`、`start`、`middle`、`end`、`disabled` | _string_ |
|
||||
| text | Text | _string_ |
|
||||
| topInfo | Top info | _string_ |
|
||||
| bottomInfo | Bottom info | _string_ |
|
||||
| className | Extra className | _string_ |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|------|------|------|
|
||||
| select | Triggered when select date | *value: Date \| Date[]* |
|
||||
| confirm | Triggered after date selection is complete,if `show-confirm` is` true`, it is triggered after clicking the confirm button | *value: Date \| Date[]* |
|
||||
| --- | --- | --- |
|
||||
| select | Triggered when select date | _value: Date \| Date[]_ |
|
||||
| confirm | Triggered after date selection is complete,if `show-confirm` is`true`, it is triggered after clicking the confirm button | _value: Date \| Date[]_ |
|
||||
| open `v2.5.2` | Triggered when open Popup | - |
|
||||
| close `v2.5.2` | Triggered when close Popup | - |
|
||||
| opened `v2.5.2` | Triggered when opened Popup | - |
|
||||
@ -258,15 +283,15 @@ Set `poppable` to `false`, the calendar will be displayed directly on the page i
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
|------|------|
|
||||
| title | Custom title |
|
||||
| Name | Description |
|
||||
| ------ | ------------- |
|
||||
| title | Custom title |
|
||||
| footer | Custom fotter |
|
||||
|
||||
### Methods
|
||||
|
||||
Use [ref](https://vuejs.org/v2/api/#ref) to get Calendar instance and call instance methods
|
||||
|
||||
| Name | Description | Attribute | Return value |
|
||||
|------|------|------|------|
|
||||
| reset | Reset selected date to default date | - | - |
|
||||
| Name | Description | Attribute | Return value |
|
||||
| ----- | ----------------------------------- | --------- | ------------ |
|
||||
| reset | Reset selected date to default date | - | - |
|
||||
|
@ -29,7 +29,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
date: '',
|
||||
show: false
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@ -39,8 +39,34 @@ export default {
|
||||
onConfirm(date) {
|
||||
this.show = false;
|
||||
this.date = this.formatDate(date);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 选择多个日期
|
||||
|
||||
设置`type`为`multiple`后可以选择多个日期,此时`confirm`事件返回的 date 为数组结构,数组包含若干个选中的日期。
|
||||
|
||||
```html
|
||||
<van-cell title="选择多个日期" :value="text" @click="show = true" />
|
||||
<van-calendar v-model="show" type="multiple" @confirm="onConfirm" />
|
||||
```
|
||||
|
||||
```js
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
text: '',
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onConfirm(date) {
|
||||
this.show = false;
|
||||
this.text = `选择了 ${date.length} 个日期`;
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@ -58,7 +84,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
date: '',
|
||||
show: false
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@ -69,8 +95,8 @@ export default {
|
||||
const [start, end] = date;
|
||||
this.show = false;
|
||||
this.date = `${this.formatDate(start)} - ${this.formatDate(end)}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@ -95,11 +121,7 @@ export default {
|
||||
通过`min-date`和`max-date`定义日历的范围
|
||||
|
||||
```html
|
||||
<van-calendar
|
||||
v-model="show"
|
||||
:min-date="minDate"
|
||||
:max-date="maxDate"
|
||||
/>
|
||||
<van-calendar v-model="show" :min-date="minDate" :max-date="maxDate" />
|
||||
```
|
||||
|
||||
```js
|
||||
@ -108,9 +130,9 @@ export default {
|
||||
return {
|
||||
show: false,
|
||||
minDate: new Date(2010, 0, 1),
|
||||
maxDate: new Date(2010, 0, 31)
|
||||
maxDate: new Date(2010, 0, 31),
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@ -132,11 +154,7 @@ export default {
|
||||
通过传入`formatter`函数来对日历上每一格的内容进行格式化
|
||||
|
||||
```html
|
||||
<van-calendar
|
||||
v-model="show"
|
||||
type="range"
|
||||
:formatter="formatter"
|
||||
/>
|
||||
<van-calendar v-model="show" type="range" :formatter="formatter" />
|
||||
```
|
||||
|
||||
```js
|
||||
@ -150,7 +168,7 @@ export default {
|
||||
if (date === 1) {
|
||||
day.topInfo = '劳动节';
|
||||
} else if (date === 4) {
|
||||
day.topInfo = '五四青年节';
|
||||
day.topInfo = '青年节';
|
||||
} else if (date === 11) {
|
||||
day.text = '今天';
|
||||
}
|
||||
@ -163,9 +181,9 @@ export default {
|
||||
}
|
||||
|
||||
return day;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 自定义弹出位置
|
||||
@ -173,11 +191,7 @@ export default {
|
||||
通过`position`属性自定义弹出层的弹出位置,可选值为`top`、`left`、`right`
|
||||
|
||||
```html
|
||||
<van-calendar
|
||||
v-model="show"
|
||||
:round="false"
|
||||
position="right"
|
||||
/>
|
||||
<van-calendar v-model="show" :round="false" position="right" />
|
||||
```
|
||||
|
||||
### 日期区间最大范围
|
||||
@ -185,11 +199,7 @@ export default {
|
||||
选择日期区间时,可以通过`max-range`属性来指定最多可选天数,选择的范围超过最多可选天数时,会弹出相应的提示文案
|
||||
|
||||
```html
|
||||
<van-calendar
|
||||
type="range"
|
||||
:max-range="3"
|
||||
:style="{ height: '500px' }"
|
||||
/>
|
||||
<van-calendar type="range" :max-range="3" :style="{ height: '500px' }" />
|
||||
```
|
||||
|
||||
### 平铺展示
|
||||
@ -210,49 +220,66 @@ export default {
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|------|------|------|------|
|
||||
| v-model | 是否显示日历弹窗 | *boolean* | `false` |
|
||||
| type | 选择类型,`single`表示选择单个日期,<br>`range`表示选择日期区间 | *string* | `single` |
|
||||
| title | 日历标题 | *string* | `日期选择` |
|
||||
| color | 颜色,对底部按钮和选中日期生效 | *string* | `#ee0a24` |
|
||||
| min-date | 最小日期 | *Date* | 当前日期 |
|
||||
| max-date | 最大日期 | *Date* | 当前日期的六个月后 |
|
||||
| default-date | 默认选中的日期 | *Date \| Date[]* | 今天 |
|
||||
| row-height | 日期行高 | *number \| string* | `64` |
|
||||
| formatter | 日期格式化函数 | *(day: Day) => Day* | - |
|
||||
| position | 弹出位置,可选值为 `top` `right` `left` | *string* | `bottom` |
|
||||
| poppable | 是否以弹层的形式展示日历 | *boolean* | `true` |
|
||||
| round | 是否显示圆角弹窗 | *boolean* | `true` |
|
||||
| show-mark | 是否显示月份背景水印 | *boolean* | `true` |
|
||||
| show-confirm | 是否展示确认按钮 | *boolean* | `true` |
|
||||
| close-on-popstate `v2.4.4` | 是否在页面回退时自动关闭 | *boolean* | `false` |
|
||||
| close-on-click-overlay | 是否在点击遮罩层后关闭 | *boolean* | `true` |
|
||||
| safe-area-inset-bottom | 是否开启[底部安全区适配](#/zh-CN/quickstart#di-bu-an-quan-qu-gua-pei) | *boolean* | `true` |
|
||||
| confirm-text | 确认按钮的文字 | *string* | `确定` |
|
||||
| confirm-disabled-text | 确认按钮处于禁用状态时的文字 | *string* | `确定` |
|
||||
| max-range `v2.4.3` | 日期区间最多可选天数,默认无限制 | *number \| string* | - |
|
||||
| range-prompt `v2.4.3` | 选择超过区间范围时的提示文案 | *string* | `选择天数不能超过 xx 天` |
|
||||
| get-container `v2.4.4` | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | *string \| () => Element* | - |
|
||||
| --- | --- | --- | --- |
|
||||
| type `v2.5.4` | 选择类型:<br>`single`表示选择单个日期,<br>`multiple`表示选择多个日期,<br>`range`表示选择日期区间 | _string_ | `single` |
|
||||
| title | 日历标题 | _string_ | `日期选择` |
|
||||
| color | 主题色,对底部按钮和选中日期生效 | _string_ | `#ee0a24` |
|
||||
| min-date | 可选择的最小日期 | _Date_ | 当前日期 |
|
||||
| max-date | 可选择的最大日期 | _Date_ | 当前日期的六个月后 |
|
||||
| default-date | 默认选中的日期,`type`为`multiple`或`range`时为数组 | _Date \| Date[]_ | 今天 |
|
||||
| row-height | 日期行高 | _number \| string_ | `64` |
|
||||
| formatter | 日期格式化函数 | _(day: Day) => Day_ | - |
|
||||
| poppable | 是否以弹层的形式展示日历 | _boolean_ | `true` |
|
||||
| show-mark | 是否显示月份背景水印 | _boolean_ | `true` |
|
||||
| show-title `v2.5.5` | 是否展示日历标题 | _boolean_ | `true` |
|
||||
| show-subtitle `v2.5.5` | 是否展示日历副标题(年月) | _boolean_ | `true` |
|
||||
| show-confirm | 是否展示确认按钮 | _boolean_ | `true` |
|
||||
| confirm-text | 确认按钮的文字 | _string_ | `确定` |
|
||||
| confirm-disabled-text | 确认按钮处于禁用状态时的文字 | _string_ | `确定` |
|
||||
|
||||
### Poppable Props
|
||||
|
||||
当 Canlendar 的 `poppable` 为 `true` 时,支持以下 props:
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| v-model | 是否显示日历弹窗 | _boolean_ | `false` |
|
||||
| position | 弹出位置,可选值为 `top` `right` `left` | _string_ | `bottom` |
|
||||
| round | 是否显示圆角弹窗 | _boolean_ | `true` |
|
||||
| close-on-popstate `v2.4.4` | 是否在页面回退时自动关闭 | _boolean_ | `false` |
|
||||
| close-on-click-overlay | 是否在点击遮罩层后关闭 | _boolean_ | `true` |
|
||||
| safe-area-inset-bottom | 是否开启[底部安全区适配](#/zh-CN/quickstart#di-bu-an-quan-qu-gua-pei) | _boolean_ | `true` |
|
||||
| get-container `v2.4.4` | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | _string \| () => Element_ | - |
|
||||
|
||||
### Range Props
|
||||
|
||||
当 Canlendar 的 `type` 为 `range` 时,支持以下 props:
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| max-range `v2.4.3` | 日期区间最多可选天数,默认无限制 | _number \| string_ | - |
|
||||
| range-prompt `v2.4.3` | 范围选择超过最多可选天数时的提示文案 | _string_ | `选择天数不能超过 xx 天` |
|
||||
| allow-same-day `v2.5.6` | 是否允许日期范围的起止时间为同一天 | _boolean_ | `fasle` |
|
||||
|
||||
### Day 数据结构
|
||||
|
||||
日历中的每个日期都对应一个 Day 对象,通过`formatter`属性可以自定义 Day 对象的内容
|
||||
|
||||
| 键名 | 说明 | 类型 |
|
||||
|------|------|------|
|
||||
| date | 日期对应的 Date 对象 | *Date* |
|
||||
| type | 日期类型,可选值为`selected`、`start`、`middle`、`end`、`disabled` | *string* |
|
||||
| text | 中间显示的文字 | *string* |
|
||||
| topInfo | 上方的提示信息 | *string* |
|
||||
| bottomInfo | 下方的提示信息 | *string* |
|
||||
| className | 额外类名 | *string* |
|
||||
| --- | --- | --- |
|
||||
| date | 日期对应的 Date 对象 | _Date_ |
|
||||
| type | 日期类型,可选值为`selected`、`start`、`middle`、`end`、`disabled` | _string_ |
|
||||
| text | 中间显示的文字 | _string_ |
|
||||
| topInfo | 上方的提示信息 | _string_ |
|
||||
| bottomInfo | 下方的提示信息 | _string_ |
|
||||
| className | 额外类名 | _string_ |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
|------|------|------|
|
||||
| select | 点击任意日期时触发 | *value: Date \| Date[]* |
|
||||
| confirm | 日期选择完成后触发,若`show-confirm`为`true`,则点击确认按钮后触发 | *value: Date \| Date[]* |
|
||||
| --- | --- | --- |
|
||||
| select | 点击任意日期时触发 | _value: Date \| Date[]_ |
|
||||
| confirm | 日期选择完成后触发,若`show-confirm`为`true`,则点击确认按钮后触发 | _value: Date \| Date[]_ |
|
||||
| open `v2.5.2` | 打开弹出层时触发 | - |
|
||||
| close `v2.5.2` | 关闭弹出层时触发 | - |
|
||||
| opened `v2.5.2` | 打开弹出层且动画结束后触发 | - |
|
||||
@ -260,18 +287,18 @@ export default {
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|------|------|
|
||||
| title | 自定义标题 |
|
||||
| 名称 | 说明 |
|
||||
| ------ | ------------------ |
|
||||
| title | 自定义标题 |
|
||||
| footer | 自定义底部区域内容 |
|
||||
|
||||
### 方法
|
||||
|
||||
通过 ref 可以获取到 Calendar 实例并调用实例方法,详见[组件实例方法](#/zh-CN/quickstart#zu-jian-shi-li-fang-fa)
|
||||
|
||||
| 方法名 | 说明 | 参数 | 返回值 |
|
||||
|------|------|------|------|
|
||||
| reset | 重置选中的日期到默认值 | - | - |
|
||||
| 方法名 | 说明 | 参数 | 返回值 |
|
||||
| ------ | ---------------------- | ---- | ------ |
|
||||
| reset | 重置选中的日期到默认值 | - | - |
|
||||
|
||||
## 常见问题
|
||||
|
||||
|
@ -6,17 +6,23 @@ const [createComponent] = createNamespace('calendar-header');
|
||||
export default createComponent({
|
||||
props: {
|
||||
title: String,
|
||||
monthTitle: String,
|
||||
subtitle: String,
|
||||
showTitle: Boolean,
|
||||
showSubtitle: Boolean,
|
||||
},
|
||||
|
||||
methods: {
|
||||
genTitle() {
|
||||
const title = this.slots('title') || this.title || t('title');
|
||||
return <div class={bem('header-title')}>{title}</div>;
|
||||
if (this.showTitle) {
|
||||
const title = this.slots('title') || this.title || t('title');
|
||||
return <div class={bem('header-title')}>{title}</div>;
|
||||
}
|
||||
},
|
||||
|
||||
genMonth() {
|
||||
return <div class={bem('month-title')}>{this.monthTitle}</div>;
|
||||
genSubtitle() {
|
||||
if (this.showSubtitle) {
|
||||
return <div class={bem('header-subtitle')}>{this.subtitle}</div>;
|
||||
}
|
||||
},
|
||||
|
||||
genWeekDays() {
|
||||
@ -24,7 +30,7 @@ export default createComponent({
|
||||
|
||||
return (
|
||||
<div class={bem('weekdays')}>
|
||||
{weekdays.map(item => (
|
||||
{weekdays.map((item) => (
|
||||
<span class={bem('weekday')}>{item}</span>
|
||||
))}
|
||||
</div>
|
||||
@ -36,7 +42,7 @@ export default createComponent({
|
||||
return (
|
||||
<div class={bem('header')}>
|
||||
{this.genTitle()}
|
||||
{this.genMonth()}
|
||||
{this.genSubtitle()}
|
||||
{this.genWeekDays()}
|
||||
</div>
|
||||
);
|
||||
|
@ -1,5 +1,13 @@
|
||||
import { createNamespace } from '../../utils';
|
||||
import { t, bem, compareDay, formatMonthTitle, ROW_HEIGHT } from '../utils';
|
||||
import {
|
||||
t,
|
||||
bem,
|
||||
compareDay,
|
||||
ROW_HEIGHT,
|
||||
getPrevDay,
|
||||
getNextDay,
|
||||
formatMonthTitle,
|
||||
} from '../utils';
|
||||
import { getMonthEndDay } from '../../datetime-picker/utils';
|
||||
|
||||
const [createComponent] = createNamespace('calendar-month');
|
||||
@ -12,10 +20,12 @@ export default createComponent({
|
||||
minDate: Date,
|
||||
maxDate: Date,
|
||||
showMark: Boolean,
|
||||
showTitle: Boolean,
|
||||
rowHeight: [Number, String],
|
||||
formatter: Function,
|
||||
currentDate: [Date, Array],
|
||||
allowSameDay: Boolean,
|
||||
showSubtitle: Boolean,
|
||||
showMonthTitle: Boolean,
|
||||
},
|
||||
|
||||
data() {
|
||||
@ -81,7 +91,67 @@ export default createComponent({
|
||||
|
||||
methods: {
|
||||
scrollIntoView() {
|
||||
this.$refs.days.scrollIntoView();
|
||||
if (this.showSubtitle) {
|
||||
this.$refs.days.scrollIntoView();
|
||||
} else {
|
||||
this.$refs.month.scrollIntoView();
|
||||
}
|
||||
},
|
||||
|
||||
getMultipleDayType(day) {
|
||||
const isSelected = (date) =>
|
||||
this.currentDate.some((item) => compareDay(item, date) === 0);
|
||||
|
||||
if (isSelected(day)) {
|
||||
const prevDay = getPrevDay(day);
|
||||
const nextDay = getNextDay(day);
|
||||
const prevSelected = isSelected(prevDay);
|
||||
const nextSelected = isSelected(nextDay);
|
||||
|
||||
if (prevSelected && nextSelected) {
|
||||
return 'multiple-middle';
|
||||
}
|
||||
|
||||
if (prevSelected) {
|
||||
return 'end';
|
||||
}
|
||||
|
||||
return nextSelected ? 'start' : 'multiple-selected';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
|
||||
getRangeDayType(day) {
|
||||
const [startDay, endDay] = this.currentDate;
|
||||
|
||||
if (!startDay) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const compareToStart = compareDay(day, startDay);
|
||||
|
||||
if (!endDay) {
|
||||
return compareToStart === 0 ? 'start' : '';
|
||||
}
|
||||
|
||||
const compareToEnd = compareDay(day, endDay);
|
||||
|
||||
if (compareToStart === 0 && compareToEnd === 0 && this.allowSameDay) {
|
||||
return 'start-end';
|
||||
}
|
||||
|
||||
if (compareToStart === 0) {
|
||||
return 'start';
|
||||
}
|
||||
|
||||
if (compareToEnd === 0) {
|
||||
return 'end';
|
||||
}
|
||||
|
||||
if (compareToStart > 0 && compareToEnd < 0) {
|
||||
return 'middle';
|
||||
}
|
||||
},
|
||||
|
||||
getDayType(day) {
|
||||
@ -95,41 +165,24 @@ export default createComponent({
|
||||
return compareDay(day, currentDate) === 0 ? 'selected' : '';
|
||||
}
|
||||
|
||||
if (type === 'multiple') {
|
||||
return this.getMultipleDayType(day);
|
||||
}
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (type === 'range') {
|
||||
const [startDay, endDay] = this.currentDate;
|
||||
|
||||
if (!startDay) {
|
||||
return;
|
||||
}
|
||||
|
||||
const compareToStart = compareDay(day, startDay);
|
||||
if (compareToStart === 0) {
|
||||
return 'start';
|
||||
}
|
||||
|
||||
if (!endDay) {
|
||||
return;
|
||||
}
|
||||
|
||||
const compareToEnd = compareDay(day, endDay);
|
||||
if (compareToEnd === 0) {
|
||||
return 'end';
|
||||
}
|
||||
|
||||
if (compareToStart > 0 && compareToEnd < 0) {
|
||||
return 'middle';
|
||||
}
|
||||
return this.getRangeDayType(day);
|
||||
}
|
||||
},
|
||||
|
||||
getBottomInfo(type) {
|
||||
if (type === 'start') {
|
||||
return t('start');
|
||||
}
|
||||
|
||||
if (type === 'end') {
|
||||
return t('end');
|
||||
if (this.type === 'range') {
|
||||
if (type === 'start' || type === 'end') {
|
||||
return t(type);
|
||||
}
|
||||
if (type === 'start-end') {
|
||||
return t('startEnd');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -145,7 +198,12 @@ export default createComponent({
|
||||
}
|
||||
|
||||
if (this.color) {
|
||||
if (type === 'start' || type === 'end') {
|
||||
if (
|
||||
type === 'start' ||
|
||||
type === 'end' ||
|
||||
type === 'multiple-selected' ||
|
||||
type === 'multiple-middle'
|
||||
) {
|
||||
style.background = this.color;
|
||||
} else if (type === 'middle') {
|
||||
style.color = this.color;
|
||||
@ -156,7 +214,7 @@ export default createComponent({
|
||||
},
|
||||
|
||||
genTitle() {
|
||||
if (this.showTitle) {
|
||||
if (this.showMonthTitle) {
|
||||
return <div class={bem('month-title')}>{this.title}</div>;
|
||||
}
|
||||
},
|
||||
@ -203,7 +261,7 @@ export default createComponent({
|
||||
role="gridcell"
|
||||
style={style}
|
||||
class={[bem('day'), item.className]}
|
||||
tabindex={disabled ? null : -1}
|
||||
tabindex={-1}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div class={bem('selected-day')} style={{ background: this.color }}>
|
||||
@ -233,7 +291,7 @@ export default createComponent({
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div class={bem('month')} style={this.monthStyle}>
|
||||
<div class={bem('month')} ref="month" style={this.monthStyle}>
|
||||
{this.genTitle()}
|
||||
{this.genDays()}
|
||||
</div>
|
||||
|
@ -1,88 +1,96 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="$t('basicUsage')">
|
||||
<demo-block :title="t('basicUsage')">
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('selectSingle')"
|
||||
:title="t('selectSingle')"
|
||||
:value="formatFullDate(date.selectSingle)"
|
||||
@click="show('single', 'selectSingle')"
|
||||
/>
|
||||
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('selectRange')"
|
||||
:title="t('selectMultiple')"
|
||||
:value="formatMultiple(date.selectMultiple)"
|
||||
@click="show('multiple', 'selectMultiple')"
|
||||
/>
|
||||
|
||||
<van-cell
|
||||
is-link
|
||||
:title="t('selectRange')"
|
||||
:value="formatRange(date.selectRange)"
|
||||
@click="show('range', 'selectRange')"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('quickSelect')">
|
||||
<demo-block :title="t('quickSelect')">
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('selectSingle')"
|
||||
:title="t('selectSingle')"
|
||||
:value="formatFullDate(date.quickSelect1)"
|
||||
@click="show('single', 'quickSelect1')"
|
||||
/>
|
||||
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('selectRange')"
|
||||
:title="t('selectRange')"
|
||||
:value="formatRange(date.quickSelect2)"
|
||||
@click="show('range', 'quickSelect2')"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('customCalendar')">
|
||||
<demo-block :title="t('customCalendar')">
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('customColor')"
|
||||
:title="t('customColor')"
|
||||
:value="formatRange(date.customColor)"
|
||||
@click="show('range', 'customColor')"
|
||||
/>
|
||||
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('customRange')"
|
||||
:title="t('customRange')"
|
||||
:value="formatFullDate(date.customRange)"
|
||||
@click="show('single', 'customRange')"
|
||||
/>
|
||||
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('customConfirm')"
|
||||
:title="t('customConfirm')"
|
||||
:value="formatRange(date.customConfirm)"
|
||||
@click="show('range', 'customConfirm')"
|
||||
/>
|
||||
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('customDayText')"
|
||||
:title="t('customDayText')"
|
||||
:value="formatRange(date.customDayText)"
|
||||
@click="show('range', 'customDayText')"
|
||||
/>
|
||||
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('customPosition')"
|
||||
:title="t('customPosition')"
|
||||
:value="formatFullDate(date.customPosition)"
|
||||
@click="show('single', 'customPosition')"
|
||||
/>
|
||||
|
||||
<van-cell
|
||||
is-link
|
||||
:title="$t('maxRange')"
|
||||
:title="t('maxRange')"
|
||||
:value="formatRange(date.maxRange)"
|
||||
@click="show('range', 'maxRange')"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('tiledDisplay')">
|
||||
<demo-block :title="t('tiledDisplay')">
|
||||
<van-calendar
|
||||
:title="$t('calendar')"
|
||||
:title="t('calendar')"
|
||||
:poppable="false"
|
||||
:show-confirm="false"
|
||||
:min-date="tiledMinDate"
|
||||
:max-date="tiledMaxDate"
|
||||
:default-date="tiledMinDate"
|
||||
:style="{ height: '500px' }"
|
||||
/>
|
||||
</demo-block>
|
||||
@ -115,10 +123,12 @@ export default {
|
||||
out: '离店',
|
||||
today: '今天',
|
||||
laborDay: '劳动节',
|
||||
youthDay: '五四青年节',
|
||||
youthDay: '青年节',
|
||||
calendar: '日历',
|
||||
maxRange: '日期区间最大范围',
|
||||
selectCount: (count) => `选择了 ${count} 个日期`,
|
||||
selectSingle: '选择单个日期',
|
||||
selectMultiple: '选择多个日期',
|
||||
selectRange: '选择日期区间',
|
||||
quickSelect: '快捷选择',
|
||||
confirmText: '完成',
|
||||
@ -139,7 +149,9 @@ export default {
|
||||
youthDay: 'Youth Day',
|
||||
calendar: 'Calendar',
|
||||
maxRange: 'Max Range',
|
||||
selectCount: (count) => `${count} dates selected`,
|
||||
selectSingle: 'Select Single Date',
|
||||
selectMultiple: 'Select Multiple Date',
|
||||
selectRange: 'Select Date Range',
|
||||
quickSelect: 'Quick Select',
|
||||
confirmText: 'OK',
|
||||
@ -160,6 +172,7 @@ export default {
|
||||
maxRange: [],
|
||||
selectSingle: null,
|
||||
selectRange: [],
|
||||
selectMultiple: [],
|
||||
quickSelect1: null,
|
||||
quickSelect2: [],
|
||||
customColor: [],
|
||||
@ -214,8 +227,8 @@ export default {
|
||||
this.color = GREEN;
|
||||
break;
|
||||
case 'customConfirm':
|
||||
this.confirmText = this.$t('confirmText');
|
||||
this.confirmDisabledText = this.$t('confirmDisabledText');
|
||||
this.confirmText = this.t('confirmText');
|
||||
this.confirmDisabledText = this.t('confirmDisabledText');
|
||||
break;
|
||||
case 'customRange':
|
||||
this.minDate = new Date(2010, 0, 1);
|
||||
@ -242,18 +255,18 @@ export default {
|
||||
|
||||
if (month === 5) {
|
||||
if (date === 1) {
|
||||
day.topInfo = this.$t('laborDay');
|
||||
day.topInfo = this.t('laborDay');
|
||||
} else if (date === 4) {
|
||||
day.topInfo = this.$t('youthDay');
|
||||
day.topInfo = this.t('youthDay');
|
||||
} else if (date === 11) {
|
||||
day.text = this.$t('today');
|
||||
day.text = this.t('today');
|
||||
}
|
||||
}
|
||||
|
||||
if (day.type === 'start') {
|
||||
day.bottomInfo = this.$t('in');
|
||||
day.bottomInfo = this.t('in');
|
||||
} else if (day.type === 'end') {
|
||||
day.bottomInfo = this.$t('out');
|
||||
day.bottomInfo = this.t('out');
|
||||
}
|
||||
|
||||
return day;
|
||||
@ -271,6 +284,12 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
formatMultiple(dates) {
|
||||
if (dates.length) {
|
||||
return this.t('selectCount', dates.length);
|
||||
}
|
||||
},
|
||||
|
||||
formatRange(dateRange) {
|
||||
if (dateRange.length) {
|
||||
const [start, end] = dateRange;
|
||||
|
@ -4,12 +4,14 @@ import { getScrollTop } from '../utils/dom/scroll';
|
||||
import {
|
||||
t,
|
||||
bem,
|
||||
copyDates,
|
||||
getNextDay,
|
||||
compareDay,
|
||||
ROW_HEIGHT,
|
||||
calcDateNum,
|
||||
compareMonth,
|
||||
createComponent,
|
||||
calcDateNum,
|
||||
ROW_HEIGHT,
|
||||
getDayByOffset,
|
||||
} from './utils';
|
||||
|
||||
// Components
|
||||
@ -29,6 +31,7 @@ export default createComponent({
|
||||
rangePrompt: String,
|
||||
defaultDate: [Date, Array],
|
||||
getContainer: [String, Function],
|
||||
allowSameDay: Boolean,
|
||||
closeOnPopstate: Boolean,
|
||||
confirmDisabledText: String,
|
||||
type: {
|
||||
@ -68,10 +71,18 @@ export default createComponent({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showTitle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showConfirm: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showSubtitle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
@ -88,16 +99,12 @@ export default createComponent({
|
||||
|
||||
data() {
|
||||
return {
|
||||
monthTitle: '',
|
||||
subtitle: '',
|
||||
currentDate: this.getInitialDate(),
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
range() {
|
||||
return this.type === 'range';
|
||||
},
|
||||
|
||||
months() {
|
||||
const months = [];
|
||||
const cursor = new Date(this.minDate);
|
||||
@ -113,23 +120,23 @@ export default createComponent({
|
||||
},
|
||||
|
||||
buttonDisabled() {
|
||||
if (this.range) {
|
||||
return !this.currentDate[0] || !this.currentDate[1];
|
||||
const { type, currentDate } = this;
|
||||
|
||||
if (type === 'range') {
|
||||
return !currentDate[0] || !currentDate[1];
|
||||
}
|
||||
|
||||
return !this.currentDate;
|
||||
if (type === 'multiple') {
|
||||
return !currentDate.length;
|
||||
}
|
||||
|
||||
return !currentDate;
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
type: 'reset',
|
||||
|
||||
value(val) {
|
||||
if (val) {
|
||||
this.initRect();
|
||||
this.scrollIntoView();
|
||||
}
|
||||
},
|
||||
value: 'init',
|
||||
|
||||
defaultDate(val) {
|
||||
this.currentDate = val;
|
||||
@ -138,9 +145,12 @@ export default createComponent({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.value || !this.poppable) {
|
||||
this.initRect();
|
||||
}
|
||||
this.init();
|
||||
},
|
||||
|
||||
/* istanbul ignore next */
|
||||
activated() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
methods: {
|
||||
@ -150,7 +160,11 @@ export default createComponent({
|
||||
this.scrollIntoView();
|
||||
},
|
||||
|
||||
initRect() {
|
||||
init() {
|
||||
if (this.poppable && !this.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
// add Math.floor to avoid decimal height issues
|
||||
// https://github.com/youzan/vant/issues/5640
|
||||
@ -159,13 +173,15 @@ export default createComponent({
|
||||
);
|
||||
this.onScroll();
|
||||
});
|
||||
this.scrollIntoView();
|
||||
},
|
||||
|
||||
// scroll to current month
|
||||
scrollIntoView() {
|
||||
this.$nextTick(() => {
|
||||
const { currentDate } = this;
|
||||
const targetDate = this.range ? currentDate[0] : currentDate;
|
||||
const targetDate =
|
||||
this.type === 'single' ? currentDate : currentDate[0];
|
||||
const displayed = this.value || !this.poppable;
|
||||
|
||||
/* istanbul ignore if */
|
||||
@ -185,14 +201,26 @@ export default createComponent({
|
||||
},
|
||||
|
||||
getInitialDate() {
|
||||
const { type, defaultDate, minDate } = this;
|
||||
const { type, minDate, maxDate, defaultDate } = this;
|
||||
|
||||
let defaultVal = new Date();
|
||||
|
||||
if (compareDay(defaultVal, minDate) === -1) {
|
||||
defaultVal = minDate;
|
||||
} else if (compareDay(defaultVal, maxDate) === 1) {
|
||||
defaultVal = maxDate;
|
||||
}
|
||||
|
||||
if (type === 'range') {
|
||||
const [startDay, endDay] = defaultDate || [];
|
||||
return [startDay || minDate, endDay || getNextDay(minDate)];
|
||||
return [startDay || defaultVal, endDay || getNextDay(defaultVal)];
|
||||
}
|
||||
|
||||
return defaultDate || minDate;
|
||||
if (type === 'multiple') {
|
||||
return defaultDate || [defaultVal];
|
||||
}
|
||||
|
||||
return defaultDate || defaultVal;
|
||||
},
|
||||
|
||||
// calculate the position of the elements
|
||||
@ -201,7 +229,7 @@ export default createComponent({
|
||||
const { body, months } = this.$refs;
|
||||
const top = getScrollTop(body);
|
||||
const bottom = top + this.bodyHeight;
|
||||
const heights = months.map(item => item.height);
|
||||
const heights = months.map((item) => item.height);
|
||||
const heightSum = heights.reduce((a, b) => a + b, 0);
|
||||
|
||||
// iOS scroll bounce may exceed the range
|
||||
@ -226,15 +254,16 @@ export default createComponent({
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (currentMonth) {
|
||||
this.monthTitle = currentMonth.title;
|
||||
this.subtitle = currentMonth.title;
|
||||
}
|
||||
},
|
||||
|
||||
onClickDay(item) {
|
||||
const { date } = item;
|
||||
const { type, currentDate } = this;
|
||||
|
||||
if (this.range) {
|
||||
const [startDay, endDay] = this.currentDate;
|
||||
if (type === 'range') {
|
||||
const [startDay, endDay] = currentDate;
|
||||
|
||||
if (startDay && !endDay) {
|
||||
const compareToStart = compareDay(date, startDay);
|
||||
@ -243,10 +272,28 @@ export default createComponent({
|
||||
this.select([startDay, date], true);
|
||||
} else if (compareToStart === -1) {
|
||||
this.select([date, null]);
|
||||
} else if (this.allowSameDay) {
|
||||
this.select([date, date]);
|
||||
}
|
||||
} else {
|
||||
this.select([date, null]);
|
||||
}
|
||||
} else if (type === 'multiple') {
|
||||
let selectedIndex;
|
||||
|
||||
const selected = this.currentDate.some((dateItem, index) => {
|
||||
const equal = compareDay(dateItem, date) === 0;
|
||||
if (equal) {
|
||||
selectedIndex = index;
|
||||
}
|
||||
return equal;
|
||||
});
|
||||
|
||||
if (selected) {
|
||||
currentDate.splice(selectedIndex, 1);
|
||||
} else {
|
||||
this.select([...currentDate, date]);
|
||||
}
|
||||
} else {
|
||||
this.select(date, true);
|
||||
}
|
||||
@ -257,26 +304,36 @@ export default createComponent({
|
||||
},
|
||||
|
||||
select(date, complete) {
|
||||
this.currentDate = date;
|
||||
this.$emit('select', this.currentDate);
|
||||
const emit = (date) => {
|
||||
this.currentDate = date;
|
||||
this.$emit('select', copyDates(this.currentDate));
|
||||
};
|
||||
|
||||
if (complete && this.range) {
|
||||
const valid = this.checkRange();
|
||||
if (complete && this.type === 'range') {
|
||||
const valid = this.checkRange(date);
|
||||
|
||||
if (!valid) {
|
||||
// auto selected to max range if showConfirm
|
||||
if (this.showConfirm) {
|
||||
emit([date[0], getDayByOffset(date[0], this.maxRange - 1)]);
|
||||
} else {
|
||||
emit(date);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
emit(date);
|
||||
|
||||
if (complete && !this.showConfirm) {
|
||||
this.onConfirm();
|
||||
}
|
||||
},
|
||||
|
||||
checkRange() {
|
||||
const { maxRange, currentDate, rangePrompt } = this;
|
||||
checkRange(date) {
|
||||
const { maxRange, rangePrompt } = this;
|
||||
|
||||
if (maxRange && calcDateNum(currentDate) > maxRange) {
|
||||
if (maxRange && calcDateNum(date) > maxRange) {
|
||||
Toast(rangePrompt || t('rangePrompt', maxRange));
|
||||
return false;
|
||||
}
|
||||
@ -285,14 +342,11 @@ export default createComponent({
|
||||
},
|
||||
|
||||
onConfirm() {
|
||||
if (this.range && !this.checkRange()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$emit('confirm', this.currentDate);
|
||||
this.$emit('confirm', copyDates(this.currentDate));
|
||||
},
|
||||
|
||||
genMonth(date, index) {
|
||||
const showMonthTitle = index !== 0 || !this.showSubtitle;
|
||||
return (
|
||||
<Month
|
||||
ref="months"
|
||||
@ -305,8 +359,10 @@ export default createComponent({
|
||||
showMark={this.showMark}
|
||||
formatter={this.formatter}
|
||||
rowHeight={this.rowHeight}
|
||||
showTitle={index !== 0}
|
||||
currentDate={this.currentDate}
|
||||
showSubtitle={this.showSubtitle}
|
||||
allowSameDay={this.allowSameDay}
|
||||
showMonthTitle={showMonthTitle}
|
||||
onClick={this.onClickDay}
|
||||
/>
|
||||
);
|
||||
@ -332,7 +388,7 @@ export default createComponent({
|
||||
color={this.color}
|
||||
class={bem('confirm')}
|
||||
disabled={this.buttonDisabled}
|
||||
nativeType="text"
|
||||
nativeType="button"
|
||||
onClick={this.onConfirm}
|
||||
>
|
||||
{text || t('confirm')}
|
||||
@ -343,11 +399,7 @@ export default createComponent({
|
||||
|
||||
genFooter() {
|
||||
return (
|
||||
<div
|
||||
class={bem('footer', {
|
||||
'safe-area-inset-bottom': this.safeAreaInsetBottom,
|
||||
})}
|
||||
>
|
||||
<div class={bem('footer', { unfit: !this.safeAreaInsetBottom })}>
|
||||
{this.genFooterContent()}
|
||||
</div>
|
||||
);
|
||||
@ -358,7 +410,9 @@ export default createComponent({
|
||||
<div class={bem()}>
|
||||
<Header
|
||||
title={this.title}
|
||||
monthTitle={this.monthTitle}
|
||||
showTitle={this.showTitle}
|
||||
subtitle={this.subtitle}
|
||||
showSubtitle={this.showSubtitle}
|
||||
scopedSlots={{
|
||||
title: () => this.slots('title'),
|
||||
}}
|
||||
@ -374,16 +428,16 @@ export default createComponent({
|
||||
|
||||
render() {
|
||||
if (this.poppable) {
|
||||
const createListener = name => () => this.$emit(name);
|
||||
const createListener = (name) => () => this.$emit(name);
|
||||
|
||||
return (
|
||||
<Popup
|
||||
round
|
||||
closeable
|
||||
class={bem('popup')}
|
||||
value={this.value}
|
||||
round={this.round}
|
||||
position={this.position}
|
||||
closeable={this.showTitle || this.showSubtitle}
|
||||
getContainer={this.getContainer}
|
||||
closeOnPopstate={this.closeOnPopstate}
|
||||
closeOnClickOverlay={this.closeOnClickOverlay}
|
||||
|
@ -27,8 +27,9 @@
|
||||
box-shadow: @calendar-header-box-shadow;
|
||||
}
|
||||
|
||||
&__month-title,
|
||||
&__header-title,
|
||||
&__month-title {
|
||||
&__header-subtitle {
|
||||
height: @calendar-header-title-height;
|
||||
font-weight: @font-weight-bold;
|
||||
line-height: @calendar-header-title-height;
|
||||
@ -39,6 +40,10 @@
|
||||
font-size: @calendar-header-title-font-size;
|
||||
}
|
||||
|
||||
&__header-subtitle {
|
||||
font-size: @calendar-header-subtitle-font-size;
|
||||
}
|
||||
|
||||
&__month-title {
|
||||
font-size: @calendar-month-title-font-size;
|
||||
}
|
||||
@ -94,7 +99,10 @@
|
||||
cursor: pointer;
|
||||
|
||||
&--end,
|
||||
&--start {
|
||||
&--start,
|
||||
&--start-end,
|
||||
&--multiple-middle,
|
||||
&--multiple-selected {
|
||||
color: @calendar-range-edge-color;
|
||||
background-color: @calendar-range-edge-background-color;
|
||||
}
|
||||
@ -107,6 +115,11 @@
|
||||
border-radius: 0 @border-radius-md @border-radius-md 0;
|
||||
}
|
||||
|
||||
&--start-end,
|
||||
&--multiple-selected {
|
||||
border-radius: @border-radius-md;
|
||||
}
|
||||
|
||||
&--middle {
|
||||
color: @calendar-range-middle-color;
|
||||
|
||||
@ -160,10 +173,11 @@
|
||||
&__footer {
|
||||
flex-shrink: 0;
|
||||
padding: 0 @padding-md;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
|
||||
&--safe-area-inset-bottom {
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
&--unfit {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,10 @@ exports[`renders demo correctly 1`] = `
|
||||
<div class="van-cell__title"><span>选择单个日期</span></div><i class="van-icon van-icon-arrow van-cell__right-icon">
|
||||
<!----></i>
|
||||
</div>
|
||||
<div role="button" tabindex="0" class="van-cell van-cell--clickable">
|
||||
<div class="van-cell__title"><span>选择多个日期</span></div><i class="van-icon van-icon-arrow van-cell__right-icon">
|
||||
<!----></i>
|
||||
</div>
|
||||
<div role="button" tabindex="0" class="van-cell van-cell--clickable">
|
||||
<div class="van-cell__title"><span>选择日期区间</span></div><i class="van-icon van-icon-arrow van-cell__right-icon">
|
||||
<!----></i>
|
||||
@ -52,7 +56,7 @@ exports[`renders demo correctly 1`] = `
|
||||
<div class="van-calendar" style="height: 500px;">
|
||||
<div class="van-calendar__header">
|
||||
<div class="van-calendar__header-title">日历</div>
|
||||
<div class="van-calendar__month-title">2012年1月</div>
|
||||
<div class="van-calendar__header-subtitle">2012年1月</div>
|
||||
<div class="van-calendar__weekdays"><span class="van-calendar__weekday">日</span><span class="van-calendar__weekday">一</span><span class="van-calendar__weekday">二</span><span class="van-calendar__weekday">三</span><span class="van-calendar__weekday">四</span><span class="van-calendar__weekday">五</span><span class="van-calendar__weekday">六</span></div>
|
||||
</div>
|
||||
<div class="van-calendar__body">
|
||||
@ -167,7 +171,7 @@ exports[`renders demo correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-calendar__footer van-calendar__footer--safe-area-inset-bottom"></div>
|
||||
<div class="van-calendar__footer"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
|
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