1. 现在遇到的问题
- 如果在popover外面包了个div写上overflow:hidden就会出bug,所以要把弹出的div放到按钮的同一个层级
- 关于click事件的,之前解决的方式是写click.stop,但是其实还是会有bug,会打断用户的事件链,用户在外面写@click,点击按钮没有用,但是点击按钮周围空白区域会有,那么就会导致别人用了组件无法自己添加click事件,所以不能用stop解决这个问题。
2. 解决overflow:hidden的问题
methods: {
xxx(){
this.visible = !this.visible
if(this.visible === true) {
setTimeout(()=>{
// 主要是下面这四句实现,但是还是有bug
document.body.appendChild(this.$refs.contentWrapper)
let {width, height, top, left} = this.$refs.triggerWrapper.getBoundingClientRect()
this.$refs.contentWrapper.style.left = left + 'px'
this.$refs.contentWrapper.style.top = top + 'px'
//
let eventHandler = ()=>{
this.visible = false;
console.log('document 隐藏 popover')
document.removeEventListener('click',eventHandler)
}
document.addEventListener('click', eventHandler)
})
}else{
console.log('vm 隐藏 popover')
}
}
3. 面试题:v-show和v-if的区别,v-if是是否出现在dom树上,v-show是改变其css样式。
4. 解决当容器有 overflow hidden 造成的bug
- clientRect是相距可视范围,绝对定位相距于body定位。现在我们的浮层是相对于body定位,而按钮获取到的top是相对于window定位而引发的bug。
-
解决这个问题只要得到两者之间的插值就好解决
methods: { xxx(){ this.visible = !this.visible if(this.visible === true) { setTimeout(()=>{ document.body.appendChild(this['$refs']['contentWrapper']) let {top, left} =this['$refs']['triggerWrapper'].getBoundingClientRect() // 这两句话解决 this['$refs']['contentWrapper'].style.left = left + window.scrollX + 'px' this['$refs']['contentWrapper'].style.top = top + window.scrollY +'px' // let eventHandler = ()=>{ this.visible = false; console.log('document 隐藏 popover') document.removeEventListener('click',eventHandler) } document.addEventListener('click', eventHandler) }) }else{ console.log('vm 隐藏 popover') } }
5. 解决外部点击click无效的问题。
// 先将点按钮和点外面的逻辑分开
onClick(event){
if(this.$refs.triggerWrapper.contains(event.target)){
console.log('按钮')
this.visible = !this.visible
} else {
console.log('其它')
}
}
// 将之前的代码移动进去
methods: {
onClick(event){
if(this.$refs.triggerWrapper.contains(event.target)){
this.visible = !this.visible
if(this.visible === true) {
setTimeout(() => {
document.body.appendChild(this['$refs']['contentWrapper'])
let {top, left} = this['$refs']['triggerWrapper'].getBoundingClientRect()
this['$refs']['contentWrapper'].style.left = left + window.scrollX + 'px'
this['$refs']['contentWrapper'].style.top = top + window.scrollY + 'px'
let eventHandler = (e) => {
if(this['$refs']['contentWrapper'].contains(e.target)){
// 这句话解决了点击内容消失的问题
} else {
this.visible = false;
document.removeEventListener('click', eventHandler)
console.log('关闭') // document事件引起的
}
}
document.addEventListener('click', eventHandler)
})
}
} else {
console.log('非按钮')
}
}
}
6.开始重构上面那段代码
methods: {
positionContent() {
document.body.appendChild(this["$refs"]["contentWrapper"])
let {top, left} = this["$refs"]["triggerWrapper"].getBoundingClientRect()
this["$refs"]["contentWrapper"].style.left = left + window.scrollX + "px"
this["$refs"]["contentWrapper"].style.top = top + window.scrollY + "px"
},
listenToDocument() {
let eventHandler = (e) => {
if (this["$refs"]["contentWrapper"].contains(e.target)) { // 这句话解决了点击内容消失的问题
} else {
this.visible = false
console.log('关闭')
document.removeEventListener("click", eventHandler)
console.log("关闭") // document事件引起的
}
}
document.addEventListener("click", eventHandler)
},
listenToDocument(){
let eventHandler = (e) => {
if ( this["$refs"]["contentWrapper"] &&
this["$refs"]["contentWrapper"].contains(e.target)) { // 这句话解决了点击内容消失的问题
return
} else {
this.visible = false
document.removeEventListener("click", eventHandler)
console.log("关闭") // document事件引起的
}
}
document.addEventListener("click", eventHandler)
},
opShow(){
setTimeout(() => {
this.positionContent()
this.listenToDocument()
})
},
onClick(event) {
if (this["$refs"]["triggerWrapper"].contains(event.target)) {
this.visible = !this.visible
if (this.visible === true) {
this.opShow()
} else {
console.log('关闭')
}
}
}
},
7. 还有一个bug,上面打印关闭,关闭了两次
- 原因是document会去关闭它,onClick也会去关闭它
-
我们需要把关闭入口收拢,这个就是代码的紧密性,也就是高内聚低耦合的内聚。
methods: { onClickDocument(e){ if ( this["$refs"]["popover"] && (this["$refs"]["popover"] && this["$refs"]["popover"].contains(e.target))) {return} else { this.close() } }, positionContent() { document.body.appendChild(this["$refs"]["contentWrapper"]) let {top, left} = this["$refs"]["triggerWrapper"].getBoundingClientRect() this["$refs"]["contentWrapper"].style.left = left + window.scrollX + "px" this["$refs"]["contentWrapper"].style.top = top + window.scrollY + "px" }, open(){ // 打开的收拢 this.visible = true setTimeout(() => { this.positionContent() document.addEventListener("click", this.onClickDocument) }) }, close(){ // 关闭的收拢 this.visible = false document.removeEventListener("click", this.onClickDocument) }, onClick(event) { if (this["$refs"]["triggerWrapper"].contains(event.target)) { if (this.visible === true) { this.close() } else { this.open() } } } }, // 所有重要的操作都要进行收拢
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。