From 7398ef14d8f0df7aaf8568360c300f31854bbe08 Mon Sep 17 00:00:00 2001 From: doly mood Date: Mon, 2 Apr 2018 15:19:11 +0800 Subject: [PATCH] Support Drawer * init * drawer item prop * drawer logic * lint * scroll add destroy * init drawer logic * test * clean code * test: done drawer * drawer check * drawer support get value default * update(demo): drawer log * Clean code * add drawer demo & doc --- document/common/config/menu.json | 6 +- document/components/docs/en-US/drawer.md | 192 ++++++++++++++++ document/components/docs/zh-CN/drawer.md | 194 ++++++++++++++++ document/components/docs/zh-CN/form.md | 6 +- example/App.vue | 4 + example/pages/drawer/custom.vue | 84 +++++++ example/pages/drawer/default.vue | 72 ++++++ example/pages/drawer/index.vue | 33 +++ example/router/routes.js | 17 ++ src/components/drawer/drawer-item.vue | 61 +++++ src/components/drawer/drawer-panel.vue | 98 ++++++++ src/components/drawer/drawer.vue | 212 ++++++++++++++++++ src/components/index-list/index-list-item.vue | 6 + src/components/scroll/scroll.vue | 4 + src/index.js | 4 +- src/module.js | 6 + src/modules/drawer/index.js | 14 ++ test/unit/specs/drawer.spec.js | 155 +++++++++++++ 18 files changed, 1162 insertions(+), 6 deletions(-) create mode 100644 document/components/docs/en-US/drawer.md create mode 100644 document/components/docs/zh-CN/drawer.md create mode 100644 example/pages/drawer/custom.vue create mode 100644 example/pages/drawer/default.vue create mode 100644 example/pages/drawer/index.vue create mode 100644 src/components/drawer/drawer-item.vue create mode 100644 src/components/drawer/drawer-panel.vue create mode 100644 src/components/drawer/drawer.vue create mode 100644 src/modules/drawer/index.js create mode 100644 test/unit/specs/drawer.spec.js diff --git a/document/common/config/menu.json b/document/common/config/menu.json index dda19bca..7e0ef097 100644 --- a/document/common/config/menu.json +++ b/document/common/config/menu.json @@ -42,7 +42,8 @@ "cascade-picker": "CascadePicker", "time-picker": "TimePicker", "dialog": "Dialog", - "action-sheet": "ActionSheet" + "action-sheet": "ActionSheet", + "drawer": "Drawer" } }, "scroll": { @@ -117,7 +118,8 @@ "time-picker": "TimePicker", "segment-picker": "SegmentPicker", "dialog": "Dialog", - "action-sheet": "ActionSheet" + "action-sheet": "ActionSheet", + "drawer": "Drawer" } }, "scroll": { diff --git a/document/components/docs/en-US/drawer.md b/document/components/docs/en-US/drawer.md new file mode 100644 index 00000000..6927f666 --- /dev/null +++ b/document/components/docs/en-US/drawer.md @@ -0,0 +1,192 @@ +## Drawer + +Drawer, this component is used to select item in many items, it used full-page panels to interaction normally. + +### Demo + +- Default usage + + ```html + Show Drawer + + ``` + ```js + import { provinceList, cityList, areaList } from '../../data/area' + export default { + data() { + return { + selectedIndex: [], + data: [ + provinceList, + [], + [] + ] + } + }, + methods: { + showDrawer() { + this.$refs.drawer.show() + }, + changeHandler(index, item, selectedVal, selectedIndex) { + // fake request + setTimeout(() => { + let data + if (index === 0) { + // procince change, get city data + data = cityList[item.value] + } else { + // city change, get area data + data = areaList[item.value] + } + // refill panel(index + 1) data + this.$refs.drawer.refill(index + 1, data) + }, 200) + }, + selectHandler(selectedVal, selectedIndex) { + console.log('select', selectedVal, selectedIndex) + }, + cancelHandler() { + console.log('cancel') + } + } + } + ``` + + `title` is the drawer's title, optional; `data` source, an array with array items; `selected-index` is the initial index of the selected value; `change`、`select`、`cancel` are events: when selected item changed (the selected item is not in the last Panel)、when selected one item (the item is in the last Panel)、cancel (when clicked the left empty area). + + You can use Drawer's `fill` method to update next Panel's data. + +- Custom usage + + You can use slots to define your own HTML structure. + + ```html + + {{province.text}} + + + + {{item.text}} + + + + ``` + ```js + import { provinceList, cityList, areaList } from '../../data/area' + export default { + data() { + return { + province: {}, + selectedIndex: [], + data: [ + [], + [] + ] + } + }, + methods: { + showDrawer() { + // get radom province + const randomIndex = Math.round(Math.random() * provinceList.length) + const randomProvince = provinceList[randomIndex] + this.province = randomProvince + this.$refs.drawer.refill(0, cityList[randomProvince.value]) + this.$refs.drawer.show() + }, + changeHandler(index, item, selectedVal, selectedIndex) { + setTimeout(() => { + // city change, get area data + const data = areaList[item.value] + this.$refs.drawer.refill(index + 1, data) + }, 200) + }, + selectHandler(selectedVal, selectedIndex) { + console.log('select', selectedVal, selectedIndex) + }, + cancelHandler() { + console.log('cancel') + } + } + } + ``` + + You can use `cube-drawer-panel` and `cube-drawer-item` in `cube-drawer`. + +### Props + +#### CubeDrawer + +| Attribute | Description | Type | Accepted Values | Default | +| - | - | - | - | - | +| title | title | String | - | '' | +| data | data source | Array | - | [] | +| selected-index | initial selected index | Array | - | [] | + +- `data` sub configuration + + It is an array and it's items is Array too, eg: + + ```js + [ + [ + { + text: 'text', + value: 'value' + }, + ... + ], + [ + 'text', + 'text2', + ... + ] + ] + ``` + +#### CubeDrawerPanel + +| Attribute | Description | Type | Accepted Values | Default | +| - | - | - | - | - | +| data | data source | Array | - | [] | +| index | the data source index in CubeDrawer's data | Number | - | -1 | + +#### CubeDrawerItem + +| Attribute | Description | Type | Accepted Values | Default | +| - | - | - | - | - | +| data | item data | String/Object | - | '' | +| index | the item index in CubeDrawerPanel's data | Number | - | -1 | + +### Events + +| Event Name | Description | Parameters 1 | Parameters 2 | Parameters 3 | Parameters 4 | +| - | - | - | - | - | - | +| change | when selected item changed (the selected item is not in the last Panel) | current Panel index | changed item | selectedVal: Array, selected item values of each panels | selectedIndex: Array, selected indexes of each panels | +| select | when selected one item (the item is in the last Panel) | selectedVal: Array, selected item values of each panels | selectedIndex: Array, selected indexes of each panels | - | - | +| cancel | when clicked the left empty area | - | - | - | - | + +### Instance methods + +| Method name | Description | Parameters 1 | Parameters 2 | Parameters 3 | +| - | - | - | - | - | +| show | show | - | - | - | +| hide | hide | - | - | - | +| refill | refill data, change one Panel's data source | the Panel index | the data source | default selected index (Optional, recommended do not specify a value) | diff --git a/document/components/docs/zh-CN/drawer.md b/document/components/docs/zh-CN/drawer.md new file mode 100644 index 00000000..360296e4 --- /dev/null +++ b/document/components/docs/zh-CN/drawer.md @@ -0,0 +1,194 @@ +## Drawer + +抽屉,主要用来需要大范围层级进行选择的场景,一般情况下应该是满屏状态。 + +### 示例 + +- 默认配置使用 + + ```html + Show Drawer + + ``` + ```js + import { provinceList, cityList, areaList } from '../../data/area' + export default { + data() { + return { + selectedIndex: [], + data: [ + provinceList, + [], + [] + ] + } + }, + methods: { + showDrawer() { + this.$refs.drawer.show() + }, + changeHandler(index, item, selectedVal, selectedIndex) { + // fake request + setTimeout(() => { + let data + if (index === 0) { + // procince change, get city data + data = cityList[item.value] + } else { + // city change, get area data + data = areaList[item.value] + } + // refill panel(index + 1) data + this.$refs.drawer.refill(index + 1, data) + }, 200) + }, + selectHandler(selectedVal, selectedIndex) { + console.log('select', selectedVal, selectedIndex) + }, + cancelHandler() { + console.log('cancel') + } + } + } + ``` + + `title` 就是标题,可选;`data` 数据源,二维数组,长度决定了抽屉的 Panel 数,初始长度一定要确定;`selected-index` 则是初始选择的索引值;`change`、`select`、`cancel` 则是对应的三个事件:选择发生改变(选中是非最后一个 Panel 中的项的时候触发)、选中了某个值(选择了最后一个 Panel 中的项触发)、取消(点击左侧空白蒙层触发)。 + + 你可以在 `change` 中通过 Drawer 的 `fill` 方法更新下一个 Panel 的数据,可以是同步更新也可以是异步更新。 + +- 自定义使用 + + 你可以通过插槽来自定义结构。 + + ```html + + {{province.text}} + + + + {{item.text}} + + + + ``` + ```js + import { provinceList, cityList, areaList } from '../../data/area' + export default { + data() { + return { + province: {}, + selectedIndex: [], + data: [ + [], + [] + ] + } + }, + methods: { + showDrawer() { + // get radom province + const randomIndex = Math.round(Math.random() * provinceList.length) + const randomProvince = provinceList[randomIndex] + this.province = randomProvince + this.$refs.drawer.refill(0, cityList[randomProvince.value]) + this.$refs.drawer.show() + }, + changeHandler(index, item, selectedVal, selectedIndex) { + setTimeout(() => { + // city change, get area data + const data = areaList[item.value] + this.$refs.drawer.refill(index + 1, data) + }, 200) + }, + selectHandler(selectedVal, selectedIndex) { + console.log('select', selectedVal, selectedIndex) + }, + cancelHandler() { + console.log('cancel') + } + } + } + ``` + + 可以在 `cube-drawer` 组件中使用 `cube-drawer-panel` 以及 `cube-drawer-item` 组件来达到某些情况下的自定义目的。 + +### Props 配置 + +#### CubeDrawer + +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| - | - | - | - | - | +| title | 标题 | String | - | '' | +| data | 数据源 | Array | - | [] | +| selected-index | 初始选择索引 | Array | - | [] | + +- `data` 子配置项 + + 是一个数组,数组中每一项仍然为数组,结构类似于: + + ```js + [ + [ + { + text: 'text', + value: 'value' + }, + ... + ], + [ + 'text', + 'text2', + ... + ] + ] + ``` + + 里层数组的每一项可以是对象(包含 text 和 value),也可以是纯字符串。 + +#### CubeDrawerPanel + +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| - | - | - | - | - | +| data | 数据源 | Array | - | [] | +| index | 该数据源在 CubeDrawer 的 data 中的索引值 | Number | - | -1 | + +#### CubeDrawerItem + +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| - | - | - | - | - | +| data | 数据项 | String/Object | - | '' | +| index | 该数据项在 CubeDrawerPanel 的 data 中的索引值 | Number | - | -1 | + +### 事件 + +| 事件名 | 说明 | 参数1 | 参数2 | 参数3 | 参数4 | +| - | - | - | - | - | - | +| change | 选择发生改变(选中是非最后一个 Panel 中的项的时候触发) | 发生改变的 Panel 的索引 | 发生改变的数据项 | 已选中的值集合 | 已选中的索引集合 | +| select | 选择了最后一个 Panel 中的项触发 | 已选中的值集合 | 已选中的索引集合 | - | - | +| cancel | 点击左侧空白区域触发 | - | - | - | - | + +### 实例方法 + +| 方法名 | 说明 | 参数1 | 参数2 | 参数3 | +| - | - | - | - | - | +| show | 显示 | - | - | - | +| hide | 隐藏 | - | - | - | +| refill | 填充数据,改变某个 Panel 数据 | 要改变的 Panel 的索引 | 填充数据 | 默认选中项(可选,建议不填) | diff --git a/document/components/docs/zh-CN/form.md b/document/components/docs/zh-CN/form.md index fa77d6f3..1c16129a 100644 --- a/document/components/docs/zh-CN/form.md +++ b/document/components/docs/zh-CN/form.md @@ -310,7 +310,7 @@ ### Props 配置 -#### Form +#### CubeForm | 参数 | 说明 | 类型 | 可选值 | 默认值 | | - | - | - | - | - | @@ -386,14 +386,14 @@ | rules | 字段的校验规则,参见 Validator | Object | - | - | | messages | 字段的校验消息,参见 Validator | String | - | - | -#### FormGroup +#### CubeFormGroup | 参数 | 说明 | 类型 | 可选值 | 默认值 | | - | - | - | - | - | | legend | 分组名字 | String | - | '' | | fields | 该组内所包含的字段集合 | Array | - | [] | -#### FormItem +#### CubeFormItem | 参数 | 说明 | 类型 | 可选值 | 默认值 | | - | - | - | - | - | diff --git a/example/App.vue b/example/App.vue index 0f19b89e..cdd1ae2c 100644 --- a/example/App.vue +++ b/example/App.vue @@ -131,6 +131,10 @@ { path: '/swipe', text: 'Swipe' + }, + { + path: '/drawer', + text: 'Drawer' } ] } diff --git a/example/pages/drawer/custom.vue b/example/pages/drawer/custom.vue new file mode 100644 index 00000000..9f831f8d --- /dev/null +++ b/example/pages/drawer/custom.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/example/pages/drawer/default.vue b/example/pages/drawer/default.vue new file mode 100644 index 00000000..8b411680 --- /dev/null +++ b/example/pages/drawer/default.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/example/pages/drawer/index.vue b/example/pages/drawer/index.vue new file mode 100644 index 00000000..07afff65 --- /dev/null +++ b/example/pages/drawer/index.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/example/router/routes.js b/example/router/routes.js index 08591f23..4dc3e41a 100644 --- a/example/router/routes.js +++ b/example/router/routes.js @@ -30,6 +30,9 @@ import Validator from '../pages/validator.vue' import Swipe from '../pages/swipe/index.vue' import SwipeDefault from '../pages/swipe/default.vue' import SwipeCustom from '../pages/swipe/custom.vue' +import Drawer from '../pages/drawer/index.vue' +import DrawerDefault from '../pages/drawer/default.vue' +import DrawerCustom from '../pages/drawer/custom.vue' import Slide from '../pages/slide/index.vue' import SlideVertical from '../pages/slide/vertical.vue' import SlideHorizontal from '../pages/slide/horizontal.vue' @@ -169,6 +172,20 @@ const routes = [ } ] }, + { + path: '/drawer', + component: Drawer, + children: [ + { + path: 'default', + component: DrawerDefault + }, + { + path: 'custom', + component: DrawerCustom + } + ] + }, { path: '/slide', component: Slide, diff --git a/src/components/drawer/drawer-item.vue b/src/components/drawer/drawer-item.vue new file mode 100644 index 00000000..0bbc79dd --- /dev/null +++ b/src/components/drawer/drawer-item.vue @@ -0,0 +1,61 @@ + + + + diff --git a/src/components/drawer/drawer-panel.vue b/src/components/drawer/drawer-panel.vue new file mode 100644 index 00000000..6d39001f --- /dev/null +++ b/src/components/drawer/drawer-panel.vue @@ -0,0 +1,98 @@ + + + + diff --git a/src/components/drawer/drawer.vue b/src/components/drawer/drawer.vue new file mode 100644 index 00000000..3584f13d --- /dev/null +++ b/src/components/drawer/drawer.vue @@ -0,0 +1,212 @@ + + + + diff --git a/src/components/index-list/index-list-item.vue b/src/components/index-list/index-list-item.vue index cb71cda5..294dc13f 100644 --- a/src/components/index-list/index-list-item.vue +++ b/src/components/index-list/index-list-item.vue @@ -1,6 +1,7 @@