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,