Vue3 ドラッグ可能な左パネルと右パネルの分割コンポーネントの実装

Vue3 ドラッグ可能な左パネルと右パネルの分割コンポーネントの実装

最近、vue を使用しているときに、中央部分をドラッグして左右の div の幅を調整できることを実現したいという要件に遭遇しました。この記事ではそれを整理して共有します。詳細は次のとおりです。

レンダリング

コンポーネントの分解

フレックスレイアウトを全体的に使用する

左パネル

  • パネルの特定のコンテンツは、slot という名前のスロットを通じて渡されます。
  • タイトルはpropを通じて渡される
  • ドラッグ可能。ドラッグによってコンテンツ スタイルが破壊されないようにするには、パネルの幅の最大値と最小値を設定します。

右パネル

  • 右パネルの幅は左パネルの幅に応じて変わります。コンテンツの幅は flex-auto を使用して自動的に調整されることに注意してください。
  • モバイルデバイスに適応させる必要があります。
  • Tailwind メディアクエリの適応的な使用

入力パラメータの分解

小道具

  • @param {Number} maxWidth 最大幅
  • @param {Number} minWidth 最小幅
  • @param {String} leftTitle 左タイトル
  • @param {String} rightTitle 正しいタイトルですか?
  • @param {Boolean} storeReage localstoregeで保存するかどうか

スロット

  • left-content {要素} 左コンテンツ
  • right-content {要素} 右コンテンツ

具体的な実装

ドラッグする方法は?

左パネルと右パネルの間に隠しボックスを追加し、このボックスを box-shadow で非表示にします。特定のイベントはこのdivに実装されます

<div id="line" class="w-2 cursor-move hidden md4:block"onMousedown={hnadleMouseDown}>
</div>

イベントリスニング

    const hnadleMouseDown = (イベント: マウスイベント) => {
      /* 開始点を取得して保存します*/
      {pageX, pageY} = evtとします。
      ベース位置.pageX = pageX;
      ベース位置.pageY = pageY;
      /* マウス移動イベントをリッスンする*/
      document.addEventListener("mousemove"、handleMouseMove);
      document.addEventListener("mouseup"、handleMouseUp);
    };
    const ハンドルマウス移動 = evt => {
      /* ブラウザのデフォルトイベントがブラウザのジェスチャ機能をトリガーしないようにする*/
      evt.preventDefault();
      /* DOM が複数回リフローするのを防ぐためにタイマーを設定します */
      タイムアウトをクリアします(タイマー値);
      タイマー値 = setTimeout(() => {
        {pageX} = evtとします。
        const baseDiv = document.querySelector(".right-border-shadow");
        /* プロセス幅が最大値/最小値の範囲内かどうか*/
        baseWidth: 数値 | undefined = とします
          Number(baseDiv?.clientWidth) + (pageX - basePosition.pageX);
        ベース幅 =
          baseWidth > Number(props?.maxWidth) ? props.maxWidth : baseWidth;
        ベース幅 =
          数値(基本幅) < 数値(props?.最小幅)
            ? プロパティの最小幅
            : ベース幅;
        baseDiv?.setAttribute("style", `width:${baseWidth}px`);
        /* 幅変更イベントを発行 */
        ctx.emit("drugend");
        /* ストアからストアへ */
        ストアを設定します(ベース幅)。
      }, 50);
    };
    定数handleMouseUp = evt => {
      /* ドラッグが終了したら、イベントのリスニングをキャンセルし、最終的な幅を出力します*/
      定数幅 = document.querySelector(".right-border-shadow")?.clientWidth;
      document.removeEventListener("mousemove"、handleMouseMove);
      document.removeEventListener("mouseup"、handleMouseUp);
      ctx.emit("drugend", 幅);
    };

幅処理

スタイル={`幅:${
            store.get("split-width")
              ? store.get("split-width")
              : props.minWidth
              ? プロパティの最小幅
              : 384
          }px`}

最適化

ブラウザウィンドウの幅を手動で変更する

