Vue の el-table は自動天井効果を実現します (固定をサポート)

Vue の el-table は自動天井効果を実現します (固定をサポート)

序文

多くのケースを見た結果、単純な観点からは、position:sticky が理想的な選択であるように思われます。ただし、el-table が fixed に設定されている場合、ここでの fixed は無効になります。最終的に、スクロールを監視するjsのアイデアが採用されました。

実装のアイデア

  • テーブル上部からの距離
  • テーブルと天板の間の距離を設定して天板を吸収させます—offsetTop1
  • スクロールバーのスクロール距離を取得する
  • スクロールバーがoffsetTop1までスクロールすると、テーブルは自動的に一番上に移動します。

効果:

使用:

el-table タグで設定します: v-sticky="{ top: 0, parent:'#appMainDom'}",

<el-テーブル 
:data="tableData" スタイル="margin:10px 0;width: 100%;" 
bordermax-height="800" class="sticky-head" v-sticky="{ top: 0, parent:'#appMainDom' }" >
...
</el-table>

例示する

パラメータ名タイプ例示する
トップ番号スクロールバーは上から何ピクセル離れているか、自動的に上に表示される
スクロールDOM要素querySelectorは、要素を取得するために内部的に使用されます。

Gitee ケースのソースコード:
https://gitee.com/kaiking_g/test-element-by-vue.git

メインソースコード:

/**
 * アイデア:
 * テーブルと天板の間の距離* テーブルと天板の間の距離を設定して天板を吸収させます --- offsetTop1
 * スクロールバーのスクロール距離を取得します * スクロールバーが offsetTop1 スクロールすると、テーブルは自動的にトップに表示されます */
'vue' から Vue をインポートします
定数テーブルStickyObj = {}

