ホームページ ウェブフロントエンド jsチュートリアル Vue+Sortable プロジェクトの実践的なコード

Vue+Sortable プロジェクトの実践的なコード

Jun 11, 2018 am 10:23 AM
vue

今回は、Vue+Sortable プロジェクトの実際のコードをお届けします。Vue+Sortable プロジェクトを実際に実装する際の注意点は次のとおりです。

私は以前、コンポーネント ライブラリ Vue と Element-UI を使用したバックエンド管理システムを開発しました。非常に興味深い問題に遭遇したので、それを共有したいと思います。

シーンは次のようになります。リスト表示ページでは、Element-UIのテーブルコンポーネントを使用します。新しい要件は、元のテーブルに基づいたドラッグアンドドロップの並べ替えをサポートすることです。しかし、元のコンポーネント自体はドラッグ&ドロップによるソートに対応しておらず、Element-UIから直接導入しているためソースコードの修正が不便で、DOMを直接操作するしか方法がありません。

具体的な方法は、マウントされたライフサイクル関数で this.$el に対して実際の DOM 操作を実行し、一連のドラッグ イベントをリッスンし、イベント コールバックで DOM を移動し、データを更新することです。

Touch イベントに似た HTML5 の Drag イベントが多数あり、手動で実装することもできますが、ここでは、オープンソースの Sortable ライブラリを直接渡して、カプセル化されたイベントを監視します。 Vue の開発モデルに従って、モバイル DOM のコールバックで実際のデータ データを更新して、データと DOM の間の一貫性を維持します。

これで終わりだと思ったら、それは完全に間違いです。遅かれ早かれ、盗んだ怠惰を返さなければなりません。 。 。この解決策は素晴らしいと思いましたが、デバッグしようと思った瞬間、奇妙な現象が発生しました。A と B をドラッグして交換した後、B と A が魔法のように再び交換されてしまいました。これはどうなっているでしょうか?実際の DOM を移動した後、データ配列の順序とレンダリングされた DOM の順序も一致するはずです。

何が問題ですか? Vue の実装原理を思い出してください。Vue2.0 より前では、双方向バインディングは、defineProperty 依存関係の挿入と追跡によって実現されていました。 v-for 配列命令では、一意の Key が指定されている場合、配列内の要素の差分が効率的な Diff アルゴリズムによって計算され、最小限の移動または削除操作が実行されます。 Vue 2.0 以降の Virtual Dom の導入後、Children 要素の Dom Diff アルゴリズムは実際には前者と似ています。唯一の違いは、2.0 より前では、Diff は v-for 命令の配列オブジェクトを直接ターゲットとしていたのに対し、2.0 以降では、それはVirtual Domをターゲットにしていました。 DOM Diff アルゴリズムについては、ここでは説明しません。virtual-dom diff アルゴリズムについては、ここでより明確に説明します

リスト要素の配列が

['A','B','C','D']

であると仮定します。

レンダリングされた DOM ノードは

[$A,$B,$C,$D]

すると、対応する Virtual Dom の構造は

[{elm:$A,data:'A'} ,
{elm:$B,data:'B'},
{elm:$C,data:'C'},
{elm:$D,data:'D'}]

ドラッグ アンド ドロップを想定しますソート後、実DOMは

[$B,$A,$C,$D]

この時は実DOMを操作して位置を調整しただけですが、仮想Domの構造はまだ変更されていません

[{elm:$A,data:'A'},
{elm:$B,data:'B'},
{elm:$C,data:'C'},
{elm :$D,data:'D'}]

このとき、実際のDOMに従ってリスト要素もソートし、

['B','A','C',' となります。 D']

このとき、Diff アルゴリズムによれば、計算された Patch は、VNode の最初の 2 つの項目は同じタイプのノードであるため、直接更新されます。つまり、$A ノードは次のように更新されます。 $B、$B ノードは $A に更新され、実際の DOM は再び

[$A,$B,$C,$D]

