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のローカルイメージ作成方法の分析

推薦する

Linuxカーネルの浮動小数点演算のサポートに関する簡単な説明

現在、ほとんどの CPU は浮動小数点ユニット (FPU) をサポートしています。FPU は、プロセ...

CSS スティッキーフッター実装コード

この記事では、CSS スティッキー フッターの実装コードを紹介し、共有します。詳細は次のとおりです。...

MySQL で大文字と小文字を区別しないように設定する方法

mysql は大文字と小文字を区別しないように設定されていますウィンドウズmysqlがインストールさ...

Linux コマンドを素早く習得する 4 つの方法

Linux マスターになりたいなら、いくつかの Linux コマンドを習得することが不可欠です。 L...

MySQL SELECT実行順序の簡単な理解

SELECT ステートメントの完全な構文は次のとおりです。 (7)選択 (8) DISTINCT ...

小さなアイコンのフロントエンド処理ソリューションのグラフィカルな説明

序文この記事を始める前に、複数選択の質問をしてみましょう。フロントエンド開発でビルド ツールを使用す...

Linux (Ubuntu) での MySQL 5.6.28 のインストールと設定のチュートリアル

mysql5.6.28のインストールと設定方法1. 基本的なシステム情報を確認し、yumでインストー...

魔法のMySQLデッドロックトラブルシューティング記録

背景MySQL のデッドロックについて言えば、私は以前 MySQL のロックに関する基本的な紹介記事...

HTML メタタグの小さなコレクション

<Head>……</head> は <HTML> のファイル ヘ...

マージントップ崩壊現象とその具体的解決策

マージントップの崩壊とはmargin-top の崩壊は、CSS ボックス モデルで発生する現象です。...

Zabbixリモートコマンド実行の詳細な例

目次1つ。環境二。予防三つ。例Zabbix トリガーがしきい値に達すると、アラート メッセージの送信...

MySQLマスタースレーブ遅延現象と原理の詳細な分析

1. 現象早朝、オンライン テーブルにインデックスが追加されました。テーブル内のデータ量が大きすぎた...

Momentsで写真を整理するためのCSSコード

まず、Moments を開いて、写真の数が異なるいくつかのレイアウトを確認するか、以下の例を参照して...

Vue の新しいパートナー TypeScript クイックスタート実践記録

目次1. 公式の足場を使って構築する2. プロジェクトディレクトリ分析3. TypeScript の...