Vueは視覚的なドラッグページエディタを実装します

Vueは視覚的なドラッグページエディタを実装します

オンラインアドレス(VPNを使用するとより高速になります)

ビジュアルページエディターなんて、手の届かないものですよね?まずはアニメーション画像を見てみましょう!

この機能を実装する前に、インターネットで多くの情報を参照しましたが、結局何も見つかりませんでした。さまざまな記事はすべて、過去の自分のことを語っていました。

それで、この時点で、それをどのように達成するかを自分で考え出す必要がありますか?

考慮すべき事項:

  • ドラッグアンドドロップの実装
  • データ構造の定義
  • コンポーネントの分割
  • 保守性と拡張性

オブジェクト参照: これは私が今まで見た中で最もクールなトリックです。詳細を一つずつ説明しましょう。 !

ドラッグアンドドロップの実装

ドラッグイベント

ここでは H5 のドラッグ イベントが主に次の目的で使用されます。

dragstart // 要素のドラッグを開始したときにトリガーされます draggable // ドラッグ可能な要素を指定します dragend // ドラッグ操作が終了したときにトリガーされます dragover // ドラッグされた要素がドロップ可能なターゲット上に移動したときにトリガーされます drop // ドラッグされた要素がドロップ可能なターゲット上で放されたときにトリガーされます

これらのイベントの使い方を見てみましょう。

<!-- 要素リストのデータをドラッグ-->
<スクリプト>
// com は対応するビューコンポーネントであり、typeList はリリース領域に表示されます: {
 バナー:
  名前:「カルーセル」
  アイコン: 'el-icon-picture',
  com: バナー
 },
 製品: {
  名前: '製品',
  アイコン: 'el-icon-s-goods',
  com: 製品
 },
 画像:
  名前: '画像'、
  アイコン: 'el-icon-picture',
  com: 画像
 },
}
</スクリプト>
<!-- 要素をドラッグ -->
<ul 
 @dragstart="ドラッグスタート"
 @dragend="ドラッグ終了"
>
 <li 
  v-for="(val, key, index) in typeList"
  ドラッグ可能 
  :data-type="キー"
  :key="インデックス + 1"
 >
  <span :class="val.icon"></span>
  <p>{{val.name}}</p>
 </li>
</ul>
<!-- リリースエリア -->
<div 
 クラス="コンテンツを表示"
 @drop="ドロップ"
 @dragover="ドラッグオーバー"
>
</div>

ドラッグして開始

ドラッグ イベントの開始時に、製品、広告画像など、現在ドラッグされている要素のタイプを決定する変数タイプを定義します。

// ドラッグタイプ dragStart(e) {
 this.type = e.target.dataset.type
}

タイプを決定したら、リリースエリアの次のステップに進みます

リリースゾーンでの移動

移動プロセス中、ドラッグされた要素の位置は、マウスの位置に応じてリアルタイムで計算される必要があります。下にスクロールすると、アニメーション効果をプレビューできます。

// 'view-content': 外側のボックスのクラス、直接プッシュ
// 'item': ボックス内の要素。位置を計算し、変換操作を実行する必要があります。dragOver() {
 className = e.target.className とします。
 name = className !== 'view-content' ? 'item' : 'view-content' とします

 // コンポーネントのデフォルトデータ const defaultData = {
  type: this.type, // コンポーネント タイプ status: 2, // デフォルト ステータス data: [], // 基本データ options: {} // その他の操作 }

 if (name == 'view-content') {
  //...
 } そうでない場合 (名前 == 'アイテム') {
  //...
 }
}

境界処理、角度計算

コア変数:

  • isPush: ドラッグされた要素がページデータにプッシュされたかどうか
  • インデックス: ドラッグされた要素の最終インデックス値
  • curIndex: マウスが位置する要素のインデックス値
  • 方向: マウスが位置する要素の上部/下部

name=='view-content'の場合、ドラッグ要素が外側の空白の解放可能領域にあることを意味します。追加されていない場合は、直接プッシュしてください。

if (name == 'view-content') {
 if (!this.isPush) {
  this.index = this.view.length
  this.isPush = true
  this.view.push(デフォルトデータ)
 }
}

name=='item'、つまり既存の要素の上にある場合、位置、上/下、追加、移動を計算する必要があります。

