diff --git a/build/bin/build-entry.js b/build/bin/build-entry.js
index 34d111e49..27c7b9e96 100644
--- a/build/bin/build-entry.js
+++ b/build/bin/build-entry.js
@@ -1,4 +1,4 @@
-var Components = require('../../components.json');
+var Components = require('./get-components')();
var fs = require('fs');
var render = require('json-templater/string');
var uppercamelcase = require('uppercamelcase');
@@ -40,13 +40,11 @@ export default {
delete Components.font;
-var ComponentNames = Object.keys(Components);
-
var includeComponentTemplate = [];
var installTemplate = [];
var listTemplate = [];
-ComponentNames.forEach(name => {
+Components.forEach(name => {
var componentName = uppercamelcase(name);
includeComponentTemplate.push(render(IMPORT_TEMPLATE, {
diff --git a/build/bin/build-lib.js b/build/bin/build-lib.js
index 0f59e218f..d20e2ba7c 100644
--- a/build/bin/build-lib.js
+++ b/build/bin/build-lib.js
@@ -12,7 +12,7 @@
const fs = require('fs');
const path = require('path');
-const components = require('../../components.json');
+const components = require('./get-components')();
const chalk = require('chalk');
require('shelljs/global');
@@ -38,7 +38,7 @@ log('Finished', 'build:vant-css');
// 5. build style entrys
log('Starting', 'build:style-entries');
-Object.keys(components).forEach((componentName) => {
+components.forEach((componentName) => {
const dir = path.join(__dirname, '../../lib/', componentName, '/style');
const file = path.join(dir, 'index.js');
const cssPath = path.join(__dirname, '../../lib/vant-css/', `${componentName}.css`);
diff --git a/build/bin/get-components.js b/build/bin/get-components.js
new file mode 100644
index 000000000..9cc7a71fe
--- /dev/null
+++ b/build/bin/get-components.js
@@ -0,0 +1,8 @@
+const fs = require('fs');
+const path = require('path');
+
+module.exports = function() {
+ const dirs = fs.readdirSync(path.resolve(__dirname, '../../packages'));
+ const excludes = ['index.js', 'vant-css', 'mixins', 'utils'];
+ return dirs.filter(dirName => excludes.indexOf(dirName) === -1)
+}
diff --git a/build/bin/init.js b/build/bin/init.js
index 2aa0b37d3..023176707 100644
--- a/build/bin/init.js
+++ b/build/bin/init.js
@@ -28,21 +28,5 @@ gulp.task('copy', function(callback) {
});
});
-
-// 添加到 components.json
-gulp.task('addComponents', function(callback) {
- const componentsFile = require('../../components.json');
- if (componentsFile[name]) {
- console.error(`${name} 已存在.`);
- process.exit(1);
- }
- componentsFile[name] = `./packages/${name}/index.js`;
- fileSave(path.join(__dirname, '../../components.json'))
- .write(JSON.stringify(componentsFile, null, ' '), 'utf8')
- .end('\n');
- gutil.log('-------> components.json文件更新成功');
- gutil.log(gutil.colors.yellow('-------> 请无视下面的make报错'));
-});
-
runSequence('copy', 'addComponents');
diff --git a/build/genExamples.js b/build/genExamples.js
deleted file mode 100644
index c668082f9..000000000
--- a/build/genExamples.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const path = require('path');
-const docConfig = require('../docs/src/doc.config');
-const { extractExample } = require('zan-doc/src/helper');
-
-function extract(watch = false) {
- extractExample({
- src: path.resolve(__dirname, '../docs/examples-docs'),
- dist: path.resolve(__dirname, '../docs/examples-dist'),
- nav: docConfig['zh-CN'].nav,
- watch
- });
-}
-
-module.exports = function watch(isProduction) {
- extract(!isProduction);
-};
diff --git a/build/webpack.config.dev.js b/build/webpack.config.dev.js
index 737712be8..c7704eae6 100644
--- a/build/webpack.config.dev.js
+++ b/build/webpack.config.dev.js
@@ -6,11 +6,20 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
const isProduction = process.env.NODE_ENV === 'production';
+const docConfig = require('../docs/src/doc.config');
+const { extractExample } = require('zan-doc/src/helper');
const styleLoaders = [
{ loader: 'css-loader' },
{ loader: 'postcss-loader', options: { sourceMap: true } }
];
-require('./genExamples')(isProduction);
+
+// extract [components].vue from [components].md
+extractExample({
+ src: path.resolve(__dirname, '../docs/examples-docs'),
+ dist: path.resolve(__dirname, '../docs/examples-dist'),
+ nav: docConfig['zh-CN'].nav,
+ watch: !isProduction
+});
module.exports = {
entry: {
diff --git a/components.json b/components.json
deleted file mode 100644
index 705772a32..000000000
--- a/components.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "button": "./packages/button/index.js",
- "switch": "./packages/switch/index.js",
- "field": "./packages/field/index.js",
- "radio": "./packages/radio/index.js",
- "cell": "./packages/cell/index.js",
- "icon": "./packages/icon/index.js",
- "cell-group": "./packages/cell-group/index.js",
- "cell-swipe": "./packages/cell-swipe/index.js",
- "popup": "./packages/popup/index.js",
- "dialog": "./packages/dialog/index.js",
- "picker": "./packages/picker/index.js",
- "radio-group": "./packages/radio-group/index.js",
- "waterfall": "./packages/waterfall/index.js",
- "loading": "./packages/loading/index.js",
- "panel": "./packages/panel/index.js",
- "card": "./packages/card/index.js",
- "steps": "./packages/steps/index.js",
- "tag": "./packages/tag/index.js",
- "checkbox": "./packages/checkbox/index.js",
- "checkbox-group": "./packages/checkbox-group/index.js",
- "badge-group": "./packages/badge-group/index.js",
- "badge": "./packages/badge/index.js",
- "search": "./packages/search/index.js",
- "step": "./packages/step/index.js",
- "tabs": "./packages/tabs/index.js",
- "tab": "./packages/tab/index.js",
- "lazyload": "./packages/lazyload/index.js",
- "image-preview": "./packages/image-preview/index.js",
- "col": "./packages/col/index.js",
- "row": "./packages/row/index.js",
- "actionsheet": "./packages/actionsheet/index.js",
- "quantity": "./packages/quantity/index.js",
- "progress": "./packages/progress/index.js",
- "toast": "./packages/toast/index.js",
- "uploader": "./packages/uploader/index.js",
- "swipe": "./packages/swipe/index.js",
- "swipe-item": "./packages/swipe-item/index.js",
- "datetime-picker": "./packages/datetime-picker/index.js",
- "notice-bar": "./packages/notice-bar/index.js"
-}
diff --git a/docs/examples-docs/switch-cell.md b/docs/examples-docs/switch-cell.md
new file mode 100644
index 000000000..24ff57fc8
--- /dev/null
+++ b/docs/examples-docs/switch-cell.md
@@ -0,0 +1,81 @@
+## SwitchCell 开关单元格
+
+`SwitchCell`组件是对`Switch`和`Cell`组件的封装
+
+
+
+### 使用指南
+``` javascript
+import { SwitchCell } from 'vant';
+
+Vue.component(SwitchCell.name, SwitchCell);
+```
+
+### 代码演示
+
+#### 基础用法
+
+:::demo 基础用法
+```html
+
+
+
+
+
+
+
+```
+:::
+
+#### 禁用状态
+通过`disabled`属性可以将组件设置为禁用状态
+
+:::demo 禁用状态
+```html
+
+
+
+```
+:::
+
+#### 加载状态
+通过`loading`属性可以将组件设置为加载状态
+
+:::demo 加载状态
+```html
+
+
+
+```
+:::
+
+### API
+
+| 参数 | 说明 | 类型 | 默认值 | 可选值 |
+|-----------|-----------|-----------|-------------|-------------|
+| v-model | 开关状态 | `Boolean` | | |
+| title | 左侧标题 | `String` | `''` | |
+| loading | 是否为加载状态 | `Boolean` | `false` | |
+| disabled | 是否为禁用状态 | `Boolean` | `false` | |
+
+### Event
+
+| 事件名 | 说明 | 参数 |
+|-----------|-----------|-----------|
+| change | 开关状态切换回调 | checked: 是否选中开关 |
\ No newline at end of file
diff --git a/docs/src/doc.config.js b/docs/src/doc.config.js
index 70cf88afc..58c899777 100644
--- a/docs/src/doc.config.js
+++ b/docs/src/doc.config.js
@@ -50,13 +50,17 @@ module.exports = {
"path": "/layout",
"title": "Layout 布局"
},
+ {
+ "path": "/badge",
+ "title": "Badge 徽章"
+ },
{
"path": "/button",
"title": "Button 按钮"
},
{
- "path": "/icon",
- "title": "Icon 图标"
+ "path": "/card",
+ "title": "Card 图文组件"
},
{
"path": "/cell",
@@ -67,56 +71,8 @@ module.exports = {
"title": "CellSwipe 滑动单元格"
},
{
- "path": "/progress",
- "title": "Progress 进度条"
- },
- {
- "path": "/card",
- "title": "Card 图文组件"
- },
- {
- "path": "/panel",
- "title": "Panel 面板"
- },
- {
- "path": "/loading",
- "title": "Loading 加载"
- },
- {
- "path": "/steps",
- "title": "Steps 步骤条"
- },
- {
- "path": "/tag",
- "title": "Tag 标记"
- },
- {
- "path": "/badge",
- "title": "Badge 徽章"
- },
- {
- "path": "/tab",
- "title": "Tab 标签"
- },
- {
- "path": "/popup",
- "title": "Popup 弹出菜单"
- },
- {
- "path": "/swipe",
- "title": "Swipe 轮播"
- },
- {
- "path": "/search",
- "title": "Search 搜索"
- },
- {
- "path": "/quantity",
- "title": "Quantity 数量选择"
- },
- {
- "path": "/waterfall",
- "title": "Waterfall 瀑布流"
+ "path": "/icon",
+ "title": "Icon 图标"
},
{
"path": "/image-preview",
@@ -126,9 +82,53 @@ module.exports = {
"path": "/lazyload",
"title": "Lazyload 图片懒加载"
},
+ {
+ "path": "/loading",
+ "title": "Loading 加载"
+ },
{
"path": "/notice-bar",
"title": "NoticeBar 通告栏"
+ },
+ {
+ "path": "/panel",
+ "title": "Panel 面板"
+ },
+ {
+ "path": "/popup",
+ "title": "Popup 弹出菜单"
+ },
+ {
+ "path": "/progress",
+ "title": "Progress 进度条"
+ },
+ {
+ "path": "/quantity",
+ "title": "Quantity 数量选择"
+ },
+ {
+ "path": "/steps",
+ "title": "Steps 步骤条"
+ },
+ {
+ "path": "/tab",
+ "title": "Tab 标签"
+ },
+ {
+ "path": "/tag",
+ "title": "Tag 标记"
+ },
+ {
+ "path": "/swipe",
+ "title": "Swipe 轮播"
+ },
+ {
+ "path": "/search",
+ "title": "Search 搜索"
+ },
+ {
+ "path": "/waterfall",
+ "title": "Waterfall 瀑布流"
}
]
},
@@ -136,8 +136,8 @@ module.exports = {
"groupName": "表单",
"list": [
{
- "path": "/switch",
- "title": "Switch 开关"
+ "path": "/checkbox",
+ "title": "Checkbox 复选框"
},
{
"path": "/field",
@@ -148,8 +148,8 @@ module.exports = {
"title": "Radio 单选框"
},
{
- "path": "/checkbox",
- "title": "Checkbox 复选框"
+ "path": "/switch",
+ "title": "Switch 开关"
},
{
"path": "/uploader",
@@ -164,14 +164,6 @@ module.exports = {
"path": "/actionsheet",
"title": "Actionsheet 行动按钮"
},
- {
- "path": "/toast",
- "title": "Toast 轻提示"
- },
- {
- "path": "/picker",
- "title": "Picker 选择器"
- },
{
"path": "/datetime-picker",
"title": "DatetimePicker 时间选择"
@@ -179,6 +171,23 @@ module.exports = {
{
"path": "/dialog",
"title": "Dialog 弹出框"
+ },
+ {
+ "path": "/picker",
+ "title": "Picker 选择器"
+ },
+ {
+ "path": "/toast",
+ "title": "Toast 轻提示"
+ }
+ ]
+ },
+ {
+ "groupName": "业务组件",
+ "list": [
+ {
+ "path": "/switch-cell",
+ "title": "SwitchCell 开关单元格"
}
]
}
diff --git a/packages/index.js b/packages/index.js
index 7529339fe..fcb708c38 100644
--- a/packages/index.js
+++ b/packages/index.js
@@ -1,79 +1,81 @@
+import Actionsheet from './actionsheet';
+import Badge from './badge';
+import BadgeGroup from './badge-group';
import Button from './button';
-import Switch from './switch';
-import Field from './field';
-import Radio from './radio';
+import Card from './card';
import Cell from './cell';
-import Icon from './icon';
import CellGroup from './cell-group';
import CellSwipe from './cell-swipe';
-import Popup from './popup';
-import Dialog from './dialog';
-import Picker from './picker';
-import RadioGroup from './radio-group';
-import Waterfall from './waterfall';
-import Loading from './loading';
-import Panel from './panel';
-import Card from './card';
-import Steps from './steps';
-import Tag from './tag';
import Checkbox from './checkbox';
import CheckboxGroup from './checkbox-group';
-import BadgeGroup from './badge-group';
-import Badge from './badge';
+import Col from './col';
+import DatetimePicker from './datetime-picker';
+import Dialog from './dialog';
+import Field from './field';
+import Icon from './icon';
+import ImagePreview from './image-preview';
+import Lazyload from './lazyload';
+import Loading from './loading';
+import NoticeBar from './notice-bar';
+import Panel from './panel';
+import Picker from './picker';
+import Popup from './popup';
+import Progress from './progress';
+import Quantity from './quantity';
+import Radio from './radio';
+import RadioGroup from './radio-group';
+import Row from './row';
import Search from './search';
import Step from './step';
-import Tabs from './tabs';
-import Tab from './tab';
-import Lazyload from './lazyload';
-import ImagePreview from './image-preview';
-import Col from './col';
-import Row from './row';
-import Actionsheet from './actionsheet';
-import Quantity from './quantity';
-import Progress from './progress';
-import Toast from './toast';
-import Uploader from './uploader';
+import Steps from './steps';
import Swipe from './swipe';
import SwipeItem from './swipe-item';
-import DatetimePicker from './datetime-picker';
-import NoticeBar from './notice-bar';
+import Switch from './switch';
+import SwitchCell from './switch-cell';
+import Tab from './tab';
+import Tabs from './tabs';
+import Tag from './tag';
+import Toast from './toast';
+import Uploader from './uploader';
+import Waterfall from './waterfall';
const version = '0.8.6';
const components = [
+ Actionsheet,
+ Badge,
+ BadgeGroup,
Button,
- Switch,
- Field,
- Radio,
+ Card,
Cell,
- Icon,
CellGroup,
CellSwipe,
- Popup,
- Picker,
- RadioGroup,
- Loading,
- Panel,
- Card,
- Steps,
- Tag,
Checkbox,
CheckboxGroup,
- BadgeGroup,
- Badge,
+ Col,
+ DatetimePicker,
+ Field,
+ Icon,
+ Loading,
+ NoticeBar,
+ Panel,
+ Picker,
+ Popup,
+ Progress,
+ Quantity,
+ Radio,
+ RadioGroup,
+ Row,
Search,
Step,
- Tabs,
- Tab,
- Col,
- Row,
- Actionsheet,
- Quantity,
- Progress,
- Uploader,
+ Steps,
Swipe,
SwipeItem,
- DatetimePicker,
- NoticeBar
+ Switch,
+ SwitchCell,
+ Tab,
+ Tabs,
+ Tag,
+ Uploader
];
const install = function(Vue) {
@@ -92,45 +94,46 @@ if (typeof window !== 'undefined' && window.Vue) {
export {
install,
version,
+ Actionsheet,
+ Badge,
+ BadgeGroup,
Button,
- Switch,
- Field,
- Radio,
+ Card,
Cell,
- Icon,
CellGroup,
CellSwipe,
- Popup,
- Dialog,
- Picker,
- RadioGroup,
- Waterfall,
- Loading,
- Panel,
- Card,
- Steps,
- Tag,
Checkbox,
CheckboxGroup,
- BadgeGroup,
- Badge,
+ Col,
+ DatetimePicker,
+ Dialog,
+ Field,
+ Icon,
+ ImagePreview,
+ Lazyload,
+ Loading,
+ NoticeBar,
+ Panel,
+ Picker,
+ Popup,
+ Progress,
+ Quantity,
+ Radio,
+ RadioGroup,
+ Row,
Search,
Step,
- Tabs,
- Tab,
- Lazyload,
- ImagePreview,
- Col,
- Row,
- Actionsheet,
- Quantity,
- Progress,
- Toast,
- Uploader,
+ Steps,
Swipe,
SwipeItem,
- DatetimePicker,
- NoticeBar
+ Switch,
+ SwitchCell,
+ Tab,
+ Tabs,
+ Tag,
+ Toast,
+ Uploader,
+ Waterfall
};
export default {
install,
diff --git a/packages/switch-cell/index.vue b/packages/switch-cell/index.vue
new file mode 100644
index 000000000..911d33da5
--- /dev/null
+++ b/packages/switch-cell/index.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
diff --git a/packages/vant-css/src/index.css b/packages/vant-css/src/index.css
index 6a7bfa8df..d897aacbd 100644
--- a/packages/vant-css/src/index.css
+++ b/packages/vant-css/src/index.css
@@ -31,3 +31,4 @@
@import './uploader.css';
@import './swipe.css';
@import './notice-bar.css';
+@import './switch-cell.css';
diff --git a/packages/vant-css/src/switch-cell.css b/packages/vant-css/src/switch-cell.css
new file mode 100644
index 000000000..7edabe8bd
--- /dev/null
+++ b/packages/vant-css/src/switch-cell.css
@@ -0,0 +1,9 @@
+.van-switch-cell {
+ .van-cell__title {
+ vertical-align: middle;
+ }
+
+ .van-switch {
+ float: right;
+ }
+}
\ No newline at end of file
diff --git a/test/unit/specs/switch-cell.spec.js b/test/unit/specs/switch-cell.spec.js
new file mode 100644
index 000000000..edfaee56a
--- /dev/null
+++ b/test/unit/specs/switch-cell.spec.js
@@ -0,0 +1,95 @@
+import SwitchCell from 'packages/switch-cell';
+import { mount } from 'avoriaz';
+import { DOMChecker } from '../utils';
+
+describe('SwitchCell', () => {
+ let wrapper;
+ afterEach(() => {
+ wrapper && wrapper.destroy();
+ });
+
+ it('default', () => {
+ wrapper = mount(SwitchCell, {
+ attachToDocument: true
+ });
+
+ DOMChecker(wrapper, {
+ count: {
+ '.van-switch--off': 1,
+ '.van-switch--disabled': 0
+ }
+ });
+ });
+
+ it('set title', () => {
+ wrapper = mount(SwitchCell, {
+ attachToDocument: true,
+ propsData: {
+ title: '测试标题'
+ }
+ });
+
+ DOMChecker(wrapper, {
+ text: {
+ '.van-cell__text': '测试标题'
+ },
+ count: {
+ '.van-switch--off': 1,
+ '.van-switch--disabled': 0
+ }
+ });
+ });
+
+ it('checked', () => {
+ wrapper = mount(SwitchCell, {
+ attachToDocument: true,
+ propsData: {
+ value: true
+ }
+ });
+
+ DOMChecker(wrapper, {
+ count: {
+ '.van-switch--on': 1,
+ '.van-switch--disabled': 0
+ }
+ });
+ });
+
+ it('disabled', () => {
+ wrapper = mount(SwitchCell, {
+ attachToDocument: true,
+ propsData: {
+ disabled: true
+ }
+ });
+
+ DOMChecker(wrapper, {
+ count: {
+ '.van-switch--off': 1,
+ '.van-switch--disabled': 1
+ }
+ });
+ });
+
+ it('listen to change event', (done) => {
+ wrapper = mount(SwitchCell, {
+ attachToDocument: true,
+ propsData: {
+ value: false
+ }
+ });
+
+ wrapper.vm.$on('input', (value) => {
+ wrapper.vm.value = value;
+ });
+
+ wrapper.vm.$on('change', (value) => {
+ expect(value).to.be.true;
+ done();
+ });
+
+ const switchEl = wrapper.find('.van-switch')[0];
+ switchEl.trigger('click');
+ });
+});