に変更されるため、更新されるという問題があります。ドラッグ後のパッチ アルゴリズム: 操作パスは、

実際の DOM をドラッグして移動 -> データ配列を操作 -> パッチ アルゴリズムで実際の DOM を更新します

根本原因仮想 DOM と実際の DOM の間の不一致です。

つまり、Vue2.0 以前では、Virtual DOM が導入されていなかったため、この問題は存在しませんでした。

Vue フレームワークを使用する場合は、DOM を直接操作しないようにしてください

ソリューション

1. キーを設定して各 VNode を一意にマークします。これは、Vue が v-for 命令を使用することを推奨する方法でもあります。 2つのVNodeが同じ型かどうかを判定する際にはsameVnodeメソッドが呼び出されるため、キーが同じかどうかの判定が優先される

function sameVnode (a, b) {
 return (
  a.key === b.key &&
  a.tag === b.tag &&
  a.isComment === b.isComment &&
  isDef(a.data) === isDef(b.data) &&
  sameInputType(a, b)
 )
}
ログイン後にコピー

2 根本的な理由は実DOMとVNodeが一致していないため、操作は行われません。実際の DOM のドラッグと移動を復元できます。つまり、コールバック関数で [$B,$A,$C,$D] を [$A,$B,$C,$D] に復元し、 Vue への DOM 操作

実際の DOM をドラッグして移動します - > 移動操作を復元します - > データ配列を操作します - > パッチ アルゴリズムにより実際の DOM が更新されます

コードは次のとおりです

var app = new Vue({
    el: '#app', 
    mounted:function(){
      var $ul = this.$el.querySelector('#ul')
      var that = this
      new Sortable($ul, {
        onUpdate:function(event){
          var newIndex = event.newIndex,
            oldIndex = event.oldIndex
            $li = $ul.children[newIndex],
            $oldLi = $ul.children[oldIndex]
          // 先删除移动的节点
          $ul.removeChild($li)  
          // 再插入移动的节点到原有节点,还原了移动的操作
          if(newIndex > oldIndex) {
            $ul.insertBefore($li,$oldLi)
          } else {
            $ul.insertBefore($li,$oldLi.nextSibling)
          }
          // 更新items数组
          var item = that.items.splice(oldIndex,1)
          that.items.splice(newIndex,0,item[0])
          // 下一个tick就会走patch更新
        }
      })
    },
    data:function() {
      return {
        message: 'Hello Vue!',
        items:[{
          key:'1',
          name:'1'
        },{
          key:'2',
          name:'2'
        },{
          key:'3',
          name:'3'
        },{
          key:'4',
          name:'4'
        }]
      }
    },
    watch:{
      items:function(){
        console.log(this.items.map(item => item.name))
      }
    }
  })
ログイン後にコピー

3。解決!パッチ更新なしで、v-if 設定を通じて直接再レンダリングします。もちろん、これを行うことはお勧めしません。私はこのアイデアを提供しているだけです~

    mounted:function(){
      var $ul = this.$el.querySelector('#ul')
      var that = this
      var updateFunc = function(event){
        var newIndex = event.newIndex,
          oldIndex = event.oldIndex
        var item = that.items.splice(oldIndex,1)
        that.items.splice(newIndex,0,item[0])
        // 暴力重新渲染!
        that.reRender = false
        // 借助nextTick和v-if重新渲染
        that.$nextTick(function(){
          that.reRender = true
          that.$nextTick(function(){
            // 重新渲染之后,重新进行Sortable绑定
            new Sortable(that.$el.querySelector('#ul'), {
              onUpdate:updateFunc
            })
          })
        })
      }
      new Sortable($ul, {
        onUpdate:updateFunc
      })
    },
ログイン後にコピー

したがって、通常フレームワークを使用するときは、フレームワークの実装原理も理解する必要があります。そうしないと、いくつかの難しい問題に対処する方法がわかりません。状況~

私はそれを信じています。この記事の事例を読んだ後は、その方法を習得したことになります。さらに興味深い情報については、PHP 中国語 Web サイトの他の関連記事に注目してください。

