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% 分析および最適化ソリューション

推薦する

CSS3で実装されたスライドメニュー

結果:実装コード: <!DOCTYPE html><html class=&quo...

LINUX ポートが占有されているかどうかを確認します

ポートが占有されているかどうかは、これまで一度もわかりませんでした。多くの人に尋ねて、ようやくわかり...

nginxとIISで使用できるSSL証明書を作成する

目次SSL証明書の作成1. 秘密鍵を生成する2. 証明書要求ファイルを生成する3. CRT証明書ファ...

IE8 開発者ツール メニューの説明

<br />この記事では、開発者ツールのさまざまなメニューについて簡単に説明しました。こ...

この記事はPReact10.5.13のソースコードを理解するのに役立ちます

目次render.js 部分create-context.js 部分差分部分Reactのソースコード...

Webpack-cliが正常にインストールされたら、詳細についてはwebpack -vエラーケースを確認してください。

目次質問1. webpack webpack-cliをインストールする2. webpackのバージョ...

JavaScript Reduceの詳しい説明

目次地図フィルターいくつかの毎インデックスを検索パイプ参考回答1. パラメータを受け入れる関数を返す...

MySQL Community Server 圧縮パッケージのインストールと設定方法

今日は、MySQL をインストールしたかったので、公式 Web サイトにアクセスして、MySQL の...

JS変数ストレージのディープコピーとシャローコピーの詳しい説明

目次可変タイプとストレージスペーススタックメモリとヒープメモリ基本的なデータ型参照タイプグラフィック...

nginx のインストールが完了した後に PHP を解析できない問題の解決方法

目次方法1方法2 nginxをインストールした後、PHPコードを解析できないことがわかりました。解決...

Dockerイメージ解析ツールのダイブ原理解析

今日は、Docker イメージ、各レイヤーの内容を調べ、Docker/OCI イメージのサイズを縮小...

ウェブデザインの経験とスキルの概要

■ ウェブサイトのテーマ計画 ウェブサイトのテーマが断片化しすぎないように注意してください。一般的に...

WeChatアプレットでラッキーホイールゲームを実装する方法

ここでは主に、WeChat アプレットでラッキーホイール ゲームを開発する方法を紹介します。主に J...

ServerSocketのデフォルトIPバインディングの実装プロセスの詳細な説明

開発中にサーバーを起動する必要がある場合、ローカルテストではポートを直接書き込み、実際の環境ではバイ...

JS 開発効率を上げる4つの超実践的なヒント

目次1. 短絡判定2. オプション連鎖演算子 (?) 3. ヌル合体演算子 (??) 4. 終了関数...