虽然我没用过Element-UI
,但是我在别人的项目里见过,Element-UI 里有个element-ui/src/utils/clickoutside
,我觉得这个很好用
不过还没支持 vue3,虽然我不用 Element-UI,但是的想用里面的 clickoutside.js,我不可用为了一个功能而去安装整个框架
想着把这个功能提取出来用,提取的时候发现,它压根就不能在 vue3 中使用,只能在 vue2 中使用
随后就直接着手自己用原生 js 写了一个(我是 vue 新手,很多东西都不是很懂)
浏览器
核心代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
function Clickoutside(targetEle, callback, currentEle = null, clean = true) { document.onclick = function (event) { const isTargetEle = targetEle.contains(event.target); const isCurrentEle = currentEle ? currentEle.contains(event.target) : false; if (isTargetEle || isCurrentEle) return; callback(); if (clean) document.onclick = null; }; }
|
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <div class="wrap"> <div class="external"> <span> 外部元素</span> </div> <div class="inside"> <span>内部元素</span> </div> </div>
<script>
function Clickoutside(targetEle, callback, currentEle = null, clean = true) { document.onclick = function (event) { const isTargetEle = targetEle.contains(event.target); const isCurrentEle = currentEle ? currentEle.contains(event.target) : false; if (isTargetEle || isCurrentEle) return; callback(); if (clean) document.onclick = null; }; }
const inside = document.querySelector(".inside"); Clickoutside(inside, () => { inside.style.background = "#" + Math.random().toString(16).substr(2, 6).toUpperCase(); },inside,false); </script>
|
Vue
修改为Vue指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| <template> <div class="wrap"> <div class="external"> <span> 外部元素</span> </div> <div class="inside" v-Clickoutside="discolor"> <span>内部元素</span> </div> </div> </template>
<script> export default { methods: { discolor(event) { const color = '#' + Math.random().toString(16).substr(2, 6).toUpperCase() console.log('修改当前点击元素背景颜色', color) event.target.style.background = color } }, directives: { Clickoutside: { beforeMount(el, binding) { function Clickoutside(event) { const isTargetEle = el.contains(event.target) if (isTargetEle) return binding.value(event) } document.addEventListener('click', Clickoutside) } } } } </script>
|
由于使用vue指令实现的功能有限(无法向自定义指令内传值,由于我是vue新手可能对vue还不是很了解吧),无法达到我需要的效果,所有我使用了调用方法的方式来完成
其主要是先点击某个按钮后显示另一个元素,当我点击这个元素内的任何内容都不会关闭,而如果点击该元素外的元素后就会关闭,目前我只能用这种办法实现了,如果你知道如何处理,欢迎在评论区与我交流,谢谢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <template> <div> <div @click="toggle($event)">切换</div> <div v-show="opened" ref="popup">弹窗</div> </div> </template>
<script>
function Clickoutside(targetEle, callback, currentEle = null, clean = true) { document.onclick = function (event) { const isTargetEle = targetEle.contains(event.target) const isCurrentEle = currentEle ? currentEle.contains(event.target) : false if (isTargetEle || isCurrentEle) return callback() if (clean) document.onclick = null } }
export default { data() { return { opened: false } },
methods: { toggle(event) { this.opened=! this.opened Clickoutside(this.$refs.popup, () => { this.opened = false },event.target) } } } </script>
|