栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

Vue造轮子-popover组件(中)

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Vue造轮子-popover组件(中)

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()
 }
      }
    }
  },
  // 所有重要的操作都要进行收拢

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/245088.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号