DataV全屏容器组件源码分析

这篇文章主要介绍“DataV全屏容器组件源码分析”,在日常操作中,相信很多人在DataV全屏容器组件源码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”DataV全屏容器组件源码分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    引言

    数据可视化页面一般在浏览器中进行全屏展示,全屏容器将根据屏幕比例及当前浏览器窗口大小,自动进行缩放处理。浏览器全屏后,全屏容器将充满屏幕。

    源码阅读(vue2版本)

    它的源码位置

    DataV全屏容器组件源码分析  datav 第1张

    看下它的DOM结构,很简单

    <div id="dv-full-screen-container" :ref="ref">
        <template v-if="ready">
          <slot></slot>
        </template>
    </div>

    源码分析

    接下来重点看下它的JS实现,它的代码中混入了autoResize.js,所以我们需要两个文件一起看,不然会对突然出现的变量很奇怪。(如果觉得分开不便于阅读,其实我们可以把它合在一起来阅读,是一样的)

    梳理下它的执行逻辑:

    第1步、mounted(组件挂载时,这一时期可对dom进行操作)

    mounted () {
      const { autoResizeMixinInit } = this
      autoResizeMixinInit()
    },

    第2步、autoResizeMixinInit函数

    methods: {
        async autoResizeMixinInit () {
          const { initWH, getDebounceInitWHFun, bindDomResizeCallback, afterAutoResizeMixinInit } = this
          await initWH(false)
          getDebounceInitWHFun()
          bindDomResizeCallback()
          if (typeof afterAutoResizeMixinInit === 'function') afterAutoResizeMixinInit()
        },
    }

    这其中调用了几个函数,我们来看看这些函数的作用。

    2.1、initWH函数

        // 初始化宽高
        initWH (resize = true) {
          const { $nextTick, $refs, ref, onResize } = this
          return new Promise(resolve => {
            $nextTick(_ => {
              const dom = this.dom = $refs[ref]
              this.width = dom ? dom.clientWidth : 0
              this.height = dom ? dom.clientHeight : 0
              if (!dom) { 
                console.warn('DataV: Failed to get dom node, component rendering may be abnormal!')
              } else if (!this.width || !this.height) {
                console.warn('DataV: Component width or height is 0px, rendering abnormality may occur!')
              }
              if (typeof onResize === 'function' && resize) onResize()
              resolve()
            })
          })
        },

    这个函数的作用很简单,就是在DOM渲染成功后,获取这个组件dom的宽高,返回一个Promise异步函数,作用就是:保证这个dom已经渲染好了,再去执行其他函数。

    2.1.1、onResize

        onResize () {
          const { setAppScale } = this
          setAppScale()
        }

    resize为true,即窗口大小变化、dom的style改变时要重新设置dom的缩放比例。

    2.2、getDebounceInitWHFun

    getDebounceInitWHFun () {
          const { initWH } = this
          this.debounceInitWHFun = debounce(100, initWH)
        },

    获取一个经过防抖的initWH函数。即debounceInitWHFun。

    2.3、bindDomResizeCallback

        // 监听dom元素变化
        bindDomResizeCallback () {
          const { dom, debounceInitWHFun } = this
          this.domObserver = observerDomResize(dom, debounceInitWHFun)
          window.addEventListener('resize', debounceInitWHFun)
        },

    很重要的一步,其中使用了observerDomResize来对这个组件dom进行监听。

    需要监听的DOM变化:

    • 窗口大小改变时触发的事件

    • dom的样式改变时触发

    第一个直接使用window监听resize事件即可。

    第二个对dom元素的监听,我们就需要使用MutationObserver来做了。

    MutationObserver用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动都会触发MutationObserver事件。

    封装一个observerDomResize函数来对dom的style属性变化进行监听

    export function observerDomResize (dom, callback) {
      const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
      const observer = new MutationObserver(callback)
      observer.observe(dom, { attributes: true, attributeFilter: ['style'], attributeOldValue: true })
      return observer
    }
    • attributes:属性的变动

    • attributeFilter:表示需要观察的特定属性

    • attributeOldValue:布尔值,表示观察attributes变动时,是否需要记录变动前的属性值。

    2.4、afterAutoResizeMixinInit

        afterAutoResizeMixinInit () {
          const { initConfig, setAppScale } = this
          initConfig()
          setAppScale()
          this.ready = true
        },

    组件dom节点渲染出来后,设置ready为true,再渲染插槽中的DOM元素。

    2.4.1、initConfig

        initConfig () {
          const { dom } = this
          // 当前屏幕分辨率
          const { width, height } = screen
          this.allWidth = width
          dom.style.width = `${width}px`
          dom.style.height = `${height}px`
        },

    作用:

    • 获取当前设备屏幕的分辨率

    • 将这个分辨率宽高设置为组件DOM的宽高

    2.4.2、setAppScale

        setAppScale () {
          const { allWidth, dom } = this
          const currentWidth = document.body.clientWidth
          dom.style.transform = `scale(${currentWidth / allWidth})`
        },

    它的作用是改变当前DOM的缩放比率。

    缩放比率 = 当前窗口的可视宽度 / 当前设备的屏幕分辨率(宽度)

    第3步、beforeDestroy(组件卸载时)

      beforeDestroy () {
        const { unbindDomResizeCallback } = this
        unbindDomResizeCallback()
      }

    我们之前对于dom的style属性和window的resize都做了监听,所以当我们组件卸载时这些监听事件也需要移除,如果不移除,那么到其他页面,做这些操作,监听事件仍然存在,但其实我们已经不需要再对他监听了,反而会造成性能浪费。

    3.1、unbindDomResizeCallback

        unbindDomResizeCallback () {
          let { domObserver, debounceInitWHFun } = this
          if (!domObserver) return
          domObserver.disconnect()
          domObserver.takeRecords()
          domObserver = null
          window.removeEventListener('resize', debounceInitWHFun)
        }

    disconnect方法用来停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器。

    takeRecords用来清除变动记录,即不再处理未处理的变动。该方法返回变动记录的数组。

    到此,关于“DataV全屏容器组件源码分析”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注蜗牛博客网站,小编会继续努力为大家带来更多实用的文章!

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    评论

    有免费节点资源,我们会通知你!加入纸飞机订阅群

    ×
    天气预报查看日历分享网页手机扫码留言评论Telegram