Vue はタブ ラベルを実装します (ラベルが自動スクロールを超える)

Vue はタブ ラベルを実装します (ラベルが自動スクロールを超える)

作成されたタブラベルがページの表示領域を超えると、タブラベルの距離だけ自動的にスクロールされます。また、クリックするとタブラベルを手動でスクロールできます。効果については GIF 画像を参照してください。

エフェクトプレビューGIF

<テンプレート>
    <div class="main-box">
        <button @click="add">追加</button>
        <div class="main-box-tab">
            <i @click="前へ"><<</i>
            <i @click="次へ">>></i>
            <div class="main-box-tab-content" ref="タブ">
                <div class="main-box-tab-roll">
                    <div v-for="(item,index) タブ内" :key="index"
                         :class="{'タブ項目アクション':アクション名 === 項目名 ,'タブ項目':アクション名 !== 項目名}"
                         @click.stop="clickTab(item.name,index)">
                        <span>{{item.meta.title}}</span>
                        <i class="el-icon-close" @click.stop="close(item.name)"></i>
                    </div>
                </div>
            </div>
        </div>
        <div class="メインボックスコンテンツ">
            <div>{{アクション名}}</div>
        </div>
    </div>
</テンプレート>
<スクリプト>
    エクスポートデフォルト{
        名前: "インデックス",
        データ() {
            戻る {
                タブ: [],
                移動X: 0,
                カウント: 1,
                空き: 0,
                タブ数: 0,
                アクション名: 'test1'
            }
        },
        時計:
            アクション名(val) {
                len = this.tabs.lengthとします
                // 重複データがある場合は、後続の関数の実行を終了します for (let i = 0; i < len; i++) {
                    if (this.tabs[i].name === val) {
                        this.$nextTick(() => {
                            this.translateX((i + 1 - this.tabsCount) * this.width - this.unoccupied)
                        })
                        戻る
                    }
                }

                this.tabs.push({
                    名前: `test${this.count}`,
                    メタ: {
                        タイトル: `test${this.count}`
                    }
                })
                this.$nextTick(() => {
                  // (合計でいくつのタブがあるか - オフセットされていないときに表示される要素の数) * 単一のタブ ラベル要素の長さ - 隠れたタブ要素の表示部分の幅 this.translateX((this.tabs.length - this.tabsCount) * this.width - this.unoccupied)
                })
            }
        },
        マウント() {
            this.tabs.push({
                名前: `test${this.count}`,
                メタ: {
                    タイトル: `test${this.count}`
                }
            })
            this.$nextTick(() => {
                tabs = this.$refs.tabs とします。
                getStyle = getComputedStyle(tabs.children[0].children[0], null) とします。
                marginLeft = parseFloat(getStyle.marginLeft.substr(0, getStyle.marginLeft.length - 2)) とします。
                marginRight = parseFloat(getStyle.marginRight.substr(0, getStyle.marginRight.length - 2)) とします。
                // 要素の実際の幅 = 要素の幅 + 余白 this.width = marginLeft + marginRight + tabs.children[0].children[0].offsetWidth

                /**
                 * 実装ロジックを理解するために、次のコメント計算方法が使用されます**/
                // // 表示領域に配置できる要素の数 = 表示領域の幅 / サブ要素の実際の幅 // let num = tabs.offsetWidth / this.width

                // // 隠されたタブ要素の表示部分の幅 = 表示領域の幅 - (子要素の実際の幅 * 整数に変換された数値)
                // this.unoccupied = tabs.offsetWidth - (this.width * parseInt(num))

                //最後に余りに簡略化されます(結果は上記の計算と同じになります)
                this.unoccupied = tabs.offsetWidth % this.width
                // 整数に変換 this.tabsCount = parseInt(tabs.offsetWidth / this.width)
            })
        },
        メソッド: {
            追加() {
                this.count++
                this.actionName = `test${this.count}`
            },

            /**
             * タブページを切り替える**/
            クリックタブ(名前) {
                if (this.actionName !== 名前) {
                    this.actionName = 名前
                }
            },

            /**
             * タブページを閉じる**/
            閉じる(名前) {
                len = this.tabs.lengthとします
                ジャンプ名をnullにする
                長さが1より大きい場合
                    (i = 0; i < len; i++) の場合 {
                        if (this.tabs[i].name === name) {
                            this.tabs.splice(i, 1)

                            ジャンプ名 = this.tabs[i ? i - 1 : 0].name
                            if (this.actionName !== ジャンプ名 && name === this.actionName) {
                                this.actionName = ジャンプ名
                            }

                            this.$nextTick(() => {
                                this.previous()
                            })
                            戻る
                        }
                    }
                }
            },

            /**
             * 右にシフト**/
            次() {
                // scrollWidth は正確ではありません // this.width * this.tabs.length を使用して合計の長さを計算します let totalWidth = this.width * this.tabs.length

                this.$nextTick(() => {
                    dom = this.$refs.tabs とします。
                    // 表示領域 < スクロール領域 (スクロール領域は表示領域より大きい場合にのみ移動できます)
                    // 移動距離 + 表示領域 = スクロール領域の幅(最後の幅、クリック時の実際の幅)< スクロール領域if (dom.clientWidth < totalWidth && this.moveX + dom.clientWidth < totalWidth) {
                        // this.moveX は 0 から未使用スペースの幅を引いた値です。this.moveX += this.moveX ? this.width : this.width - this.unoccupied
                        this.translateX(this.moveX)
                    }
                })
            },

            /**
             * 左オフセット**/
            前の() {
                (this.moveX > 0)の場合{
                    this.moveX -= this.width
                    this.translateX(this.moveX)
                }
            },

            /**
             * domの移動を開始する
             **/
            翻訳X(x) {
                this.moveX = x < 0 ? 0 : x
                this.$refs.tabs.children[0].style.transform = `translateX(-${this.moveX}px)`
            }
        }
    }
