Vueのカスタムディレクティブの詳細なガイド

Vueのカスタムディレクティブの詳細なガイド

1. カスタム指示とは何ですか?

v- で始まるインライン属性はすべて命令です。異なる命令によって、異なる機能を完了または実装し、通常の DOM 要素に対して低レベルの操作を実行できます。これは、カスタム命令が使用されるときです。コア関数 (v-model および v-show) のデフォルトの組み込み命令に加えて、Vue ではカスタム命令を登録することもできます。

このコマンドを使用する方法はいくつかあります。

// コマンドをインスタンス化しますが、このコマンドにはパラメータ `v-xxx` がありません
 
// -- 値を命令 `v-xxx="value"` に渡します  
 
// -- `v-html="'<p>Content</p>'"` などの文字列をディレクティブに渡します。
`v-xxx="'文字列'"` 
 
// -- `v-bind:class="className"` などのパラメータ (`arg`) を渡します
`v-xxx:arg="値"` 
 
// -- 修飾子を使用する (`modifier`)
`v-xxx:arg.modifier="値"` 

2. 指示をカスタマイズする方法

カスタム ディレクティブの登録は、グローバルまたはローカルで行うことができます。

グローバル登録は主にVue.directiveメソッドを使用して登録されます

Vue.directiveの最初のパラメータはディレクティブの名前(v-プレフィックスなし)であり、2番目のパラメータはオブジェクトデータまたはディレクティブ関数になります。

// グローバルカスタムディレクティブ `v-focus` を登録します
Vue.directive('focus', {
  // バインドされた要素が DOM に挿入されると...
  挿入: 関数 (el) {
    // 要素にフォーカス el.focus() // ページが読み込まれた後に入力ボックスに自動的にフォーカスする小さな関数}
})

ローカル登録は、コンポーネントオプションのディレクティブ属性を設定することによって行われます。

ディレクティブ: {
  集中:
    // 挿入された命令の定義: function (el) {
      el.focus() // ページが読み込まれた後に入力ボックスに自動的にフォーカスする小さな関数}
  }
}

次のように、テンプレート内の任意の要素に新しい v-focus プロパティを使用できます。

<入力vフォーカス />

フック機能

カスタム命令にも、コンポーネントのようなフック関数があります。

  • bind: ディレクティブが要素に最初にバインドされるときに 1 回だけ呼び出されます。ここで、1回限りの初期化設定を実行できます
  • 挿入: バインドされた要素が親ノードに挿入されるときに呼び出されます (親ノードが存在することを保証するだけで、必ずしもドキュメントに挿入されるわけではありません)
  • update: コンポーネントの VNode が更新されたときに呼び出されますが、子 VNode が更新される前に発生することもあります。命令の値は変更されている場合と変更されていない場合があります。ただし、更新前と更新後の値を比較することで、不要なテンプレートの更新を無視することができます。
  • componentUpdated: 命令が配置されているコンポーネントのVNodeとその子VNodeがすべて更新された後に呼び出されます。
  • unbind: 命令が要素からアンバインドされたときに一度だけ呼び出されます

すべてのフック関数のパラメータは次のとおりです。

  • el: 命令がバインドされている要素。DOMを直接操作するために使用できます。
  • バインディング: 次のプロパティを含むオブジェクト:

`name`: v- プレフィックスを除いたディレクティブの名前。

`value`: ディレクティブのバインディング値。たとえば、v-my-directive="1 + 1" の場合、バインディング値は 2 です。

`oldValue`: ディレクティブ バインディングの前の値。update フックと componentUpdated フックでのみ使用できます。値が変更されたかどうかに関係なく使用できます。

`expression`: 文字列としてのディレクティブ式。たとえば、v-my-directive="1 + 1" の場合、式は "1 + 1" になります。

`arg`: コマンドに渡されるパラメータ(オプション)。たとえば、v-my-directive:foo の場合、パラメーターは "foo" です。

`modifiers`: 修飾子を含むオブジェクト。たとえば、v-my-directive.foo.bar では、修飾子オブジェクトは { foo: true, bar: true } です。

`vnode`: Vue コンパイルによって生成された仮想ノード

`oldVnode`: 以前の仮想ノード。update および componentUpdated フックでのみ使用可能

el を除き、他のすべてのパラメータは読み取り専用であり、変更しないでください。フック間でデータを共有する必要がある場合は、要素のデータセットを介して共有することをお勧めします。

例えば:

<div v-demo="{ color: 'white', text: 'hello!' }"></div>
<スクリプト>
    Vue.directive('demo', 関数(el, バインディング) {
    console.log(binding.value.color) // "白"
    console.log(binding.value.text) // "こんにちは!"
    })
</スクリプト>

3. 応用シナリオ

