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 をインストールする方法

推薦する

Mysql の varchar 型に関する注意点

varchar の保存ルール4.0 未満のバージョンでは、varchar(20) は 20 バイトを...

MySQL データベースで UTF-8 エンコードを設定する方法

/etc/my.cnf または /etc/mysql/my.cnf ファイルを変更する [クライアン...

JavaScript の setTimeout() の使用法の概要

目次1. はじめに2. setIntervalとsetTimeoutの違い3.タイムアウトを設定する...

Linux のハードリンクとソフトリンクの区別

Linux には、2 種類のファイル接続があります。1 つは Windows のショートカットに似て...

Linux での MySQL 5.7.17 の最新安定バージョンのインストール チュートリアル

ソースコードを通じて Linux に最新の安定バージョンの MySQL をインストールします: my...

HTML タグのセマンティクス化 (H5 を含む)

導入HTML は、Web ドキュメントのコンテンツのコンテキスト構造と意味を提供します。HTML 自...

Reactのdiffアルゴリズムの詳細な分析

Reactのdiffアルゴリズムの理解diffアルゴリズムは、 Virtual DOMの変更された部...

JavaScriptにおけるPromiseの使い方と注意点について(推奨)

1. 約束の説明Promise は、非同期操作の最終状態 (失敗または正常完了) とその結果の値を...

DockerコンテナにRedisをデプロイする手順の紹介

目次1 つの Redis 設定ファイル2 Dockerコマンドの開始3 docker-compose...

nofollowタグの使用と分析に関する簡単な説明

nofollowをめぐる論争Zac と Guoping の間では、nofollow が PR を無駄...

backgroundImage を使用して画像カルーセルの切り替えを解決する詳細な説明

単一のDOMノードでカルーセルを実装するbackgroundImage を使用すると、複数の画像を追...

マウスを置いたときに半透明効果のテキスト説明を実現するための純粋な CSS (初心者は必読)

効果は以下のとおりです。 例1 例2:例1[結婚式の計画]を例にとるHTML: <div cl...

フックを使用して React コンポーネントを書くときに注意すべき 5 つの点

目次01. レンダリングが不要な場合はuseStateを使用する02. リンクの代わりにrouter...

Vue カプセル化コンポーネント アップロード画像コンポーネント

この記事の例では、参考のためにvueアップロード画像コンポーネントの具体的なコードを共有しています。...

WeChatアプレットはシンプルなサイコロゲームを実装します

この記事では、サイコロゲームを実装するためのWeChatアプレットの具体的なコードを参考までに共有し...