diff --git a/src/popover/README.zh-CN.md b/src/popover/README.zh-CN.md index 3b582b61f..cbdb6af8f 100644 --- a/src/popover/README.zh-CN.md +++ b/src/popover/README.zh-CN.md @@ -29,10 +29,8 @@ Vue.use(Popover); | actions | 选项列表 | _Action[]_ | `[]` | | placement | 弹出位置 | _string_ | - | | theme | 主题风格,可选值为 `dark` | _string_ | `light` | -| text-color | 自定义文字颜色 | _string_ | - | -| background-color | 自定义背景颜色 | _string_ | - | | overlay | 是否显示遮罩层 | _boolean_ | `false` | -| close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `false` | +| close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `true` | | close-on-click-outside | 是否在点击外部元素后关闭菜单 | _boolean_ | `true` | | get-container `v2.4.4` | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | _string \| () => Element_ | - | @@ -40,10 +38,11 @@ Vue.use(Popover); `actions` 属性是一个由对象构成的数组,数组中的每个对象配置一列,对象可以包含以下值: -| 键名 | 说明 | 类型 | -| --------- | ------------------------ | -------- | -| text | 文字内容 | _string_ | -| className | 为对应选项添加额外的类名 | _any_ | +| 键名 | 说明 | 类型 | +| --- | --- | --- | +| text | 文字内容 | _string_ | +| icon | 文字左侧的图标,支持传入[图标名称](#/zh-CN/icon)或图片链接 | _string_ | +| className | 为对应选项添加额外的类名 | _any_ | ### placement 可选值 diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue index fa57dfdad..2f4ea5762 100644 --- a/src/popover/demo/index.vue +++ b/src/popover/demo/index.vue @@ -52,13 +52,26 @@
+ + + + + {{ t('showPopover') }} + + + @@ -66,7 +79,14 @@ export default { i18n: { 'zh-CN': { - actions: [{ text: '文本' }, { text: '文本' }, { text: '文本' }], + actions: [{ text: '选项一' }, { text: '选项二' }, { text: '选项三' }], + shortActions: [{ text: '选项一' }, { text: '选项二' }], + actionsWithIcon: [ + { text: '选项一', icon: 'add-o' }, + { text: '选项二', icon: 'music-o' }, + { text: '选项三', icon: 'more-o' }, + ], + showIcon: '展示图标', placement: '弹出位置', darkTheme: '深色风格', lightTheme: '浅色风格', @@ -74,7 +94,18 @@ export default { choosePlacement: '选择弹出位置', }, 'en-US': { - actions: [{ text: 'Text' }, { text: 'Text' }, { text: 'Text' }], + actions: [ + { text: 'Option 1' }, + { text: 'Option 2' }, + { text: 'Option 3' }, + ], + shortActions: [{ text: 'Option 1' }, { text: 'Option 2' }], + actionsWithIcon: [ + { text: 'Option 1', icon: 'add-o' }, + { text: 'Option 2', icon: 'music-o' }, + { text: 'Option 3', icon: 'more-o' }, + ], + showIcon: 'Show Icon', placement: 'Placement', darkTheme: 'Dark Theme', lightTheme: 'Light Theme', @@ -86,6 +117,7 @@ export default { data() { return { show: { + showIcon: false, placement: false, darkTheme: false, lightTheme: false, @@ -139,7 +171,7 @@ export default { &-box { display: flex; justify-content: center; - margin-top: 160px; + margin: 110px 0 80px; } } diff --git a/src/popover/index.js b/src/popover/index.js index 981b89862..775cc1b3c 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -1,10 +1,12 @@ -import { createNamespace } from '../utils'; import { createPopper } from '@popperjs/core'; +import { createNamespace } from '../utils'; +import { BORDER_BOTTOM } from '../utils/constant'; // Mixins import { ClickOutsideMixin } from '../mixins/click-outside'; // Components +import Icon from '../icon'; import Popup from '../popup'; const [createComponent, bem] = createNamespace('popover'); @@ -23,7 +25,6 @@ export default createComponent({ placement: String, textColor: String, backgroundColor: String, - closeOnClickAction: Boolean, offset: { type: Array, default: () => [0, 8], @@ -40,6 +41,10 @@ export default createComponent({ type: [String, Function], default: 'body', }, + closeOnClickAction: { + type: Boolean, + default: true, + }, }, data() { @@ -64,31 +69,55 @@ export default createComponent({ } }, + beforeDestroy() { + if (this.popper) { + this.popper.destroy(); + this.popper = null; + } + }, + methods: { + createPopper() { + return createPopper(this.$refs.wrapper, this.$refs.popover.$el, { + placement: this.placement, + modifiers: [ + { + name: 'computeStyles', + options: { + adaptive: false, + }, + }, + { + name: 'offset', + options: { + offset: this.offset, + }, + }, + ], + }); + }, + updateLocation() { this.$nextTick(() => { - createPopper(this.$refs.wrapper, this.$refs.popover.$el, { - placement: this.placement, - modifiers: [ - { - name: 'computeStyles', - options: { - adaptive: false, - }, - }, - { - name: 'offset', - options: { - offset: this.offset, - }, - }, - ], - }); + if (!this.popper) { + this.popper = this.createPopper(); + } else { + this.popper.setOptions({ + placement: this.placement, + }); + } }); }, renderAction(action) { - return
{action.text}
; + return ( +
+ {action.icon && ( + + )} +
{action.text}
+
+ ); }, onToggle(value) { diff --git a/src/popover/index.less b/src/popover/index.less index 7f8a4fb7a..5ef0cc9c4 100644 --- a/src/popover/index.less +++ b/src/popover/index.less @@ -24,23 +24,32 @@ position: relative; display: flex; align-items: center; - justify-content: center; + box-sizing: border-box; width: 128px; height: 44px; + padding: 0 @padding-md; font-size: @font-size-md; - &::after { - .hairline-bottom(@cell-border-color, @padding-md, @padding-md); + &:last-child { + .van-popover__action-text::after { + display: none; + } } - &:last-child::after { - display: none; + &-text { + display: flex; + flex: 1; + align-items: center; + justify-content: center; + height: 100%; + } + + &-icon { + font-size: 16px; } } - &--placement-top, - &--placement-top-start, - &--placement-top-end { + &[data-popper-placement^='top'] { .van-popover__arrow { bottom: 0; border-top-color: currentColor; @@ -49,27 +58,25 @@ } } - &--placement-top { + &[data-popper-placement='top'] { .van-popover__arrow { left: 50%; } } - &--placement-top-start { + &[data-popper-placement='top-start'] { .van-popover__arrow { left: @padding-md; } } - &--placement-top-end { + &[data-popper-placement='top-end'] { .van-popover__arrow { right: @padding-md; } } - &--placement-left, - &--placement-left-start, - &--placement-left-end { + &[data-popper-placement^='left'] { .van-popover__arrow { right: 0; border-right-width: 0; @@ -78,27 +85,25 @@ } } - &--placement-left { + &[data-popper-placement='left'] { .van-popover__arrow { top: 50%; } } - &--placement-left-start { + &[data-popper-placement='left-start'] { .van-popover__arrow { top: @padding-md; } } - &--placement-left-end { + &[data-popper-placement='left-end'] { .van-popover__arrow { bottom: @padding-md; } } - &--placement-right, - &--placement-right-start, - &--placement-right-end { + &[data-popper-placement^='right'] { .van-popover__arrow { left: 0; border-right-color: currentColor; @@ -107,27 +112,25 @@ } } - &--placement-right { + &[data-popper-placement='right'] { .van-popover__arrow { top: 50%; } } - &--placement-right-start { + &[data-popper-placement='right-start'] { .van-popover__arrow { top: @padding-md; } } - &--placement-right-end { + &[data-popper-placement='right-end'] { .van-popover__arrow { bottom: @padding-md; } } - &--placement-bottom, - &--placement-bottom-start, - &--placement-bottom-end { + &[data-popper-placement^='bottom'] { .van-popover__arrow { top: 0; border-top-width: 0; @@ -136,19 +139,19 @@ } } - &--placement-bottom { + &[data-popper-placement='bottom'] { .van-popover__arrow { left: 50%; } } - &--placement-bottom-start { + &[data-popper-placement='bottom-start'] { .van-popover__arrow { left: @padding-md; } } - &--placement-bottom-end { + &[data-popper-placement='bottom-end'] { .van-popover__arrow { right: @padding-md; } @@ -180,14 +183,16 @@ } .van-popover__action { - &::after { - border-color: @gray-7; - } - &:active { opacity: @active-opacity; } } + + .van-popover__action-text { + &::after { + border-color: @gray-7; + } + } } // &-zoom-enter,