カスタム コンポーネントを使用すると、日常のシナリオの一部に対応できます。カスタム コンポーネントの例をいくつか示します。

  • 安定
  • 画像の遅延読み込み
  • ワンクリックコピー機能

入力ボックスの手ぶれ補正

この場合、Vスロットルカスタム命令を設定して手ぶれ防止を実現する

例えば:

// 1. v-throttleカスタムディレクティブを設定する Vue.directive('throttle', {
  バインド: (el, バインディング) => {
    let throttleTime = binding.value; // 手ぶれ補正時間if (!throttleTime) { // ユーザーが手ぶれ補正時間を設定していない場合、デフォルトは2秒です
      スロットル時間 = 2000;
    }
    cbFun を実行します。
    el.addEventListener('クリック', イベント => {
      if (!cbFun) { // 最初の実行 cbFun = setTimeout(() => {
          cbFun = null;
        }, スロットル時間);
      } それ以外 {
        イベント && event.stopImmediatePropagation();
      }
    }、 真実);
  },
});
// 2. ボタン タグに v-throttle カスタム命令を設定します <button @click="sayHello" v-throttle>Submit</button>

画像の遅延読み込み

画像の遅延読み込みを完了するためにv-lazyカスタムコンポーネントを設定する

定数LazyLoad = {
    // インストールメソッド install(Vue,options){
       // image の代わりに画像を読み込みます let defaultSrc = options.default;
        Vue.directive('lazy',{
            バインド(el,バインディング){
                LazyLoad.init(el、binding.value、defaultSrc);
            },
            挿入された(el){
                // 互換性処理 if('InterpObserver' in window){
                    LazyLoad.observe(el);
                }それ以外{
                    LazyLoad.listenerScroll(el);
                }
                
            },
        })
    },
    // 初期化 init(el,val,def){
        // src は実際の src を格納します
        el.setAttribute('src',val);
        // src を読み込み画像に設定します el.setAttribute('src',def);
    },
    // InterpObserverを使用してelを監視する
    観察する{
        io = new InterpObserver(エントリ => {
            realSrc = el.dataset.src; とします。
            エントリ[0]が交差している場合
                if(realSrc){
                    el.src = 実Src;
                    el.removeAttribute('src');
                }
            }
        });
        io.observe(el);
    },
    // スクロールイベントをリッスンする listenerScroll(el){
        ハンドラをLazyLoad.throttle(LazyLoad.load,300);
        LazyLoad.load(el);
        window.addEventListener('スクロール',() => {
            ハンドラ(el);
        });
    },
    // 実画像を読み込む load(el){
        windowHeight = document.documentElement.clientHeight とします。
        elTop を el.getBoundingClientRect().top とします。
        elBtm = el.getBoundingClientRect().bottom; とします。
        realSrc = el.dataset.src; とします。
        if(elTop - windowHeight<0&&elBtm > 0){
            if(realSrc){
                el.src = 実Src;
                el.removeAttribute('src');
            }
        }
    },
    // スロットル(fn,遅延){
        タイマーを設定します。 
        prevTime を設定します。
        関数(...引数)を返す{
            currTime = Date.now() とします。
            コンテキストを this とします。
            前の時刻が現在の時刻と等しい場合、前の時刻は現在の時刻と等しくなります。
            タイマーをクリアします。
            
            (現在の時刻 - 前の時刻 > 遅延) の場合 {
                前回の時刻 = 現在の時刻;
                fn.apply(コンテキスト、引数);
                タイマーをクリアします。
                戻る;
            }
 
            タイマー = setTimeout(関数(){
                前の時刻 = Date.now();
                タイマー = null;
                fn.apply(コンテキスト、引数);
            }、遅れ);
        }
    }
 
}
デフォルトのLazyLoadをエクスポートします。

ワンクリックコピー機能

'ant-design-vue' から { Message } をインポートします。
 
const vCopy = { //
  /*
    バインドフック関数は、初めてバインドするときに呼び出され、初期化設定を行うために使用できます。el: 操作する DOM オブジェクト。value: 命令に渡される値、つまりコピーしたい値*/
  バインド(el, { 値 }) {
    el.$value = value; // この値は他のフック関数で使用されるため、渡された値を格納するためにグローバルプロパティを使用します。el.handler = () => {
      if (!el.$value) {
      // 値が空の場合、プロンプトを表示します。ここで使用しているプロンプトは ant-design-vue のプロンプトです。自由に使用できます。Message.warning('No copy content');
        戻る;
      }
      // textarea タグを動的に作成します。const textarea = document.createElement('textarea');
      // iOS 上でキーボードが自動的に表示されないようにするために textarea を読み取り専用に設定し、textarea を表示領域から移動します。textarea.readOnly = 'readonly';
      textarea.style.position = '絶対';
      textarea.style.left = '-9999px';
      // コピーする値を textarea タグの value 属性に割り当てます。textarea.value = el.$value;
      // 本文にテキストエリアを挿入します。 document.body.appendChild(textarea);
      // 値を選択してコピーします textarea.select();
      // textarea.setSelectionRange(0, textarea.value.length);
      const result = document.execCommand('コピー');
      if (結果) {
        Message.success('コピーが成功しました');
      }
      document.body.removeChild(テキストエリア);
    };
    // クリック イベント (いわゆるワンクリック コピー) をバインドします。el.addEventListener('click', el.handler);
  },
  // 入力値が更新されると、componentUpdated(el, { value }) がトリガーされます。
    el.$value = 値;
  },
  // 命令が要素からアンバインドされたら、イベントバインディングを削除します unbind(el) {
    el.removeEventListener('click', el.handler);
  },
};
 