定数__STICKY_TABLE = {
  // 固定ヘッダーのスタイルを設定する doFix (dom, top, data) {
    const { uid, domType, isExist } = データ
    const uObj = テーブルStickyObj[uid]
    const curObj = uObj[domType]
    定数 headerRect = tableStickyObj[uid].headerRect

    存在する場合
      dom.style.position = '固定'
      dom.style.zIndex = '2001'
      dom.style.top = 上 + 'px'
    }
    uObj.tableWrapDom.style.marginTop = headerRect.height + 'px'

    domType === 'fixed'の場合{
      dom.style.left = curObj.left + 'px'
    } そうでない場合 (domType === 'fixedRight') {
      dom.style.left = curObj.left + 1 + 'px'
    }
  },
  // 固定ヘッダーのスタイルを解除する removeFix (dom, data) {
    const { uid, domType } = データ
    // dom.parentNode.style.paddingTop = 0
    const uObj = テーブルStickyObj[uid]
    const curObj = uObj[domType]
    dom.style.position = '静的'
    dom.style.top = '0'
    dom.style.zIndex = '0'

    uObj.tableWrapDom.style.marginTop = '0'

    domType === 'fixed'の場合{
      curObj.dom.style.top = '0'
    } そうでない場合 (domType === 'fixedRight') {
      curObj.dom.style.top = '0'
    }
  },
  // 固定ヘッダーにクラスを追加
  addClass (dom、fixtop、データ) {
    フィックストップ = フィックストップ || 0
    const isExist = dom.classList.contains('fixed')
    data.isExist = !!isExist
    if (!isExist) { // 存在する場合は追加しない dom.classList.add('fixed')
    }
    this.doFix(dom、fixtop、データ)
  },
  // 固定ヘッダーからクラスを削除する
  クラスの削除 (dom, データ) {
    dom.classList.contains('fixed') の場合
      dom.classList.remove('fixed')
      this.removeFix(dom, データ)
    }
  },

  /**
   * 親要素に対する要素の上の距離を計算します* @param {Nodes} 要素* @param {String} domId 親要素のID
   * @param {Boolean} isParent 親要素かどうか * @returns {Number}
   */
  getPosY(el, domId) {
    オフセットを0にする
    定数 pDom = el.offsetParent
    pDom != null && '#' + el.id !== domId の場合 {
      オフセット = el.offsetTop
      オフセット += this.getPosY(pDom, domId)
    }
    リターンオフセット
  },

  // 要素の水平座標を取得します(ウィンドウを基準として)
  getPosX (e) {
    var オフセット = e.offsetLeft
    (e.offsetParent != null) の場合、オフセット += this.getPosX(e.offsetParent)
    リターンオフセット
  },
  fixHead (scrollDom、el、uid、binding) {
    this.fixHead1(this、{ scrollDom、el、uid、binding })
  },
  // ヘッダーを固定するかどうかを決定するメイン関数 fixHead1: sticky_throttle((_this, { scrollDom, el, uid, binding }) => {
    const top = バインディング値.top
    /**
     * myTop は、スクロール親コンテナーからの現在の要素の高さです。
     * fixtop 現在の要素に設定する必要がある絶対位置の高さ * parentHeight スクロールする親コンテナの高さ */
    // テーブルヘッダーDOMノード const headerWrapDom = el.children[1] // el-table__header-wrapper

    定数 headerTop = tableStickyObj[uid].headerRect.top
    定数 scrollTop = scrollDom.scrollTop

    const fixedHeadDom = tableStickyObj[uid].fixed.headerDom
    const fixedHeadRightDom = tableStickyObj[uid].fixedRight.headerDom

    スクロールトップ >= ヘッダートップの場合
      const fixtop = top + scrollDom.getBoundingClientRect().top
      // ヘッダーが親コンテナの上部までスクロールする場合。修正:positioning_this.addClass(headerWrapDom, fixtop, { domType: 'mainBody', uid })
      fixedHeadDom && _this.addClass(fixedHeadDom、fixtop、{domType: 'fixed'、uid })
      fixedHeadRightDom && _this.addClass(fixedHeadRightDom, fixtop, { domType: 'fixedRight', uid })
    } それ以外 {
      // テーブルが上にスクロールして親コンテナにスクロールする場合。固定のpositioning_this.removeClass(headerWrapDom, { domType: 'mainBody', uid })をキャンセル
      fixedHeadDom && _this.removeClass(fixedHeadDom, { domType: 'fixed', uid })
      fixedHeadRightDom && _this.removeClass(fixedHeadRightDom, { domType: 'fixedRight', uid })
    }
  }, 100, { イベントタイプ: 'fixHead111' }),
  //
  setHeadWidth(データ) {
    this.setHeadWidth1(これ、データ)
  },
  // ヘッダーを固定に設定すると、ヘッダーコンテナの幅はテーブル本体の幅に設定されます setHeadWidth1: sticky_debounce((_this, data) => {
    const { el, uid, バインディング, イベントタイプ } = データ
    const { scrollDom } = tableStickyObj[uid]
    const headerWrapDom = el.children[1] // el-table__header-wrapper
    定数 headerH = headerWrapDom.offsetHeight
    const distTop = _this.getPosY(headerWrapDom、binding.value.parent)
    const scrollDistTop = _this.getPosY(scrollDom) // スクロールバーと上端の間の距離 tableStickyObj[uid].headerRect.top = distTop + headerH - scrollDistTop / 3 // ヘッダーと上端の間の距離 - ヘッダー自体の高さ - スクロールバーと上端の間の距離 tableStickyObj[uid].headerRect.height = headerH
    // tableStickyObj[uid].headerRect.width = tableW

    // デバッガー
    // 左/右ヘッダーを固定
    // 各更新が 1 回だけ取得されるようにします // tableStickyObj[uid].fixed.dom = ''
    _this.initFixedWrap({ el、uid、eventType、キー: 'fixed'、クラス名: 'el-table__fixed'、クラス名1: 'el-table__fixed-header-wrapper' })
    _this.initFixedWrap({ el, uid, eventType, key: 'fixedRight', className: 'el-table__fixed-right', className1: 'el-table__fixed-header-wrapper' })

    // デバッガー
    // 現在のテーブル本体の幅を取得します。const bodyWrapperDom = el.getElementsByClassName('el-table__body-wrapper')[0]
    定数幅 = getComputedStyle(bodyWrapperDom).width
    // テーブルの幅を設定します。ここでは、デフォルトでは、ページ上の複数のテーブルの幅は同じになります。したがって、直接走査して値を割り当てることも、必要に応じて const tableParent = el.getElementsByClassName('el-table__header-wrapper') を個別に設定することもできます。
    (i = 0 とします; i < tableParent.length; i++) {
      tableParent[i].style.width = 幅
    }
    // デバッガー
    _this.fixHead(scrollDom, el, uid, binding) // 上部が固定されているかどうかを判定する処理}),

  initFixedWrap (データ) {
    const { キー、el、イベントタイプ、クラス名、クラス名1、uid } = データ
    // 各更新が 1 回だけ取得されるようにする if (eventType === 'resize' || !tableStickyObj[uid][key].dom) {
      const tableFixedDom = el.getElementsByClassName(クラス名)
      (tableFixedDom.length) の場合 {
        定数 fixedDom = テーブルFixedDom[0]
        const arr = fixedDom.getElementsByClassName(className1) //
        定数 headW = getComputedStyle(fixedDom).width

        tableStickyObj[uid][key].dom = fixedDom
        (arr.length)の場合{
          const distLeft = this.getPosX(fixedDom) // ウィンドウの左側からの距離 const headDom = arr[0]
          headDom.style.width = headW
          tableStickyObj[uid][key].left = distLeft // ウィンドウの左側からのピクセル if (key === 'fixedRight') { // 右固定の特殊機能 headDom.classList.add('scroll-bar-h0')
            headDom.style.overflow = 'auto'
            headDom.scrollLeft = headDom.scrollWidth
            headDom.style.overflow = 'hidden' // 最後までスクロールするように設定し、スクロール不可に設定する} else {
            headDom.style.overflow = '隠し'
          }

          tableStickyObj[uid][key].headerDom = headDom // 最初のものを取得}
      }
    }
  },

  //親の特定の変数を監視します(監視するには親にそれらの変数が必要です)
  監視対象 ({ el, バインディング, vnode, uid }) {
    // 左のナビゲーションバーが折りたたまれているかどうかを監視します vnode.context.$watch('isNavFold', (val) => {
      vnode.context.$nextTick(() => {
        タイムアウトを設定する(() => {
          // デバッガー
          this.setHeadWidth({ el, uid, binding, eventType: 'resize' })
        }, 200)
      })
    })
  }

}

