作成されたタブラベルがページの表示領域を超えると、タブラベルの距離だけ自動的にスクロールされます。また、クリックするとタブラベルを手動でスクロールできます。効果については 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 をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Linux の一般的なコマンド chmod を使用して、ファイルの権限 777 と 754 を変更します。
>>: MySQL サーバー IO 100% 分析および最適化ソリューション
Web ページのアクセシビリティは、フロントエンドでのみ評価および実装できるもののようです。ユーザビ...
導入Memcached は分散キャッシュ システムです。Memcached には認証とセキュリティ制...
Linux で Ctrl+c、Ctrl+d、Ctrl+z はどういう意味ですか? Ctrl+c と ...
目次1. 依存関係をインストールする2. vue.config.js ファイルで pwa を設定しま...
クエリキャッシュ1. クエリキャッシュの動作原理クエリ ステートメントを実行する前に、MySQL は...
1. Nginx ステータス監視Nginx には、Nginx の全体的なアクセス ステータスを監視す...
目次1. HTTP範囲リクエスト1.1 範囲構文2. 大きなファイルをダウンロードする方法2.1 補...
シェルスクリプト #!/bin/sh # 現在のディレクトリ CURRENT_DIR=$( cd &...
目次定期的に剪定するミラーエビクションコンテナのクリーンアップネットワークソート体積の蒸発完全にクリ...
MySQL 8.0.13 のインストールと設定方法を皆さんと共有したいと思います。お役に立てれば幸...
Linuxにunzipコマンドがない問題の解決策unzipコマンドを使用して.zipファイルを解凍す...
概要実際のビジネス シナリオ アプリケーションでは、ビジネス条件に基づいて対象データを取得およびフィ...
前回の記事では、MySQL ステートメントの実行時間をチェックする 2 つの方法を紹介しました。今日...
テーブルがコンパクトになりすぎないように、テーブル内のセル間に一定の距離を設定できます。基本的な構文...
序文昨日、h5 WeChat認証の実装が必要なプロジェクトがありました。したがって、この機能を完了す...