推奨書籍:

Google がリリースした JS コード記述の仕様

サーバーサイドレンダリング用の Vue+Nuxt.js

以上がVue+Sortable プロジェクトの実践的なコードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

VUEのボタンに関数を追加する方法 VUEのボタンに関数を追加する方法 Apr 08, 2025 am 08:51 AM

HTMLテンプレートのボタンをメソッドにバインドすることにより、VUEボタンに関数を追加できます。 VUEインスタンスでメソッドを定義し、関数ロジックを書き込みます。

VueでBootstrapの使用方法 VueでBootstrapの使用方法 Apr 07, 2025 pm 11:33 PM

vue.jsでBootstrapを使用すると、5つのステップに分かれています。ブートストラップをインストールします。 main.jsにブートストラップをインポートしますブートストラップコンポーネントをテンプレートで直接使用します。オプション:カスタムスタイル。オプション:プラグインを使用します。

vue.jsでJSファイルを参照する方法 vue.jsでJSファイルを参照する方法 Apr 07, 2025 pm 11:27 PM

vue.jsでJSファイルを参照するには3つの方法があります。タグ;; mounted()ライフサイクルフックを使用した動的インポート。 Vuex State Management Libraryを介してインポートします。

VueでWatchの使用方法 VueでWatchの使用方法 Apr 07, 2025 pm 11:36 PM

Vue.jsの監視オプションにより、開発者は特定のデータの変更をリッスンできます。データが変更されたら、Watchはコールバック関数をトリガーして更新ビューまたはその他のタスクを実行します。その構成オプションには、すぐにコールバックを実行するかどうかを指定する即時と、オブジェクトまたは配列の変更を再帰的に聴くかどうかを指定するDEEPが含まれます。

Vue Multi-Page開発とはどういう意味ですか? Vue Multi-Page開発とはどういう意味ですか? Apr 07, 2025 pm 11:57 PM

VUEマルチページ開発は、VUE.JSフレームワークを使用してアプリケーションを構築する方法です。アプリケーションは別々のページに分割されます。コードメンテナンス:アプリケーションを複数のページに分割すると、コードの管理とメンテナンスが容易になります。モジュール性:各ページは、簡単に再利用および交換するための別のモジュールとして使用できます。簡単なルーティング:ページ間のナビゲーションは、単純なルーティング構成を介して管理できます。 SEOの最適化:各ページには独自のURLがあり、SEOに役立ちます。

Vueによる前のページに戻る方法 Vueによる前のページに戻る方法 Apr 07, 2025 pm 11:30 PM

vue.jsには、前のページに戻る4つの方法があります。$ router.go(-1)$ router.back()outes< router-link to ="/" Component Window.history.back()、およびメソッド選択はシーンに依存します。

Vueのバージョンを照会する方法 Vueのバージョンを照会する方法 Apr 07, 2025 pm 11:24 PM

Vue Devtoolsを使用してブラウザのコンソールでVueタブを表示することにより、Vueバージョンを照会できます。 NPMを使用して、「NPM List -G Vue」コマンドを実行します。 package.jsonファイルの「依存関係」オブジェクトでVueアイテムを見つけます。 Vue CLIプロジェクトの場合、「Vue -Version」コマンドを実行します。 < script>でバージョン情報を確認してくださいVueファイルを参照するHTMLファイルにタグを付けます。

Function Intercept Vueの使用方法 Function Intercept Vueの使用方法 Apr 08, 2025 am 06:51 AM

VUEの関数傍受は、指定された期間内に関数が呼び出され、パフォーマンスの問題を防ぐ回数を制限するために使用される手法です。実装方法は次のとおりです。LodashLibrary:Import {Debounce}から「Lodash」からインポート。 debounce関数を使用して、インターセプト関数を作成します。インターセプト関数を呼び出すと、制御関数は500ミリ秒でせいぜい1回呼び出されます。

See all articles