/**
 * スロットリング関数: タスクは指定された時間間隔内に1回だけ実行されます* @param {function} fn
 * @param {数値} 間隔
 */
関数sticky_throttle(fn、間隔= 300){
  canRun = true とします
  関数を返す(){
    if (!canRun) 戻り値
    canRun = 偽
    タイムアウトを設定する(() => {
      fn.apply(これ、引数)
      canRun = true
    }, 間隔)
  }
}

/**
 * 手ぶれ防止: タスクは指定された時間間隔内に 1 回だけ実行され、この時間内に再度トリガーされた場合は時間が再計算されます。 (手ぶれ補正機能の非即時実行版)
 * 特定のイベントが頻繁に発生し、大量の計算やリソースを大量に消費する操作が発生する場合、手ぶれ補正は連続した期間に 1 回だけ実行されるように強制できます * */
関数sticky_debounce(fn,delay,config){
  定数_delay = 遅延 || 200
  設定 = 設定 || {}
  // const _this = this // これは common.js を指します
  関数を返す(){
    const th = this // this はインスタンスを指します const args = arguments
    // デバウンス数++
    // str = `、ラベル: ${th && th.listItem && th.listItem.label}` とします
    if (fn.timer) {
      タイムアウトをクリアする(fn.timer)
      fn.timer = null
    } それ以外 {
      // fn.debounceNum = デバウンスNum
    }
    fn.timer = setTimeout(関数() {
      // str = `、ラベル: ${th && th.listItem && th.listItem.label}`
      fn.timer = null
      fn.apply(th, args)
    }、 _遅れ)
  }
}

// カスタムイベントをグローバルに登録する Vue.directive('sticky', {
  // バインドされた要素が DOM に挿入されると...
  挿入された (el, バインディング, vnode) {
    // 現在の vueComponent の ID を取得します。さまざまな監視イベントを保存するためのキーとして
    定数 uid = vnode.componentInstance._uid
    // 現在のスクロール コンテナーを取得します。ドキュメントがスクロールしている場合。親パラメータはデフォルトで省略できます const scrollDom = document.querySelector(binding.value.parent) || document.body // TODO: binding.value.parentがない場合を検討してください。再度ログインして内部ページに直接移動すると、if (!tableStickyObj[uid]) {
      テーブルスティッキーオブジェクト[uid] = {
        uid、
        fixFunObj: {}, // スクロール コンテナのスクロール イベント リスナーを格納するために使用されます setWidthFunObj: {}, // ページのサイズが変更された後にヘッド幅を再計算するイベントを格納するために使用されます autoMoveFunObj: {}, // ユーザー ストレージ DOM 要素内のローカル スクロールの場合、ドキュメントがスクロールすると、固定レイアウトのヘッダーもドキュメントとともに上にスクロールする必要があります scrollDomRect: {},
        ヘッダー矩形: { 上: 0, 左: 0 },
        fixed: {}, // テーブルの左にフロート fixedRight: {}, // テーブルの右にフロート // バインディング、
        // エル、
        テーブルラップDom: el.getElementsByClassName('el-table__body-wrapper')[0],
        スクロールドム
      }
    }

    __STICKY_TABLE.watched({ el, binding, vnode, uid }) // 親のいくつかの変数をリッスンします // ウィンドウのサイズが変更されると、テーブルヘッダーの幅を再計算して設定し、リスニング関数オブジェクトにリスニング関数を保存して、リスニングイベントの削除を容易にします window.addEventListener('resize', (tableStickyObj[uid].setWidthFunObj = () => {
      __STICKY_TABLE.setHeadWidth({ el, uid, binding, eventType: 'resize' }) // 最初にヘッダーの幅を設定します})
    )

    // スクロール コンテナにスクロール リスナー イベントを追加します。リスニング関数オブジェクトにリスニング関数を保存して、リスニングイベントの削除を容易にします scrollDom.addEventListener('scroll', (tableStickyObj[uid].fixFunObj = (e) => {
      __STICKY_TABLE.fixHead(スクロールドメイン、el、uid、バインディング)
    }))
  },
  // コンポーネントが更新された後。ヘッダー幅を再計算するcomponentUpdated(el, binding, vnode) {
    定数 uid = vnode.componentInstance._uid
    __STICKY_TABLE.setHeadWidth({ el, uid, binding, eventType: 'componentUpdated' })
  },
  // ノードがバインドされていない場合は、すべてのリスニング イベントを削除します。
  アンバインド (el, バインディング, vnode) {
    定数 uid = vnode.componentInstance._uid
    window.removeEventListener('resize', tableStickyObj[uid].setWidthFunObj)
    const scrollDom = document.querySelector(binding.value.parent) || ドキュメント
    scrollDom.removeEventListener('scroll', tableStickyObj[uid].fixFunObj)
    if (binding.value.parent) {
      document.removeEventListener('スクロール'、tableStickyObj[uid].autoMoveFunObj)
    }
  }
})