if (名前 == 'アイテム') {
 ターゲット = e.target とする
 [ y, h, curIndex ] = [ e.offsetY, target.offsetHeight, target.dataset.index ] とします。
 let direction = y < (h / 2) // 現在の要素上のマウスの位置を計算して、ドラッグされた要素の上下方向を決定します。if (!this.isPush) {
  // 初め
  if (方向) {
   (現在のインデックス == 0) の場合 {
    this.view.unshift(デフォルトデータ)
   } それ以外 {
    this.view.splice(現在のインデックス、0、デフォルトデータ)
   }
  } それ以外 {
   現在のインデックス = +現在のインデックス + 1
   this.view.splice(現在のインデックス、0、デフォルトデータ)
  }
 } それ以外 {
  //移動中
  if (方向) {
   var i = curIndex == 0 ? 0 : curIndex - 1
   var 結果 = this.view[i]['ステータス'] == 2
  } それ以外 {
   var i = +現在のインデックス + 1
   var result = this.view.length > i && this.view[i]['status'] == 2
  }
  
  // ドラッグされた要素の位置を変更する必要があるかどうか if (result) return

  定数 temp = this.view.splice(this.index, 1)
  this.view.splice(curIndex, 0, temp[0])
 }
 this.index = curIndex // 要素の位置をドラッグします this.isPush = true // 入力する場合は押す、つまり true
}
  • 最初: 押されていない場合、ドラッグされた要素の位置は現在のインデックスと方向に基づいて決定されます
  • 移動: 押されて移動している状態。現在のインデックスと方向に応じて対応する値の状態を検索します。ドラッグされた要素の場合はそれを返し、そうでない場合は位置を変更します。

要約すると、マウスが現在位置する要素のインデックスを取得し、マウスが要素の上半分にあるか下半分にあるかを計算して、ドラッグされた要素の位置を推測します。 ! !

ちょっとした質問です:

上記の name=='item' では、ターゲットが内部要素になり、位置を計算できなくなるのを避けるために、Event イベントでデフォルト イベントをブロックする必要があります。ただし、イベント ブロックのみを使用すると、ここでは機能しません。理由はわかりません。.item のすべての子要素に、属性 pointer-events: none! を追加する必要があります。

e.preventDefault()
e.stopPropagation()

.item div{
 ポインタイベント: なし;
}

ドラッグ終了

マウスを離すか、リリースエリアから離れると、デフォルトの状態が復元されます。

ここでのステ​​ータスの役割は何でしょうか?

  1. 上記の計算ルールは、要素がドラッグ要素であるかどうかを判断するために使用されます。
  2. ページ表示モード: ドラッグ時にコンポーネント名のみが表示され、リリース後に通常の表示内容に戻ります。
// ドラッグ終了 dragEnd(e) {
 this.$delete(this.view[this.index], 'status')
 this.isPush = false
 this.type = null
},
// すでに指定された位置に配置されている drog(e) {
 e.preventDefault()
 e.stopPropagation()
 this.dragEnd()
},

コンテンツブロックのドラッグアンドドロップの実装

時間の制約のため、ここでは怠けて、より完璧なリストドラッグプラグイン Vue.Draggable (星 14.2k) を使用します。

しばらく勉強してみると、そのロジックは上で実装したドラッグアンドドロップと関連しており、具体的な実装方法も似ていることがわかりました。上記の実用的な例を使えば、あなたもできると思います!

あなたも試してみてはいかがでしょうか?

Vue.Draggable の使用に基づいてドラッグ コンポーネントを実装できます。これは、(ドラッグ、スロット、DOM) などの操作を使用します。

(時間があれば後で戻ってきてパッケージ化します)

コンポーネント部門

中央のビュー コンポーネントと右側の編集コンポーネントは、コンポーネントのセットです。予想どおり、コンポーネントのセットです。コンポーネントのセットである価値があります。

page=>indexはページ全体のコンテンツを管理します

。
├── コンポーネント
| ├── 編集 ## 右側で編集| | ├── 情報 # 基本情報| | ├── 画像 # 広告画像| | ├── 商品 # 商品| | └── インデックス # コンポーネント情報の管理と編集| └── 表示 ## 中央ビュー| | ├── バナー # スライドショー| | ├── 画像 # 広告画像| | └── 商品 # 商品一覧└── ページ
 └── インデックス ## メインページ

ページをプレビューする効果を得るには、components=>View の下のコンポーネントを使用するだけです。使い方は page=>index と同じなので、過度な変更は必要ありません。

データ構造の定義

明るく拡張可能な機能を実現するには、修飾されたデータ構造を定義することが不可欠です。同時に、コードの品質も判断できます。