</スクリプト>

<style lang="scss" スコープ>
    .メインボックス{
        高さ: 500px;
        幅: 500ピクセル;
        パディング: 10px 20px 20px 20px;

        .メインボックスタブ{
            位置: 相対的;
            パディング: 10px 20px;
            オーバーフロー: 非表示;

            & > 私 {
                位置: 絶対;
                カーソル: ポインタ;
                下: 15px;

                &:n番目の子(1) {
                    左: 0;
                }

                &:n番目の子(2) {
                    右: 0;
                }
            }

            .メインボックスタブコンテンツ{
                オーバーフロー: 非表示;

                .メインボックスタブロール{
                    遷移: 変換 .5s;
                    ディスプレイ: フレックス;
                    アイテムの位置を中央揃えにします。

                    div {
                        フレックス収縮: 0;
                        カーソル: ポインタ;
                        幅: 130ピクセル;
                        高さ: 25px;
                        マージン: 0 5px;
                        ディスプレイ: フレックス;
                        アイテムの位置を中央揃えにします。
                        コンテンツの両端揃え: スペースの間;

                        スパン、i {
                            フォントサイズ: 12px;
                        }

                        スパン {
                            左マージン: 10px;
                            オーバーフロー: 非表示;
                            空白: ラップなし;
                            テキストオーバーフロー: 省略記号;
                        }

                        私 {
                            右マージン: 10px;
                        }
                    }
                }
            }

            .タブ項目{
                色: #cccccc;
                背景色: rgba(255, 255, 255, .5);
                境界線の半径: 0 1px 0 1px;
                境界線: 1px 実線 #052141;
            }

            .タブ項目アクション{
                色: #ffffff;
                背景: rgba(0, 180, 255, 0.8);
                境界線の半径: 0 1px 0 1px;
                境界線: 1px実線 #1E2088;
            }

        }

        .メインボックスコンテンツ{
            高さ: calc(100% - 70px);
            パディング: 10px;
            境界線: 1px サドルブラウン実線;
            背景サイズ: 100% 100%;
        }
    }
</スタイル>

Vue のタブタグの実装(タブが自動スクロールを超える)に関するこの記事はこれで終わりです。Vue タブタグの関連コンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き閲覧してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • vue-router がタブタグを切り替えて閉じるときに発生するキャッシュの問題を解決する
  • Vueはタブタグルーティング効果を実装し、Animate.cssを使用して遷移アニメーション効果を作成します。
  • タブページキャッシュ機能を実装するためのvuex + keep-alive
  • Vue2.0で実装したタブ切り替え効果の例(内容はカスタマイズ可能)
  • Vue2.0 タブとページ切り替えトランジションにスタイルを追加する方法
  • vue-router 実装タブページの詳細説明(単一ページ)

<<:  Linux の一般的なコマンド chmod を使用して、ファイルの権限 777 と 754 を変更します。

>>:  MySQL サーバー IO 100% 分析および最適化ソリューション

推薦する

Vue3でカルーセルコンポーネントをカプセル化する方法

目的カルーセルコンポーネントをカプセル化して直接使用します。具体的な内容は以下のとおりです。一般的な...

MySQLの外部ネットワークアクセス権を開く方法

以下のように表示されます。主に認証コマンドを実行します: 2つの方法1. 任意のホストがユーザー b...

JavaScript で円形のプログレスバー効果を実装する

この記事では、円形のプログレスバー効果を実現するためのJavaScriptの具体的なコードを参考まで...

Linux ファイアウォールを設定してポート 80 と 3306 を開く方法

ポート80も設定されています。まずファイアウォール設定ファイルを入力しますシェル># vim ...

Windows システム mysql5.7.18 インストール グラフィック チュートリアル

Windows システム向け MySQL インストール チュートリアルダウンロード1. https:...

Unicode の数学記号の概要

数学、物理学、および一部の科学技術分野で使用される特殊記号は多数あります。Unicode コードには...

MySQL における SQL ページングクエリのいくつかの実装方法と利点と欠点

【SQL】SQLページングクエリの概要開発プロセスではページングが必要になることがよくあります。今日...

HTML におけるベースタグの使用に関する詳細な説明

requireJS には、baseURL というプロパティがあります。baseURL を設定すること...

HTML 代替カラーコードを実現する n 通りの方法 サンプルコード

この記事では、主に HTML のサンプル コードを紹介し、次のように交互に色を変更する方法を共有しま...

MySQL 5.7 および MySQL 8.0 でルートパスワードを変更する方法の概要

MySQL 5.7 バージョン:方法1: SET PASSWORDコマンドを使用するフォーマット: ...

HTML テキストフォーマットの簡単な例 (詳細な説明)

1. テキストの書式設定: この例では、HTML ファイル内のテキストを書式設定する方法を示します...

Win10 の組み込み Linux システムを使用して Spring Boot プロジェクトを開始する方法

1. Windows10の組み込みLinuxサブシステムをインストールする1.1. Linuxサブシ...

Vueコンポーネント通信のさまざまな方法の詳細な説明

目次1. 父から息子へ2. 息子から父へ3. 親子関係のないコンポーネントの値の転送4. ヴュークス...

Win10でのJDKのインストールと環境変数の設定に関する詳細なチュートリアル

目次序文1. 準備2. インストール3. 環境変数を設定する1. 「新規」をクリックすると、ポップア...

Vue の一般的な問題と解決策の概要 (推奨)

Vue に限定されず、他の種類の SPA プロジェクトにも当てはまる問題がいくつかあります。 1....