次のティック(() => {
        ctx.emit("load", ctx);
        MutationObserver = window.MutationObserver;
        if (ミューテーションオブザーバー) {
          /* ブラウザウィンドウの変更を監視します。この API は場合によっては必要です */
          mo = 新しい MutationObserver(関数() {
            const __wm = document.querySelector("#rezie-id");
            // __wm 要素が変更された場合にのみ __canvasWM を再呼び出しします
            もし (!__wm) {
              // mo.disconnect() が常にトリガーされないようにする。
              mo = null;
              ctx.emit("サイズ変更");
            }
          });
          mo.observe(document.querySelector("#rezie-id"), {
            属性: true、
            サブツリー: true、
            子リスト: true、
          });
        }
      });

効果がありません。アドバイスをお願いします

バグ

親コンポーネントの onMounted フックで子要素のスロット要素ノードを取得するときにエラーが発生しました。値は null です。現在の解決策は、子コンポーネントの onMounted フックでロード イベントをスローし、親コンポーネントが onLoad を使用して後続のロジックを処理することです。

git アドレス

倉庫住所プレビューアドレス

Vue3 ドラッグ可能な左右のパネル分割コンポーネントの実装に関するこの記事はこれで終わりです。Vue3 ドラッグ可能な左右のパネル分割コンポーネントに関するその他の関連コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • vue-Split はパネルのセグメンテーションを実現します
  • Vueはドラッグアンドスライド分割パネルを実装します
  • Vue 分割パネルのカプセル化実装記録

<<:  MySQL 自動インクリメント ID のオーバーサイズ問題のトラブルシューティングと解決策

>>:  Linux で pyenv をインストールする方法

推薦する

データベースクエリ、どのオブジェクトにどのフィールドが含まれているか、メソッドステートメント

データベースは、どのオブジェクトにどのフィールドが含まれているかを照会します。 *を選択 sysob...

Dockerコンテナ間の通信と外部ネットワーク通信の操作

コンテナ間の通信1. コンテナのネットワーク共有このモードの Docker コンテナはネットワーク ...

MySQL トランザクションと分離レベルの基本原理の簡単な分析

目次序文1. 取引の基本原則の簡単な分析原子性:持続性分離:一貫性: 2. 分離レベルの基本原理の分...

Three.js が Facebook Metaverse 3D ダイナミック ロゴ効果を実現

目次背景メタバースとは何ですか?成果を達成するトライアル 1: THREE.TorusGeometr...

1 つの記事で Vuex を理解する

目次概要Vuex の 4 つの主要オブジェクト状態の使用突然変異の使用ゲッターの使用アクションの使用...

Docker での Tomcat インストールの 404 問題の解決方法

tomcat の containerID を見つけて、tomacat ディレクトリに入ります。 [r...

シームレスなトークンリフレッシュを実現する方法

目次1. 需要方法1方法2方法3 2. 実装3. 問題解決質問1: トークンの複数回の更新を防ぐ方法...

XHTML Web ページ チュートリアル

この記事は主に、初心者に XHTML の基本的な知識と、XHTML と HTML の違いを理解しても...

HTML テーブル マークアップ チュートリアル (2): テーブル境界属性 BORDER

デフォルトでは、テーブルの境界線は 0 ですが、テーブルの境界線を設定できます。基本的な構文<...

CSS BEM 命名標準の概要 (推奨)

1 BEM命名標準とはBem は、ブロック、要素、修飾子の略語であり、Yandex チームによって...

IDEA は MySQL への接続時にエラーを報告します。サーバーが無効なタイムゾーンを返します。タブに移動して serverTimezone プロパティを設定してください。

これからの道は常に困難で、棘だらけです。歯を食いしばって、乗り越えられると信じてください。さあ、さあ...

win10 mysql 5.6.35 winx64 無料インストールバージョン設定チュートリアル

mysql 5.6.35 winx64無料インストールバージョン構成チュートリアルwin10、具体的...

MYSQLクエリデータの結果に自動的に番号を付ける方法

序文実際、クエリ中に結果に番号が付けられるこのような状況に遭遇したことは一度もありません。同僚が転職...

ウェブページを開いて数秒後に他のページにリダイレクトする

これを実現するには、次のコードを追加するだけです。方法1: メタを使用する使用方法: <Met...