もちろん、それはあなたが何を学んだか、そしてあなたの論理的思考力に依存します。

ここで最も目を引く処理方法は、オブジェクト間の関係を使用して、コンポーネント間の値の転送に一方向の送信のみが必要になるようにすることです。

ビュー: [
 {
  タイプ: '情報'、
  タイトル: 'ページタイトル',
  備考: 'ページの備考'、
  背景色: '赤'
 },
 {
  タイプ: 'バナー'、
  データ: [
   { url: '1.jpg'、名前: 'カルーセル画像1'、リンク: 'https://carousel image jump address.cn' },
   { url: '2.jpg'、名前: 'カルーセル 2'、リンク: 'https://carousel jump address.cn' }
  ]
 },
 {
  タイプ: '画像'、
  データ: [
   { url: '1.jpg', name: '広告画像1', link: 'https://広告画像ジャンプアドレス.cn' },
   { url: '2.jpg'、name: '広告画像2'、link: 'https://広告画像ジャンプアドレス.cn' }
  ]
 },
 {
  タイプ: '製品'、
  データ: [
   { id: '1'、名前: '製品 1'、画像: '1.jpg' }, 
   { id: '2'、名前: '製品 2'、画像: '2.jpg' }
  ]、
  オプション:
   originalPrice: true, // 取り消し線付き価格 goodRatio: true, // 好意的な評価 volumeStr: false, // 販売量}
 }
]

これは配列であり、配列内の項目はモジュールを表す。

  • タイプ: モジュールタイプ
  • データ: 基本情報
  • オプション: その他の操作

....オリジナルのコンポーネントモジュールを参考に、必要に応じて拡張することができます。

コンポーネント値を編集

ビューコンポーネントを選択するときに、ビューで指定されたアイテムオブジェクトをパラメーターとして編集コンポーネントに渡します。

オブジェクトは同じメモリ アドレスを指し、参照関係があります。多面的なデータ更新を実現するには、一度変更するだけで済みます。

<セクションクラス="r">
 <編集フォーム
  :data="プロパティ"
  v-if="isRight"
 </編集フォーム>
</セクション>
<スクリプト>
// ビューコンポーネントを切り替える selectType(index) {
 this.isRight = false
 this.props = this.view[インデックス]
 this.$nextTick(() => this.isRight = true)
}
</スクリプト>

画像アップロード

上に画像アップロードコンポーネントがあるので、ここで使用上のヒントを共有したいと思います。 !

Element-uiの組み込みアップロードコンポーネントを使用している友人は、ぜひご覧ください(黒板をたたきます)

まずは簡略化されたバージョンを実装してみましょう。

<!-- すべてのデフォルトメソッドを無効にする -->
<el-アップロード
 :http-request="アップロード"
 :ファイルリストを表示="false"
 複数
 アクション
>
 <img :src="item.url" v-for="(item, index) リスト内" :key="index">
</el-アップロード>
<スクリプト>
アップロード(パラメータ) {
 定数ファイル = params.file;
 定数フォーム = 新しい FormData();
 form.append("ファイル", ファイル);
 フォームに "clientType"、"multipart/form-data" を追加します。

 const index = this.imageIndex // 画像インデックスを編集する const data = { 
  url: URL.createObjectURL(ファイル)、 
  形状
 }
 if (インデックス !== null) {
  // this.list => 画像コレクション this.$set(this.list, index, data)
 } それ以外 {
  this.list.push(データ)
 }
}
</スクリプト>
  • アップロードメソッドを書き直す
  • URL.createObjectURL(file) を使用してローカルプレビューアドレスを作成します
  • フォームオブジェクトを保存し、送信時にアップロードします
// 上記のコードに従って、Promise を使用してアップロード機能を実装します。const request = []
this.list.forEach(item => {
 リクエスト.push(
  新しい Promise((resolve, 拒否) => {
   /**
    * アップロードインターフェース* 元のURLを置き換える
    * フォームを削除
    */
   imageUpload(item.form).then(res => {
    アイテム.url = res.data.url
    アイテムの削除フォーム
    解決する
   }).catch(エラー => {
    拒否(エラー)
   })
  })
 )
})
Promise.all(リクエスト).then(res => {
 // ... 提出する ...
})

最後のステップまで待ってデータを送信し、すべての写真をアップロードして、アップロードが完了したらデータを送信するためのインターフェイスを呼び出します。 !

複数のデータを送信するフォームがあるシナリオでは、これが最も正しいアプローチです。

最終まとめ

