diff --git a/docs/src/Preview.vue b/docs/src/Preview.vue
index 903e23a4..582d8e7f 100644
--- a/docs/src/Preview.vue
+++ b/docs/src/Preview.vue
@@ -44,7 +44,8 @@ const MAP = {
tabbar: 'tabbar-201808160922.png',
toast: 'toast-201808191046.png',
transition: 'transition-20180821.png',
- 'tree-select': 'tree-select-201808092138.png'
+ 'tree-select': 'tree-select-201808092138.png',
+ checkbox: 'checkbox-20180928-1.png'
};
export default {
diff --git a/example/app.json b/example/app.json
index 3b75d79f..bea9f296 100644
--- a/example/app.json
+++ b/example/app.json
@@ -31,7 +31,8 @@
"pages/tree-select/index",
"pages/area/index",
"pages/submit-bar/index",
- "pages/radio/index"
+ "pages/radio/index",
+ "pages/checkbox/index"
],
"window": {
"navigationBarBackgroundColor": "#f8f8f8",
diff --git a/example/config.js b/example/config.js
index f215eaaf..4d3cb92f 100644
--- a/example/config.js
+++ b/example/config.js
@@ -71,6 +71,10 @@ export default [
{
groupName: '表单组件',
list: [
+ {
+ path: '/checkbox',
+ title: 'Checkbox 复选框'
+ },
{
path: '/field',
title: 'Field 输入框'
diff --git a/example/pages/checkbox/index.js b/example/pages/checkbox/index.js
new file mode 100644
index 00000000..7ff0a2fd
--- /dev/null
+++ b/example/pages/checkbox/index.js
@@ -0,0 +1,36 @@
+import Page from '../../common/page';
+
+Page({
+ data: {
+ checkbox1: true,
+ checkbox2: true,
+ list: ['a', 'b', 'c'],
+ result: ['a', 'b'],
+ result2: [],
+ result3: [],
+ icon: {
+ normal:
+ 'https://img.yzcdn.cn/public_files/2017/10/13/c547715be149dd3faa817e4a948b40c4.png',
+ active:
+ 'https://img.yzcdn.cn/public_files/2017/10/13/793c77793db8641c4c325b7f25bf130d.png'
+ }
+ },
+
+ onChange(event) {
+ const { key } = event.currentTarget.dataset;
+ this.setData({ [key]: event.detail });
+ },
+
+ onClick(event) {
+ const { value } = event.currentTarget.dataset;
+ this.setData({
+ radio3: value
+ });
+ },
+
+ toggle(event) {
+ const { name } = event.currentTarget.dataset;
+ const checkbox = this.selectComponent(`.checkboxes-${name}`);
+ checkbox.toggle();
+ }
+});
diff --git a/example/pages/checkbox/index.json b/example/pages/checkbox/index.json
new file mode 100644
index 00000000..8b2d8481
--- /dev/null
+++ b/example/pages/checkbox/index.json
@@ -0,0 +1,10 @@
+{
+ "navigationBarTitleText": "Checkbox 复选框",
+ "usingComponents": {
+ "demo-block": "../../components/demo-block/index",
+ "van-checkbox-group": "../../dist/checkbox-group/index",
+ "van-checkbox": "../../dist/checkbox/index",
+ "van-cell": "../../dist/cell/index",
+ "van-cell-group": "../../dist/cell-group/index"
+ }
+}
diff --git a/example/pages/checkbox/index.wxml b/example/pages/checkbox/index.wxml
new file mode 100644
index 00000000..8102a8be
--- /dev/null
+++ b/example/pages/checkbox/index.wxml
@@ -0,0 +1,58 @@
+
+ 复选框
+
+
+
+ 复选框
+ 复选框
+
+
+
+
+ 自定义图标
+
+
+
+
+
+
+
+ 复选框 {{ item }}
+
+
+
+
+
+
+
+ 复选框 {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/pages/checkbox/index.wxss b/example/pages/checkbox/index.wxss
new file mode 100644
index 00000000..4ed6d7b4
--- /dev/null
+++ b/example/pages/checkbox/index.wxss
@@ -0,0 +1,11 @@
+.demo-checkbox-group {
+ margin: 10px 0 0 20px;
+}
+
+.demo-checkbox {
+ margin: 10px 0 0 20px;
+}
+
+.icon {
+ width: 20px;
+}
diff --git a/packages/checkbox-group/index.json b/packages/checkbox-group/index.json
new file mode 100644
index 00000000..0a336c08
--- /dev/null
+++ b/packages/checkbox-group/index.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "van-icon": "../icon/index"
+ }
+}
diff --git a/packages/checkbox-group/index.less b/packages/checkbox-group/index.less
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/checkbox-group/index.ts b/packages/checkbox-group/index.ts
new file mode 100644
index 00000000..ef6a3f53
--- /dev/null
+++ b/packages/checkbox-group/index.ts
@@ -0,0 +1,37 @@
+import { VantComponent } from '../common/component';
+
+VantComponent({
+ relation: {
+ name: 'checkbox',
+ type: 'descendant',
+ linked(target: Weapp.Component) {
+ const { value, disabled } = this.data;
+ target.setData({
+ value: value.indexOf(target.data.name) !== -1,
+ disabled: disabled || target.data.disabled
+ });
+ }
+ },
+
+ props: {
+ value: Array,
+ disabled: Boolean,
+ max: Number
+ },
+
+ watch: {
+ value(value) {
+ const children = this.getRelationNodes('../checkbox/index');
+ children.forEach(child => {
+ child.setData({ value: value.indexOf(child.data.name) !== -1 });
+ });
+ },
+
+ disabled(disabled: boolean) {
+ const children = this.getRelationNodes('../checkbox/index');
+ children.forEach(child => {
+ child.setData({ disabled: disabled || child.data.disabled });
+ });
+ }
+ }
+});
diff --git a/packages/checkbox-group/index.wxml b/packages/checkbox-group/index.wxml
new file mode 100644
index 00000000..775ee3ce
--- /dev/null
+++ b/packages/checkbox-group/index.wxml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/packages/checkbox/README.md b/packages/checkbox/README.md
new file mode 100644
index 00000000..c0baceea
--- /dev/null
+++ b/packages/checkbox/README.md
@@ -0,0 +1,190 @@
+## Checkbox 复选框
+
+### 使用指南
+在 index.json 中引入组件
+```json
+"usingComponents": {
+ "van-checkbox": "path/to/vant-weapp/dist/checkbox/index",
+ "van-checkbox-group": "path/to/vant-weapp/dist/checkbox-group/index"
+}
+```
+
+### 代码演示
+
+#### 基础用法
+通过`value`绑定 checkbox 的勾选状态
+
+```html
+复选框
+```
+
+#### 禁用状态
+
+```html
+复选框
+```
+
+#### 自定义图标
+通过 icon 插槽自定义图标
+
+```html
+
+ 自定义图标
+
+
+```
+
+```js
+Page({
+ data: {
+ checked: true,
+ icon: {
+ normal: '//img.yzcdn.cn/icon-normal.png',
+ active: '//img.yzcdn.cn/icon-active.png'
+ }
+ },
+
+ onChange(event) {
+ this.setData({
+ checked: event.detail
+ });
+ }
+});
+```
+
+#### Checkbox 组
+
+需要与`van-checkbox-group`一起使用,选中值是一个数组,通过`value`绑定在`van-checkbox-group`上,数组中的项即为选中的`Checkbox`的`name`属性设置的值
+
+```html
+
+
+ 复选框 {{ item }}
+
+
+```
+
+```javascript
+Page({
+ data: {
+ list: ['a', 'b', 'c'],
+ result: ['a', 'b']
+ },
+
+ onChange(event) {
+ this.setData({
+ result: event.detail
+ });
+ }
+});
+```
+
+#### 设置最大可选数
+
+```html
+
+
+ 复选框 {{ item }}
+
+
+```
+
+#### 与 Cell 组件一起使用
+
+此时你需要再引入`Cell`和`CellGroup`组件,并通过 checkbox 的 toggle 方法手动触发切换
+
+```html
+
+
+
+
+
+
+
+```
+
+```js
+Page({
+ data: {
+ list: ['a', 'b', 'c'],
+ result: ['a', 'b']
+ },
+
+ onChange(event) {
+ this.setData({
+ result: event.detail
+ });
+ }
+
+ toggle(event) {
+ const { name } = event.currentTarget.dataset;
+ const checkbox = this.selectComponent(`.checkboxes-${name}`);
+ checkbox.toggle();
+ }
+});
+```
+
+### Checkbox API
+
+| 参数 | 说明 | 类型 | 默认值 |
+|-----------|-----------|-----------|-------------|
+| name | 标识 Checkbox 名称 | `any` | - |
+| value | 是否为选中状态 | `Boolean` | `false` |
+| disabled | 是否禁用单选框 | `Boolean` | `false` |
+| label-disabled | 是否禁用单选框内容点击 | `Boolean` | `false` |
+| label-position | 文本位置,可选值为 `left` | `String` | `right` |
+| shape | 形状,可选值为 `round` `square` | `String` | `round` |
+| use-icon-slot | 是否使用 icon slot | `Boolean` | `false` |
+
+### CheckboxGroup API
+
+| 参数 | 说明 | 类型 | 默认值 |
+|-----------|-----------|-----------|-------------|
+| value | 所有选中项的 name | `Array` | - |
+| disabled | 是否禁用所有单选框 | `Boolean` | `false` |
+| max | 设置最大可选数 | `Number` | `0`(无限制) |
+
+### Checkbox Event
+
+| 事件名称 | 说明 | 回调参数 |
+|-----------|-----------|-----------|
+| change | 当绑定值变化时触发的事件 | 当前组件的值 |
+
+### CheckboxGroup Event
+
+| 事件名称 | 说明 | 回调参数 |
+|-----------|-----------|-----------|
+| change | 当绑定值变化时触发的事件 | 当前组件的值 |
+
+### Checkbox Slot
+
+| 名称 | 说明 | slot-scope |
+|-----------|-----------|-----------|
+| - | 自定义文本 | - |
+| icon | 自定义图标 | checked: 是否为选中状态 |
+
+### Checkbox 方法
+
+通过 selectComponent 可以获取到 checkbox 实例并调用实例方法
+
+| 方法名 | 参数 | 返回值 | 介绍 |
+|-----------|-----------|-----------|-------------|
+| toggle | - | - | 切换选中状态 |
diff --git a/packages/checkbox/index.json b/packages/checkbox/index.json
new file mode 100644
index 00000000..0a336c08
--- /dev/null
+++ b/packages/checkbox/index.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "van-icon": "../icon/index"
+ }
+}
diff --git a/packages/checkbox/index.less b/packages/checkbox/index.less
new file mode 100644
index 00000000..de3e18fe
--- /dev/null
+++ b/packages/checkbox/index.less
@@ -0,0 +1,56 @@
+@import '../common/style/var.less';
+
+@van-checkbox-size: 20px;
+
+.van-checkbox {
+ overflow: hidden;
+ user-select: none;
+
+ &__icon-wrap,
+ &__label {
+ display: inline-block;
+ line-height: @van-checkbox-size;
+ vertical-align: middle;
+ }
+
+ &__icon {
+ box-sizing: border-box;
+ display: block;
+ width: @van-checkbox-size;
+ height: @van-checkbox-size;
+ border: 1px solid #aaa;
+ color: transparent;
+ font-size: 12px;
+ text-align: center;
+
+ &--round {
+ border-radius: 100%;
+ }
+
+ &--checked {
+ border-color: @green;
+ background-color: @green;
+ color: #fff;
+ }
+
+ &--disabled {
+ border-color: @border-color;
+ background-color: currentColor;
+ color: @background-color;
+ }
+
+ &--disabled&--checked {
+ border-color: @border-color;
+ background-color: @border-color;
+ }
+ }
+
+ &__label {
+ margin-left: 10px;
+
+ &--left {
+ margin: 0 10px 0 0;
+ float: left;
+ }
+ }
+}
diff --git a/packages/checkbox/index.ts b/packages/checkbox/index.ts
new file mode 100644
index 00000000..996394a7
--- /dev/null
+++ b/packages/checkbox/index.ts
@@ -0,0 +1,77 @@
+import { VantComponent } from '../common/component';
+
+VantComponent({
+ relation: {
+ name: 'checkbox-group',
+ type: 'ancestor'
+ },
+
+ classes: ['icon-class', 'label-class'],
+
+ props: {
+ name: null,
+ value: null,
+ disabled: Boolean,
+ labelDisabled: Boolean,
+ labelPosition: String,
+ shape: {
+ type: String,
+ value: 'round'
+ },
+ useIconSlot: Boolean
+ },
+
+ computed: {
+ iconClass(): string {
+ const { disabled, value, shape } = this.data;
+ return this.classNames('van-checkbox__icon', `van-checkbox__icon--${shape}`, {
+ 'van-checkbox__icon--disabled': disabled,
+ 'van-checkbox__icon--checked': value
+ });
+ }
+ },
+
+ methods: {
+ emitChange(value) {
+ const parent = this.getRelationNodes('../checkbox-group/index')[0];
+ if (parent) {
+ const parentValue = parent.data.value.slice();
+ const { name } = this.data;
+ if (value) {
+ if (parent.data.max && parentValue.length >= parent.data.max) {
+ return;
+ }
+ /* istanbul ignore else */
+ if (parentValue.indexOf(name) === -1) {
+ parentValue.push(name);
+ parent.$emit('input', parentValue);
+ parent.$emit('change', parentValue);
+ }
+ } else {
+ const index = parentValue.indexOf(name);
+ /* istanbul ignore else */
+ if (index !== -1) {
+ parentValue.splice(index, 1);
+ parent.$emit('input', parentValue);
+ parent.$emit('change', parentValue);
+ }
+ }
+ } else {
+ this.$emit('input', value);
+ this.$emit('change', value);
+ }
+ },
+
+ toggle() {
+ if (!this.data.disabled) {
+ this.emitChange(!this.data.value);
+ }
+ },
+
+ onClickLabel() {
+ if (!this.data.disabled && !this.data.labelDisabled) {
+ this.emitChange(!this.data.value);
+ }
+ }
+ }
+});
diff --git a/packages/checkbox/index.wxml b/packages/checkbox/index.wxml
new file mode 100644
index 00000000..d320d0f3
--- /dev/null
+++ b/packages/checkbox/index.wxml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/packages/radio-group/index.less b/packages/radio-group/index.less
index ae41f459..e69de29b 100644
--- a/packages/radio-group/index.less
+++ b/packages/radio-group/index.less
@@ -1,55 +0,0 @@
-@import '../common/style/var.less';
-
-@van-radio-size: 20px;
-
-.van-radio {
- overflow: hidden;
- user-select: none;
-
- &__input,
- &__label {
- display: inline-block;
- vertical-align: middle;
- }
-
- &__input {
- height: 1em;
- position: relative;
- font-size: @van-radio-size;
- }
-
- &__control {
- z-index: 1;
- position: absolute;
- top: 0;
- left: 0;
- opacity: 0;
- margin: 0;
- width: 100%;
- height: 100%;
- }
-
- &__label {
- line-height: @van-radio-size;
- margin-left: 10px;
-
- &--left {
- float: left;
- margin: 0 10px 0 0;
- }
- }
-
- &__icon {
- width: 1em;
- pointer-events: none;
- &--disabled {
- color: @gray-light;
- }
- &--checked {
- color: @green;
- }
- &--check {
- color: @gray-dark;
- }
- }
-}