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

推薦する

MySQL 5.7 のインストールと設定方法のグラフィックチュートリアル

このチュートリアルでは、MySQL 5.7のインストールと設定方法を参考までに紹介します。具体的な内...

MySQL のレイテンシ問題とデータフラッシュ戦略プロセスの分析

目次1. MySQLレプリケーションプロセス2. MySQLの遅延問題の分析3. プロモーション期間...

...

CSS3 を使用した背景ぼかし効果の 3 つの例

導入から始めず、いきなり本題に入りましょう。通常の背景ぼかし効果は次のとおりです。 プロパティを使用...

MySQLでSQLクエリ文がどのように実行されるかを分析する

目次1. MySQL論理アーキテクチャの概要2. コネクタクエリキャッシュ4. パーサー5. オプテ...

nginxを使用してドメイン名ベースの仮想ホストを構成する

1. 仮想ホストとは何ですか?仮想ホストは、特殊なテクノロジーを使用して、実行中のサーバーを論理的に...

jQuery はテーブルのページング効果を実装します

この記事では、テーブルのページング効果を実現するためのjQueryの具体的なコードを参考までに紹介し...

MySQL 8.0 のユーザーとロールの管理原則と使用方法の詳細

この記事では、MySQL 8.0 のユーザーとロールの管理について例を挙げて説明します。ご参考までに...

jsは動的にテーブルを生成します(ノード操作)

この記事の例では、テーブルを動的に生成するjsの具体的なコードを参考までに共有しています。具体的な内...

Dockerでランナーコンテナを構成する方法

1. ランナーコンテナを作成する mk@mk-pc:~/Desktop$ docker run -d...

Vuex データの永続性を実装するためのアイデアとコード

vuexとはvuex: vue.js専用に開発された状態管理ツールで、すべてのコンポーネントの状態を...

初心者のためのWebページ作成: HTMLのハイパーリンクAタグの使い方を学ぶ

ハイパーリンク a タグはリンク ポイントを表し、英語の単語「anchor」の略語です。その機能は、...

MySQL ログイン警告問題の解決策

1. はじめにMySQL にログインすると、次のような警告が表示されることがよくあります。警告: コ...

Jenkins を使用した Vue プロジェクトのワンクリック パッケージングと公開の実装

目次Jenkinsのインストールインストールポート番号を変更します(デフォルトのポートは8080です...

SSL を実装するために nginx を設定する方法の例

環境説明サーバーシステム: Ubuntu 18.04 64ビットnginx: 1.14この記事では主...