デフォルトの vCopy をエクスポートします。

ドラッグ

<div ref="a" id="bg" v-drag></div>

  ディレクティブ: {
    ドラッグ: {
      バインド() {},
      挿入(el) {
        el.onmousedown = (e) => {
          x = e.clientX - el.offsetLeft とします。
          y = e.clientY - el.offsetTop とします。
          ドキュメント.onmousemove = (e) => {
            xx = e.clientX - x + "px" とします。
            yy = e.clientY - y + "px" とします。
            el.style.left = xx;
            el.style.top = yy;
          };
          el.onmouseup = (e) => {
            ドキュメント.onmousemove = null;
          };
        };
      },
    },
  },

ドラッグ アンド ドロップの指示、ページの透かし、権限の検証など、カスタム コンポーネントの適用シナリオは多数あります。

要約する

Vue のカスタム ディレクティブに関するこの記事はこれで終わりです。Vue のカスタム ディレクティブに関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vueカスタム命令の詳細な説明
  • Vueカスタムディレクティブの詳細
  • Vueカスタムコピー命令v-copy関数の実装

<<:  MySQL テーブルがロックされているかどうかを照会する方法

>>:  MySQL 結合クエリ構文と例

推薦する

CentOS7 システムでスワップを増やす方法の例

序文スワップは、ディスク上にある「仮想メモリ」の一部である特殊なファイル (またはパーティション) ...

Linuxの簡単な分析でファイアウォールの状態と外部に開いているポートの状態を確認する

1. ファイアウォールの状態を確認するファイアウォールのステータスを確認する systemctl s...

Mysqlトランザクション処理の詳細な説明

1. MySQLのトランザクションの概念MySQL トランザクションは主に、操作量が多く複雑度の高い...

HTML+CSS+JavaScript でシンプルな三目並べゲームを作成する

目次HTMLの実装CSSを追加Javascript部分の実装デモアドレス HTMLの実装まず、hea...

MySQLデスクトップツールSQLyogのリソースとアクティベーション方法は、白黒のコマンドラインに別れを告げます

では、早速リソースについて見ていきましょう。 123WORDPRESS.COM ダウンロードSQLy...

MySQL 8.0.15 圧縮版インストール グラフィック チュートリアル

この記事では、参考までにMySQL 8.0.15圧縮版のインストール方法を紹介します。具体的な内容は...

CSS でよく使用されるフォントサイズ、フォント単位、行の高さの詳細な説明

px(ピクセル)ピクセルという言葉は皆さんもよくご存知だと思います。次に、この単位に関するちょっとし...

GIFアニメーション効果を模倣した自動ビデオ再生を実現するWeChatアプレットの例

需要背景:ミニプログラムページに GIF ダイナミック画像を挿入しますが、GIF 画像は通常サイズが...

1つのSQL文でMySQLの重複排除が完了し、1つが保持されます。

数日前、ある要件に取り組んでいたとき、MySQL で重複レコードをクリーンアップする必要がありました...

React Hooksの使用例

目次簡単なコンポーネントの例より複雑な親子コンポーネントのケースオンセレクトの書き方反応する子供Re...

ウィンドウ表示効果を実現するJavaScript

この記事では、ウィンドウ表示効果を実現するためのJavaScriptの具体的なコードを参考までに紹介...

Linux で Oracle データベースをバックアップするためのスケジュールされたタスクの設定に関するチュートリアル

1. データベースの文字セットを確認するデータベースの文字セットは、Linux で設定された環境変数...

Dockerコンテナの個別展開のためのLNMPの実装

1. 環境整備各コンテナの IP アドレス: nginx: 172.16.10.10マイSQL: 1...

Docker で Redis センチネル モードを構成する方法 (複数のサーバー上)

目次序文状態DockerをインストールするRedisのマスターノードとスレーブノードを構成する序文以...

dockerを使用してGrafana+Prometheus構成をデプロイする

docker-compose-monitor.yml バージョン: '2' ネットワ...