実際には、それは複雑ではありません。鍵となるのは、データ構造、コンポーネントの相互作用処理、論理的メソッドなどの計画です。このステップの核心点が達成されればそれで十分です。

新しいコンポーネントの追加、新しい操作の追加など、その他の拡張性操作については、残りの問題はもはや問題ではありません。

これはあくまでも簡易版として捉えることができます。必要に応じて最適化、熟考、改善し、自分の知識として吸収することができます。

少なくとも仕事の必要は満たされました、ハハハハハ〜〜〜

詳細はソースコードをご確認ください。こちらがGithubのアドレスです。星をありがとうございます。私はお茶を飲まない李白です。

以上が、Vue のビジュアル ドラッグ アンド ドロップ ページ エディターの実装の詳細です。Vue のビジュアル ドラッグ アンド ドロップ ページ エディターの詳細については、123WORDPRESS.COM の他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • Vueカスタム指示により、ポップアップウィンドウのドラッグ4辺ストレッチと対角ストレッチ効果を実現
  • VUEは、マウスをドラッグアンドドロップしてウィンドウサイズを変更するためのStudio管理バックグラウンドを実装しています。
  • VUEは、自由にドラッグできるポップアップコンポーネントを実装しています。
  • Vue の一時停止されたドラッグ可能なフローティング ボタンのサンプル コード
  • Vue ベースのドラッグ アンド ドロップ機能を実装する
  • Vueをベースにドラッグ効果を実現
  • Vueはdivドラッグアンドドロップを実装します
  • Vueはドラッグアンドドロップを実装します
  • Vue draggableは左から右へのドラッグ機能を実現します
  • Vue はドラッグウィンドウ機能を実装します

<<:  MySQL インストール プロンプト「詳細なヘルプについては NET HELPMSG 3534 と入力してください」の解決方法

>>:  nginx+uwsgi で Django プロジェクトを開始するための詳細な手順

推薦する

Robots.txtの詳細な紹介

robots.txt の基本的な紹介Robots.txt はプレーンテキスト ファイルであり、Web...

ブラウザのスクロールバーのスタイルを変更するための純粋な CSS の例

CSSを使用してブラウザのスクロールバーのスタイルを変更する ::-webkit-スクロールバー{ ...

Windows 2016 Server セキュリティ設定

目次システムアップデート構成Windows Update サーバーの変更自動更新を有効にして許可する...

Zabbixリモートコマンド実行の詳細な例

目次1つ。環境二。予防三つ。例Zabbix トリガーがしきい値に達すると、アラート メッセージの送信...

Nginx で 403 forbidden を解決するための完全な手順

ウェブページに403 Forbiddenと表示されるNginx (yum インストール ログは通常 ...

1 つ以上のフィールドに基づいて重複データを検索する MySQL SQL ステートメント

SQLはテーブル内の重複レコードをすべて見つけます1. テーブルには id と name の 2 つ...

SQL 実践演習: オンライン モール データベース ユーザー情報データ操作

オンラインショッピングモールデータベース - ユーザー情報データ運用プロジェクトの説明電子商取引の台...

MySQL のレイテンシ問題とデータフラッシュ戦略プロセスの分析

目次1. MySQLレプリケーションプロセス2. MySQLの遅延問題の分析3. プロモーション期間...

2列の水平タイムラインを実装するためのVueサンプルコード

目次1.コンポーネントtimelineH.vueを実装する2. コンポーネントの呼び出しこの記事では...

コード例を通してページ置換アルゴリズムの原理を理解する

ページ置換アルゴリズム: 本質は、限られたメモリをワイヤレス プロセスに対応できるようにすることです...

Linux での MySQL 5.7.16 無料インストール バージョンのグラフィック チュートリアル

この記事では、参考までにMySQL 5.7.16の無料インストール版のチュートリアルを紹介します。具...

CSSを使用して炎の効果を作成する方法

本文は以下から始まります。 123WORDPRESS.COM ダウンロード:純粋な CSS3 で超リ...

Web 開発チュートリアル クロスドメイン ソリューションの詳細な説明

序文この記事では、主にWeb開発のためのクロスドメインソリューションを紹介し、参考と学習のために共有...

Linuxは数字当てゲームのソースコードを実装する

シンプルな Linux 推測ゲームのソースコードゲームのルール:数字当てゲームは通常 2 人でプレイ...

JavaScript 即時実行関数の使用状況分析

一般的に、関数は実行する前に呼び出す必要があることはご存じのとおりです。以下に示すように、関数を定義...