diff --git a/example/app.js b/example/app.js index 0951a2d1..674c3fde 100644 --- a/example/app.js +++ b/example/app.js @@ -14,6 +14,7 @@ import HideSeconds from './demo/HideSeconds.vue'; import MinuteStep from './demo/MinuteStep.vue'; import FixedTimeList from './demo/FixedTimeList.vue'; import Disabled from './demo/Disabled.vue'; +import ShadowDom from './demo/ShadowDom.vue'; import docEn from './en.md'; import docZhCN from './zh-cn.md'; @@ -74,6 +75,11 @@ const components = [ component: ControlOpen, code: fs.readFileSync(`${__dirname}/demo/ControlOpen.vue`, 'utf8'), }, + { + id: 'ShadowDom', + component: ShadowDom, + code: fs.readFileSync(`${__dirname}/demo/ShadowDom.vue`, 'utf8'), + }, ]; function transformMd(text) { diff --git a/example/demo/ShadowDom.vue b/example/demo/ShadowDom.vue new file mode 100644 index 00000000..601aad59 --- /dev/null +++ b/example/demo/ShadowDom.vue @@ -0,0 +1,28 @@ + + + diff --git a/example/en.md b/example/en.md index 1f64814d..8e3c7fab 100644 --- a/example/en.md +++ b/example/en.md @@ -81,3 +81,9 @@ Set custom time options by `hourOptions` `minuteOptions` `secondOptions`. ### Select fixed time list You can provide a list of fixed time for users to choose by `timePickerOptions` + + + +### Shadow DOM + +If you use the component inside shadow DOM, you should set the `:append-to-body="false"`. diff --git a/example/zh-cn.md b/example/zh-cn.md index 6822ef58..550295de 100644 --- a/example/zh-cn.md +++ b/example/zh-cn.md @@ -81,3 +81,9 @@ ### 固定的时间列表 可以通过 `timePickerOptions` 提供一个固定的时间列表选择 + + + +### Shadow DOM + +If you use the component inside shadow DOM, you should set the `:append-to-body="false"`. diff --git a/src/popup.vue b/src/popup.vue index 731adf6d..d3dc5faf 100644 --- a/src/popup.vue +++ b/src/popup.vue @@ -37,6 +37,25 @@ export default { left: '', }; }, + computed: { + hasShadowParent() { + if (!document.head.attachShadow) { + return false; + } + + let element = this.$el; + + while (element) { + if (element instanceof ShadowRoot) { + return true; + } + + element = element.parentNode; + } + + return false; + }, + }, watch: { visible: { immediate: true, @@ -76,10 +95,18 @@ export default { }, methods: { handleClickOutside(evt) { - if (!this.visible) return; + if (!this.visible) { + return; + } + const { target } = evt; const el = this.$el; + if (el && !el.contains(target)) { + if (this.hasShadowParent && evt.composedPath().includes(el)) { + return; + } + this.$emit('clickoutside', evt); } },