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()
}
}
}
},
// 所有重要的操作都要進行收攏
最後,個人微信,歡迎交流!