blog

Vueでデコレーターを使う、マジで!

製品が発売されるとやることがたくさんあり、テスト製品はいつも押されます。\n私の目は絵の具のようで、体は泥のようです。\n元Javaコーダーとして、jsのデコレーターを初めて見たとき、すぐにJavaの...

Feb 18, 2020 · 11 min. read
シェア

製品がラインアップされるとやることがたくさんあって、テスト製品は常にプッシュされます。虫が何匹残っているかなんて聞かないで、目は絵の具のよう、体は泥のよう。

元Javaコーダーとして、jsのデコレータを初めて見たとき、すぐにJavaのアノテーションを思い浮かべました。もちろん、上記の実際の原理や機能において、Javaのアノテーションとjsのデコレータはやはり大きく異なります。この記事のタイトルは、Vueでのデコレータの使用ですが、私は深刻ですが、この記事では、デコレータの開発チャットの概念からになります、それを見てみましょう。

この記事の内容を通して、あなたは以下のことを学ぶでしょう。

  1. デコレーターとは何か
  2. メソッドでのデコレータの使用
  3. クラスでデコレーターを使う
  4. Vueでデコレータを使う

デコレーターとは

アンチシェイクやスロットリングは、日々の開発やバグ取りの際によく使われます。

let obj = { name: ' , officialAccounts: 'フロントエンドは、"再生する必要がある }
Object.defineProperty(obj,'name', { // writeableをfalseに設定すると、この属性は変更されない。 writable: false }) // オブジェクトを修正する.name obj.name = " // プリントはまだZijunである console.log(obj.name)

デバウンスとログ2つの関数では、上記のコードは、本質的に2つのパッケージング関数は、パッケージングの元の関数のこれらの2つの関数を介して、ので、元の関数の動作が変更され、jsのデコレータの原理は、このように、上記のコード変換のデコレータの使用です。

/** *@param wait 遅延 */ function debounce(wait) { return function(target, name, descriptor) { descriptor.value = debounce(descriptor.value, wait) } } // 使用方法 class MyClass { @debounce(100) follow() { console.log('Zijunは、フロントエンドが再生する必要があり、注意がああ驚きを持っている') } }

デコレーターの形式は、@ + 関数名で、パラメータがある場合は括弧で囲みます。

メソッドでのデコレータの使用

デコレータは、上記のクラスまたはクラス属性に適用することができますが、一般的に、上記のクラス属性に適用されるシーンは、上記のログ、デバウンスなど、一般的に上記のクラス属性に適用され、特定のデコレータを実装する方法を見て、次の上記のクラスに適用されます。デコレータの実装では、最初にプロパティ記述子を理解する必要があります

プロパティ記述子を知る

オブジェクトのプロパティを定義する際、プロパティの上には、そのプロパティが変更可能か、列挙可能か、削除可能かなどを示すプロパティ記述子が多数存在します。同時に、ECMAScriptでは、これらのプロパティ記述子をデータプロパティとアクセッサプロパティの2つに分けており、データプロパティとアクセッサプロパティは共存できません。

データプロパティ

data 属性には、値を読み書きできるデータ値の場所が含まれます。data属性は、4つの記述子を含んでいます。

  1. コンフィギュラブル

    deleteによって属性を削除できるかどうか、属性の他の記述子特性を変更できるかどうか、データ属性をアクセサ属性に変更できるかどうかを示します。let obj = {name: ''}でオブジェクトが宣言されると、このオブジェクト内のすべてのプロパティの設定可能な記述子値はtrueになります。

  2. 列挙可能

    一般的に、この記述子の値は、宣言されたオブジェクトに対してはtrueですが、クラス内の属性に対してはfalseです。

  3. 書き込み可能

    属性のデータ値を変更できるかどうかを示します。これをfalseに変更すると、属性の読み取り専用効果が得られます。

  4. 価値

    現在の属性のデータ値を示します。属性値を読み込む場合はここから読み込まれ、属性値を書き込む場合はこの場所に書き込まれます。

アクセサのプロパティ

一方、configurable と enumerable は、データプロパティとアクセッサプロパティの両方に共通する記述子です。

  1. ゲッター

    この関数は、プロパティが読み込まれたときに呼び出され、デフォルトでは未定義です。

  2. セッター

    この関数は、プロパティの値が書き込まれるときに呼び出され、デフォルトでは未定義です。

これらの6つの記述子について学んだ後、いくつかの疑問が浮かぶかもしれません。これらのプロパティ記述子は、今日のトピックとどのような関係があるのでしょうか?その答えを見つける時が来ました。

使うdescriptor.value = debounce(descriptor.value, wait)

// これは、ミックスするオブジェクトである const methods = { logger() { console.log('記録') } } // これはログインとログアウトのクラスである class Login{ login() {} logout() {} } Vue 2.0の双方向バインディングの原理を知っていれば、Vueの双方向バインディングはデータ属性のゲッターメソッドとセッターメソッドを定義することで実現されることを知っているはずです。

// これはミックスするオブジェクトである const methods = { logger() { console.log('記録') } } // これはロゲインとローガンへの戯言である。 class Login{ login() {} logout() {} }

function mixins(obj) { return function (target) { Object.assign(target.prototype, obj) } } // その後、装飾をミックスする @mixins(methods) class Login{ login() {} logout() {} } このオブジェクト内のユーザー名は変更できないようにしたいのですが、どのように定義すればよいでしょうか?

function mixins(obj) { return function (target) { Object.assign(target.prototype, obj) } } // その後、装飾はミックスする。 @mixins(methods) class Login{ login() {} logout() {} }

vue-property-decoratorオブジェクト・プロパティのプロパティ記述子を定義または変更するには、 を使用します。データ・プロパティとアクセサ・プロパティは互いに排他的なので、一度に変更できるのはどちらか一方だけです。

アンチシェイク・デコレーターの定義

デコレーターは本質的にはまだ関数ですが、この関数には固定パラメーターがあります。

parserOptions: { ecmaFeatures:{ // デコレーターサポート legacyDecorators: true } }

一行ずつ進んでコードを分析

  1. まず、デバウンス関数が1つの引数waitで定義されます。これは、次のデコレータの呼び出しで使われる@debounce(100)に対応します。
  2. debounce関数は新しい関数を返します。この関数はデコレータの核となるもので、3つのパラメータを持ちます。
    1. ターゲット:関数がマウントされているクラス、例えば、MyClass。
    2. 記述子:これは属性記述子であり、直接上記の属性を記述することにより、属性の読み取り専用、データの書き換えやその他の機能を実現することができます。
  3. function log() { /** * @param target メソッドに対応するオブジェクト * @param name 対応するプロパティのメソッドの名前 * @param descriptor 属性メソッドに対応する修飾子 */ return function(target, name, descriptor) { console.log(target, name, descriptor) const fn = descriptor.value descriptor.value = function(...rest) { console.log(`これは呼び出し方法である${name}旧印刷ジャーナル`) fn.call(this, ...rest) console.log(`これは呼び出し方法である${name}印刷後のログ`) } } } export default { created() { this.getData() }, methods: { @log() getData() { console.log('データを入手する) } } } そして3行目、すでに学んだように、属性記述子の上の値はこの属性の値に対応しているので、この属性をオーバーライドすることで、デバウンス関数でラップされます。

上記の3つのステップにより、クラス属性の上で利用可能なデコレーターが実装され、同時にクラス属性に適用されます。

クラスでのデコレータの使用

デコレータは、クラスの属性に適用するだけでなく、上記のクラスに直接適用することもできます。たとえば、私はいくつかのメソッドの属性に混在するクラスに、その関数の同様のVueのミックスインを実現できるようにしたいのですが、私はそれについてどのように行くべきでしょうか?

function log() { /** * @param target オブジェクトにメソッドに応じる * @param name 対応するプロパティのメソッドの名前 * @param descriptor 属性石工の装飾家 */ return function(target, name, descriptor) { console.log(target, name, descriptor) const fn = descriptor.value descriptor.value = function(...rest) { console.log(`これはアイデアを呼び出す方法である${name}古い印刷ジャーナル`) fn.call(this, ...rest) console.log(`これはアイデアを呼び出す方法である${name}印刷後のロゴ`) } } } export default { created() { this.getData() }, methods: { @log() getData() { console.log('(データを使い始める) } } }

上記のメソッドをLoginに混ぜるには、まずクラス・デコレーターを実装します。

import { throttle, debounce } from 'lodash' /** * ファンクション・スロットリング・デコレーター * @param {number} wait ミリ秒単位のスロットル * @param {Object} options スロットルオプションオブジェクト * [options.leading=true] (boolean): スロットリングが始まる前にコールを指定する。 * [options.trailing=true] (boolean): 通話はスロットリングの終了時に指定する。 */ export const throttle = function(wait, options = {}) { return function(target, name, descriptor) { descriptor.value = throttle(descriptor.value, wait, options) } } /** * 手ぶれ補正機能 * @param {number} wait 何ミリ秒の遅延が必要か。 * @param {Object} options オプション * [options.leading=false] (boolean): 遅延が始まる前にコールすることを指定する。 * [options.maxWait] (number): ファンクが遅延させられる最大値を設定する。 * [options.trailing=true] (boolean): ディレイ終了時にコールすることを指定する。 */ export const debounce = function(wait, options = {}) { return function(target, name, descriptor) { descriptor.value = debounce(descriptor.value, wait, options) } }

これはクラス・デコレーターを実装したものです。クラスデコレータの引数は target のみで、これはクラスそのものに対応します。

デコレータを理解したら、次はVueでのデコレータの使い方を見てみましょう。

Vueでデコレータを使う

import {debounce} from '@/decorator' export default { methods:{ @debounce(100) resize(){} } } tsの開発Vueの学生の使用は奇妙に感じることはありませんする必要があります、このプラグインは、開発時に使用するすべての人に便利なデコレータの数を提供し、もちろん、この記事の真ん中のポイントは、このプラグインではありません。実際には、プロジェクトがtsを使用していない場合は、また、デコレータを使用することができ、どのようにそれを使用するには?

ベース環境の設定

いくつかの古いプロジェクトに加えて、今、一般的な新しいVueのプロジェクトは、新しいプロジェクトを作成するための足場vue-cli3/4を使用することを選択し、この時間は、新しいプロジェクトは、デコレータのデフォルトのサポートを持って、あまりにも多くのことを追加設定する必要はありませんが、あなたのプロジェクトはeslintを使用している場合は、eslintのために次のように設定する必要があります。

import {debounce} from '@/decorator' export default { methods:{ @debounce(100) resize(){} } }

デコレーターの使用

Vueのコンポーネントは一般的にオブジェクトをエクスポートするように記述されていますが、上記の例のログのように、コンポーネント内で直接デコレータを使用することには影響しません。

export default { methods:{ async getData() { const loading = Toast.loading() try{ const data = await loadData() // その他の操作 }catch(error){ // 例外処理 Toast.fail('ロードに失敗した'); }finally{ loading.clear() } } } }

上記のコードを見て、デコレータを使用してVueで発見されていない、まだ非常にシンプルであり、上記のプロパティのクラスでは、まったく同じように使用しますが、そこに1つのことは、上記のメソッド内のメソッドでは、デコレータの使用に注意してください、この時間は、デコレータのターゲットは、メソッドに対応しています。

メソッドでデコレータを使うだけでなく、 ライフサイクルフック関数でもデコレータを使うことができます。

一般的なデコレーター

次の小さなリストでは、プロジェクトのいくつかの小さな一般的に使用されるいくつかのデコレータの便宜のために

ファンクション・スロットリングとディザリング

関数スロットルとアンチシェイクアプリケーションシナリオは比較的広いですが、時間の一般的な使用は、スロットルまたはデバウンス関数のメソッドを介してパッケージ化されるために呼び出される、あなたは今、これらの2つの関数は、デコレータにパッケージ化されていると述べた上記の内容を使用することができます、アンチシェイクは、lodashによって提供されるメソッドを使用してスロットル、また、独自のスロットルとアンチシェイク関数ああを実現することができます!

import { Toast } from 'vant' /** * loading * @param {*} message ヒント * @param {function} errorFn 例外処理ロジック */ export const loading = function(message = ' ...', errorFn = function() {}) { return function(target, name, descriptor) { const fn = descriptor.value descriptor.value = async function(...rest) { const loading = Toast.loading({ message: message, forbidClick: true }) try { return await fn.call(this, ...rest) } catch (error) { // 失敗した呼び出しとユーザー定義の失敗したコールバック関数では、次に実行する errorFn && errorFn.call(this, error, ...rest) console.error(error) } finally { loading.clear() } } } }

カプセル化後

export default { methods:{ @loading('ローディング') async getData() { try{ const data = await loadData() // その他の操作 }catch(error){ // 例外処理 Toast.fail('ロードに失敗した'); } } } }

loading

データをロードする際、ユーザーに親切な注意喚起を与える一方、ユーザーが操作を続行することを防止するため、一般的にロードの表示前に要求し、ロードをオフにする要求の終了後、一般的な書き方は次のとおりです。

import { Dialog } from 'vant' export default { methods: { deleteData() { Dialog.confirm({ title: ' , message: 'あなたがデータを削除したいことを確認し、この操作は返すことができない。 }).then(() => { console.log('ここで削除操作を行う') }) } } }

上記のロードロジックは、デコレータを使って次のようにラップすることができます。

import { Dialog } from 'vant' /** * 確認プロンプトボックスデコレーター * @param {*} message ヒント * @param {*} title * @param {*} cancelFn コールバック関数をキャンセルする */ export function confirm( message = 'あなたがデータを削除したいことを確認し、この操作は返すことができない。, title = ' , cancelFn = function() {} ) { return function(target, name, descriptor) { const originFn = descriptor.value descriptor.value = async function(...rest) { try { await Dialog.confirm({ message, title: title }) originFn.apply(this, rest) } catch (error) { cancelFn && cancelFn(error) } } } }

次に、上記のコンポーネントコードを変換します。

export default { methods: { // あなたは、パラメータを渡すことができない、デフォルトのパラメータを使用する @confirm() deleteData() { console.log('ここで削除操作を行う') } } }

確認ボックス

削除ボタンをクリックすると、一般的には、削除するかどうかをユーザーに確認するためのプロンプトボックスをポップアップ表示する必要があります。

export default { methods: { @confirm() @loading() async deleteData() { await delete() } } }

上記の確認プロセスは、次のようにデコレータとして提案することができます。


そして、再度確認ボックスを使うときは、次のようにします。


即座にはるかに単純ではありませんが、もちろん、あなたは、記事の限られた内容のため、一時的にこれらの3つを提供し、多くのデコレータの多くをカプセル化し続けることができます。

デコレーターの併用

上記でクラス属性にデコレータを使う場合、デコレータは組み合わせて使えると言いましたが、Vueのコンポーネントでも同様で、例えば削除を確認した後にインターフェイスを呼び出す際にローディングを表示したい場合は、以下のように記述します。


このセクションで定義されたデコレータは、このプロジェクト に適用されている 、これはVantの開発に基づいて、すぐに使えるモバイルフレームワークであり、あなただけの任意の設定を行うことなく、ビジネス開発のために直接することができ、フォークダウンする必要があり、星を与えるためにトラブルのように、使用することを歓迎します。

結論

インスピレーションとイマジネーションを吹き飛ばすな。モデルの奴隷になるな。 --ヴィンセント・ヴァン・ゴッホ

Read next

OpenGL-ポリゴンオフセットとカラーブレンド

深度テストを使用することで、隠面消去の問題を解決できることを話しました。結果は完璧に見えますが、本当に深度テストに問題はないのでしょうか?もちろんそうではありません。では、テストの問題の深さについて見ていきましょう:\nI.深さテストの潜在的なリスク:Zファイト(Zコンフリクト、フラッシュ)

Feb 18, 2020 · 5 min read