diff --git a/example/app.json b/example/app.json index c4bdc15e..5705f003 100644 --- a/example/app.json +++ b/example/app.json @@ -1,6 +1,7 @@ { "pages": [ "pages/dashboard/index", + "pages/actionsheet/index", "pages/btn/index", "pages/badge/index", "pages/capsule/index", diff --git a/example/pages/actionsheet/index.js b/example/pages/actionsheet/index.js new file mode 100644 index 00000000..b28c57df --- /dev/null +++ b/example/pages/actionsheet/index.js @@ -0,0 +1,51 @@ +const { Actionsheet, extend } = require('../../dist/index'); + +Page(extend({}, Actionsheet, { + data: { + baseActionsheet: { + show: false, + cancelText: '关闭 Action', + closeOnClickOverlay: true, + componentId: 'baseActionsheet', + actions: [{ + name: '选项1', + subname: '选项描述语1', + className: 'action-class', + loading: false + }, { + name: '选项2', + subname: '选项描述语2', + className: 'action-class', + loading: false + }] + } + }, + + toggleActionsheet() { + this.setData({ + 'baseActionsheet.show': true + }); + }, + + handleZanActionsheetCancel({ componentId }) { + this.setData({ + [`${componentId}.show`]: false + }); + }, + + handleZanActionsheetClick({ componentId, index }) { + console.log(`item index ${index} clicked`); + + this.setData({ + [`${componentId}.actions[${index}].loading`]: true + }); + + setTimeout(() => { + this.setData({ + [`${componentId}.show`]: false, + [`${componentId}.actions[${index}].loading`]: false + }); + }, 1500); + } + +})); diff --git a/example/pages/actionsheet/index.json b/example/pages/actionsheet/index.json new file mode 100644 index 00000000..175d8120 --- /dev/null +++ b/example/pages/actionsheet/index.json @@ -0,0 +1,3 @@ +{ + "navigationBarTitleText": "Actionsheet 行动按钮" +} diff --git a/example/pages/actionsheet/index.wxml b/example/pages/actionsheet/index.wxml new file mode 100644 index 00000000..52c5659d --- /dev/null +++ b/example/pages/actionsheet/index.wxml @@ -0,0 +1,15 @@ + + + + + ACTIONSHEET + + + + + + + + diff --git a/example/pages/dashboard/config.js b/example/pages/dashboard/config.js index 73e1f07d..42029869 100644 --- a/example/pages/dashboard/config.js +++ b/example/pages/dashboard/config.js @@ -72,6 +72,9 @@ export default { title: '操作反馈', content: [ { + name: 'Actionsheet 行动按钮', + path: '/pages/actionsheet/index' + }, { name: 'Dialog 弹出框', path: '/pages/dialog/index' }, { diff --git a/packages/actionsheet/README.md b/packages/actionsheet/README.md new file mode 100644 index 00000000..881f1453 --- /dev/null +++ b/packages/actionsheet/README.md @@ -0,0 +1,78 @@ +## Actionsheet 行动按钮 + +### 使用指南 +在 app.wxss 中引入组件库所有样式 +```css +@import "path/to/zanui-weapp/dist/index.wxss"; +``` + +在需要使用的页面里引入组件库模板和脚本 +```html + + + +``` +```js +const { Actionsheet, extend } = require('path/to/zanui-weapp/dist/index'); + +// 在 Page 中混入 Actionsheet 里面声明的方法 +Page(extend({}, Actionsheet, { + data: { + actionsheet: { + show: false, + actions: [] + } + } + // ... +})); +``` + +### 代码演示 +#### 基础功能 +在 js 中设置传入的 show 为 true,即可展示出 actionsheet。actionsheet 会根据传入的 actions 展示按钮。 +```js +this.setData({ + 'actionsheet.show': true +}) +``` + +当行动按钮被点击或者弹层被关掉时,都可以在可以在页面中注册 `handleZanActionsheetClick` 和 `handleZanActionsheetCancel` 方法来监听。 +```js +Page({ + // 当行动按钮被关闭时,触发该函数 + // componentId 即为在模板中传入的 componentId + // 用于在一个页面上使用多个 actionsheet 时,进行区分 + handleZanActionsheetCancel({ componentId }) { + }, + + // 当行动按钮中有一个被点击时触发 + // index 代表被点击按钮在传入参数 actions 中的位置 + handleZanActionsheetClick({ componentId, index }) { + } +}); +``` + +#### `Actionsheet` 支持的具体参数如下 +| 参数 | 说明 | 类型 | 默认值 | 必须 | +|-----------|-----------|-----------|-------------|-------------| +| show | 用来表示是否展示行动按钮 | Boolean | false | | +| cancelText | 行动按钮底部取消按钮的文案,不传则不显示取消按钮 | String | | | +| closeOnClickOverlay | 是否在点击背景时,关闭行动按钮 | Boolean | false | | +| componentId | 用于区分行动按钮之间的唯一名称 | String | | | +| actions | 行动按钮的按钮显示配置 | Array | [] | | + +actions 的具体数据结构 +```js +// actions 为数组结构传入 +[{ + // 按钮文案 + name: '选项1', + // 按钮描述文案,不传就不显示 + subname: '选项描述语1', + // 按钮特殊类,可以通过传入这个,为按钮增加特殊样式 + className: 'action-class', + // 按钮是否显示为 loading + loading: false +}] +``` + diff --git a/packages/actionsheet/index.js b/packages/actionsheet/index.js new file mode 100644 index 00000000..02a64544 --- /dev/null +++ b/packages/actionsheet/index.js @@ -0,0 +1,41 @@ +const { extractComponentId } = require('../common/helper'); + +module.exports = { + _handleZanActionsheetMaskClick({ currentTarget = {} }) { + const dataset = currentTarget.dataset || {}; + const { componentId, closeOnClickOverlay } = dataset; + + // 判断是否在点击背景时需要关闭弹层 + if (!closeOnClickOverlay) { + return; + } + + resolveCancelClick.call(this, { componentId }); + }, + + _handleZanActionsheetCancelBtnClick(e) { + const componentId = extractComponentId(e); + + resolveCancelClick.call(this, { componentId }); + }, + + _handleZanActionsheetBtnClick({ currentTarget = {} }) { + const dataset = currentTarget.dataset || {}; + const { componentId, index } = dataset; + + if (this.handleZanActionsheetClick) { + this.handleZanActionsheetClick({ componentId, index }); + } else { + console.warn('页面缺少 handleZanActionsheetClick 回调函数'); + } + } +}; + +function resolveCancelClick({ componentId }) { + console.info('[zan:actionsheet:cancel]'); + if (this.handleZanActionsheetCancel) { + this.handleZanActionsheetCancel({ componentId }); + } else { + console.warn('页面缺少 handleZanActionsheetCancel 回调函数'); + } +} diff --git a/packages/actionsheet/index.pcss b/packages/actionsheet/index.pcss new file mode 100644 index 00000000..349c2642 --- /dev/null +++ b/packages/actionsheet/index.pcss @@ -0,0 +1,71 @@ +@import "../common/_var"; +@import "../common/_mixins"; + +.zan-actionsheet { + background-color: #f8f8f8; +} + +.zan-actionsheet__mask { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 10; + background: rgba(0, 0, 0, 0.7); + display: none; +} + +.zan-actionsheet__container { + position: fixed; + left: 0; + right: 0; + bottom: 0; + background: $background-color; + transform: translate3d(0, 50%, 0); + transform-origin: center; + transition: all 0.2s ease; + z-index: 11; + opacity: 0; +} + +.zan-actionsheet__btn.zan-btn { + height: 50px; + line-height: 50px; + margin-bottom: 0; + + &::after { + border-width: 0; + border-bottom-width: 1px; + } +} + +.zan-actionsheet__btn.zan-btn:last-child { + &::after { + border-bottom-width: 0; + } +} + +.zan-actionsheet__subname { + margin-left: 2px; + font-size: 12px; + color: $gray-darker; +} + +.zan-actionsheet__footer { + margin-top: 10px; +} + +/* btn-loading 状态 */ +.zan-actionsheet__btn.zan-btn--loading .zan-actionsheet__subname { + color: transparent; +} + +/* zan-actionsheet 展示出来的样式 */ +.zan-actionsheet--show .zan-actionsheet__container { + opacity: 1; + transform: translate3d(0, 0, 0); +} +.zan-actionsheet--show .zan-actionsheet__mask { + display: block; +} diff --git a/packages/actionsheet/index.wxml b/packages/actionsheet/index.wxml new file mode 100644 index 00000000..9c77dddf --- /dev/null +++ b/packages/actionsheet/index.wxml @@ -0,0 +1,39 @@ + diff --git a/packages/index.js b/packages/index.js index ebfb8bbc..24195ba4 100644 --- a/packages/index.js +++ b/packages/index.js @@ -1,3 +1,4 @@ +exports.Actionsheet = require('./actionsheet/index'); exports.CheckLabel = require('./select/index'); exports.Dialog = require('./dialog/index'); exports.Field = require('./field/index'); diff --git a/packages/index.pcss b/packages/index.pcss index 6a4e0079..95916492 100644 --- a/packages/index.pcss +++ b/packages/index.pcss @@ -1,3 +1,4 @@ +@import "actionsheet/index.pcss"; @import "badge/index.pcss"; @import "btn/index.pcss"; @import "capsule/index.pcss";