使用vue开发popover组件接连踩坑过程实录

ps:只是说明思路,生产中不采用此方式

html代码:

<div id='app'>    
    <g-popover>        
        <template slot="content">            
            <div>popover里面的内容div>        
        template>        
    <button>点击button>    
g-popover>div>复制代码

vue组件代码:


复制代码

通过给按钮添加click方法,切换visible的值来控制文本的显示与隐藏


接下来实现点击空白部分关闭popover,

最容易想到的思路是在切换visible时监听document的click事件

// 建议监听document而不是document.body,否则关闭区域会受body高度影响

onClick(){                this.visible = !this.visible                if(this.visible === true){                document.addEventListener('click',()=>{                    this.visible = false                })            }复制代码

这时会发现popover没有出现,我们来看log

onClick(){                this.visible = !this.visible                console.log('改变visible的值')                if(this.visible === true){                document.addEventListener('click',()=>{                    console.log('点击document隐藏popover')                    this.visible = false                })            }复制代码

浏览器控制台


两个log依次执行,所以popover刚开启就被关闭了

改用异步代码

if (this.visible === true) {        setTimeout(() => {          document.addEventListener("click", () => {            console.log("点击document隐藏popover");            this.visible = false;          });        }, 500);      }复制代码

多点击几次,会发现popover组件出问题了,点击一次会执行很多次log

分析代码会发现,我们没有清除click事件队列,导致事件越来越多


在popover隐藏后要清除click事件,为了方便,改写剪头函数,并绑定this

if (this.visible === true) {        setTimeout(() => {          document.addEventListener("click", function x(){            console.log("点击document隐藏popover");            this.visible = false;            document.removeEventListener('click',x)          }.bind(this));        }, 500);      }复制代码

结果发现,事件监听队列还是继续叠加,好像并没有成功的删除监听器

这是因为x.bind会生成一个新的函数,所以我们添加的函数和我们的删除的函数并不是同一个

解决方法是给箭头函数取一个名字

if (this.visible === true) {        setTimeout(() => {            let eventHandler = ()=>{                this.visible = false;                console.log('点击document关闭popover')                document.removeEventListener('click',eventHandler)            }            document.addEventListener("click", eventHandler);        });      }复制代码

浏览器控制台


好了,暂时解决了一个bug

另一个细节是popover出现后,点击button按钮会隐藏两次popover

第一次是button按钮点击后,切换visible的值,组件自身隐藏popover

同时button按钮也在document区域内,点击按钮同样会触发事件队列,再隐藏一次popover

另一个bug是点击popover区域也会隐藏popover

这明显是不合理的,如果用户要复制popover里面的内容怎么办?

上面两个问题都可以通过阻止冒泡解决

click.stop解决bug的同时也会带来新的问题,就是用户无法给button添加click事件,所以这不是最终解决办法,同时popover不应该和button放在同一层级,否则用户写一个overflow:hidden,

popover就无法正确出现了





转载于:https://juejin.im/post/5cff1aa051882523e37696cb

你可能感兴趣的:(javascript)