これで、Vue で el-table を使用して自動天井効果を実現する方法についての記事は終了です (固定サポート)。el-table 自動天井の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vueカスタム命令は、タブテーブルの天井効果を実現するためのUUIDスクロール監視コードを生成します。
  • Vueは天井、アンカーポイント、スクロールハイライトボタンの効果を実現します
  • Vue天井アンカーコンポーネントメソッドを実装する
  • Vue のマルチルート テーブル ヘッダー天井のいくつかのレイアウト方法
  • 天井効果を実現するためのVue開発のサンプルコード
  • Vueは要素の天井または固定位置表示を実現します(スクロールイベントをリッスン)

<<:  MySQLクエリのソートとページング関連

>>:  Dockerのローカルイメージ作成方法の分析

推薦する

xshell を使用して VMware で Linux に接続する方法 (2 つの方法)

【序文】最近、ITOO の試験システムのストレステストを行いたいので、自分のコンピュータに Lin...

MySQL クエリのパケットが大きすぎる問題と解決策

問題の説明:エラーメッセージ:原因: com.mysql.jdbc.PacketTooBigExce...

XHTML チュートリアル、XHTML の基礎を簡単に紹介します

<br />この記事では、XHTMLとXHTMLの基礎知識について簡単に紹介します。 X...

Vueにおける混合継承の詳細な説明

目次混合継承の影響: 1. 継承Vue.extend メソッド​プロパティを拡張する2. ミックスイ...

JTAを実装するためにAtomikosと組み合わせたTomcatについて

最近、プロジェクトは環境を切り替え、WebLogic を Tomcat に置き換えました。途中で発生...

MySQL 5.7 の一時テーブルスペースを使用して落とし穴を回避する方法

導入MySQL 5.7 は、SSL/TLS と全体的なセキュリティ開発におけるいくつかの重要な変更に...

時系列転位修復ケースを実装するSQL

目次1. 要件の説明2. アイデアの概要1. 延長を要求する2. アイデアの概要3. SQLコード1...

docker compose helloworld を使い始めるための詳細なプロセス

前提条件Compose は、Docker コンテナをオーケストレーションするためのツールです。Doc...

js は複数の画像を zip にパッケージ化します

目次1. ファイルをインポートする2. HTMLページ3. メインコード4. 画像をbase64に変...

MySQL 最適化のヒント: 重複削除の実装方法の分析 [数百万のデータ]

この記事では、MySQL 最適化のヒントで重複したエントリを削除する方法を例を使って説明します。ご参...

jsプロキシの原理の詳細な説明

目次プロキシモードとは何ですか?実例を紹介例を使ってプロキシモデルの定義を理解するプロキシとはget...

Ubuntu 19.04 インストール チュートリアル (画像とテキストの手順)

1. 準備1.1 VMware 15 をダウンロードしてインストールするダウンロード リンク: h...

MySQLで偽または真を保存する方法

MySQL ブール値、偽または真を格納つまり、データベースに保存されるブール値は 0 と 1 であり...

Linux CentOS 7.7 システムの VMware インストールに関する詳細なチュートリアル

Linux CentOS 7.7 システムを Vmware にインストールする方法。最小限のインスト...