VueはElementUIのフォームサンプルコードを模倣する

VueはElementUIのフォームサンプルコードを模倣する

実装要件

ElementUI を模倣したフォームは、インデックス コンポーネント、Form フォーム コンポーネント、FormItem フォーム項目コンポーネント、Input および CheckBox コンポーネントの 4 つのレイヤーに分かれています。具体的な分担は次のとおりです。

インデックスコンポーネント:

  • 実装: アセンブリを実現するために、Form コンポーネント、FormItem コンポーネント、Input コンポーネントをそれぞれ導入します。

フォームフォームコンポーネント:

  • 実装: 予約済みスロット、管理データ モデル モデル、カスタム検証ルール、グローバル検証メソッドの検証。

FormItem フォーム項目コンポーネント:

  • 実装: スロットを予約し、ラベルを表示し、データ検証を実行し、検証結果を表示します。

入力およびチェックボックスコンポーネント:

  • 実装: データ モデル v-model をバインドし、FormItem コンポーネントに検証を実行するように通知します。

入力コンポーネント

具体的な実装は以下のとおりです。

1. カスタム コンポーネントは、v-model を実装するために :value と @input を実装する必要があります。

2. 入力ボックスのデータが変更されたら、親コンポーネントに通知して検証を実行します。

3. 入力コンポーネントのタイプがパスワードの場合、コンポーネント内で v-bind="$attrs" を使用して、props 以外のコンテンツを取得します。

4. 最上位コンテナーが属性を継承しないようにするには、inheritAttrs を false に設定します。

入力コンポーネントの実装:

<テンプレート>
 <div>
 <input :value="値" @input="onInput" v-bind="$attrs" />
 </div>
</テンプレート>

<スクリプト>
エクスポートデフォルト{
 inheritAttrs: false, // トップレベルのコンテナがプロパティを継承しないようにする props: {
 価値: {
 タイプ: 文字列、
 デフォルト: ""
 }
 },
 データ() {
 戻る {};
 },
 メソッド: {
 入力時(e) {
 // 親コンポーネントに値の変更を通知します this.$emit("input", e.target.value);
 
 // FormItem に検証を実行するよう通知します // Input コンポーネントと FormItem コンポーネントの間に世代が存在する可能性があるため、この記述方法は堅牢ではありません this.$parent.$emit("validate");
 }
 }
};
</スクリプト>

<スタイル スコープ></style>

注: コードでは、イベントをディスパッチするために this.$parent を使用します。この記述方法は堅牢ではなく、Input コンポーネントと FormItem コンポーネントの間に世代のギャップがある場合に問題が発生します。具体的な解決策については、記事の最後にあるコード最適化のセクションを参照してください。

チェックボックスコンポーネント

1. input と同様に、checkBox の双方向データ バインディングをカスタマイズします。:checked と @change を実装する必要があります。

CheckBox コンポーネントの実装:

<テンプレート>
 <セクション>
 <input type="checkbox" :checked="チェック済み" @change="onChange" />
 </セクション>
</テンプレート>

<スクリプト>

エクスポートデフォルト{
 小道具: {
 チェック済み:
 タイプ: ブール値、
 デフォルト: false
 }
 },
 モデル: {
 プロパティ: "チェック済み",
 イベント: 「変更」
 },
 メソッド: {
 onChange(e) {
 this.$emit("change", e.target.checked);
 this.$parent.$emit("検証");
 }
 }
};
</スクリプト>
<style スコープ lang="less"></style>

FormItem コンポーネント

具体的な実装は以下のとおりです。

1. Input コンポーネントまたは CheckBox コンポーネント用のスロットを予約します。

2. ユーザーがコンポーネントにラベル属性を設定すると、ラベル タグが表示されます。

3. 検証イベントをリッスンし、検証を実行します (検証には async-validator プラグインを使用します)。

4. 検証ルールが満たされていない場合は、検証結果を表示する必要があります。

開発プロセスでは、いくつかの問題について考える必要があります。

1. コンポーネント内で検証する必要があるデータと検証ルールを取得するにはどうすればよいですか?

2. フォームには、ユーザー名、パスワード、電子メールなど、複数のメニュー項目があります。FormItem コンポーネントは、どのメニューが検証されているかをどのように認識するのでしょうか?

FormItem コンポーネントの実装:

<テンプレート>
 <div class="formItem-wrapper">
 <div class="content">
 <label v-if="label" :style="{ width: labelWidth }">{{ label }}:</label>
 <スロット></スロット>
 </div>
 <p v-if="errorMessage" class="errorStyle">{{ errorMessage }}</p>
 </div>
</テンプレート>

<スクリプト>
「async-validator」からスキ​​ーマをインポートします。

エクスポートデフォルト{
 挿入: ["formModel"],
 小道具: {
 ラベル: {
 タイプ: 文字列、
 デフォルト: ""
 },
 プロパティ: 文字列
 },
 データ() {
 戻る {
 エラーメッセージ: "",
 ラベル幅: this.formModel.labelWidth
 };
 },
 マウント() {
 // 検証イベントをリッスンし、検証を実行します this.$on("validate", () => {
 これを検証します。
 });
 },
 メソッド: {
 検証() {
 // コンポーネント検証を実行する // 1. データを取得する const values ​​= this.formModel.model[this.prop];
 // 2. 検証ルールを取得する const rules = this.formModel.rules[this.prop];
 // 3. 検証を実行する const schema = new Schema({
 [this.prop]: ルール
 });

 // パラメータ 1 は値、パラメータ 2 は検証エラー オブジェクトの配列です。// 検証は Promise<Boolean> を返します。
 schema.validate({ [this.prop]: values ​​}, errors => { を返します。
 if (エラー) {
 this.errorMessage = エラー[0].メッセージ;
 } それ以外 {
 this.errorMessage = "";
 }
 });
 }
 }
};
</スクリプト>

<style スコープ lang="less">
@ラベル幅: 90px;

.formItemラッパー{
 パディング下部: 10px;
}
。コンテンツ {
 ディスプレイ: フレックス;
}
.errorStyle {
 フォントサイズ: 12px;
 色: 赤;
 マージン: 0;
 左パディング: @labelWidth;
}
</スタイル>

まず、上記の 2 つの質問に答えてみましょう。これには、コンポーネント間の値の転送が含まれます。前回の記事「コンポーネントの値の転送と通信」を参照してください。
まず、フォーム データと検証ルールがインデックス コンポーネント内で定義され、Form コンポーネントにマウントされます。フォーム検証項目は FormItem コンポーネントで発生します。Form コンポーネントは最初に props を通じて渡されたデータを受け取り、次に provide/inject を通じて FormItem コンポーネントの子孫コンポーネントに渡します。

日常生活で ElementUI のフォーム検証を使用すると、検証が必要な各フォームに prop 属性が設定され、その属性値がバインドされたデータと一致していることがわかります。ここでの目的は、FormItem コンポーネントで検証を実行するときに、相対的な検証ルールとデータ オブジェクトを取得できるようにすることです。

FormItem コンポーネントでは、inject を使用して注入された Form インスタンスを取得し、prop 属性と組み合わせることで、フォーム データと検証ルールを取得できます。

// 1. データを取得する const values ​​= this.formModel.model[this.prop];

// 2. 検証ルールを取得する const rules = this.formModel.rules[this.prop];

async-validator プラグインを使用して、検証用のスキーマ オブジェクトをインスタンス化します。schema.validate は 2 つのパラメータを渡す必要があります。パラメータ 1 は、現在検証対象のフィールドと対応するルールで構成されるキーと値のペアのオブジェクトです。パラメータ 2 は、エラー情報 (配列) を取得するために使用されるコールバック関数です。検証メソッドは Promise<Boolean> を返します。

注: このコンポーネントの検証メソッドで、最後に return を使用する目的は、Form コンポーネントでグローバル検証を実行することです。

フォームコンポーネント

具体的な実装は以下のとおりです。

1. FormItem コンポーネント用のスロットを予約します。

2. Form インスタンスを FormItem などの子孫に渡して、検証データとルールを取得します。

3. グローバル検証を実行する

フォームコンポーネントの実装:

<テンプレート>
 <div>
 <スロット></スロット>
 </div>
</テンプレート>

<スクリプト>
エクスポートデフォルト{
 提供する() {
 戻る {
 formModel: this // 検証データとルールを取得するために、Form インスタンスを FormItem などの子孫に渡します};
 },
 小道具: {
 モデル: {
 タイプ: オブジェクト、
 必須: true
 },
 ルール:
 タイプ: オブジェクト
 },
 ラベル幅: 文字列
 },
 データ() {
 戻る {};
 },
 メソッド: {
 検証(cb) {
 // グローバル検証を実行します // マップの結果は Promise の配列です const tasks = this.$children.filter(item => item.prop).map(item => item.validate());
 // 検証済みとみなされるには、すべてのタスクが正常に検証される必要があります。Promise.all(tasks)
 .then(() => {
 cb(真);
 })
 .catch(() => {
 cb(偽);
 });
 }
 }
};
</スクリプト>

<スタイル スコープ></style>

Form コンポーネントで provide を使用して現在のコンポーネント オブジェクトを注入し、後続の子孫がデータやメソッドを取得しやすくします。

グローバル検証を実行する場合、まずフィルターを使用して検証する必要のないコンポーネントを除外し (FormItem コンポーネントに設定した prop 属性は、この属性がある限り検証する必要があります)、次にコンポーネント内で個別に検証メソッドを実行し (FormItem コンポーネントで戻りデータが使用されない場合、最終的に取得されるすべてのデータは未定義になります)、Promise の配列を返します。

Promise.all() メソッドを簡単に紹介します。

Promise.all() メソッドは、反復可能なタイプの Promise (注: Array、Map、Set はすべて ES6 の反復可能なタイプに属します) の入力を受け取り、1 つの Promise インスタンスのみを返します。その入力のすべての Promise の解決コールバックの結果は配列です。この Promise の解決コールバックは、すべての入力 Promise の解決コールバックが完了したとき、または入力反復可能オブジェクトに Promise が存在しないときに実行されます。拒否コールバックが実行され、入力プロミスの拒否コールバックが実行されるか、無効なプロミスが入力されると、エラーが直ちにスローされ、スローされた最初のエラーメッセージが拒否されます。

インデックスコンポーネント

モデルデータ、検証ルールなどを定義し、Form コンポーネント、FormItem コンポーネント、Input コンポーネントをそれぞれ導入してアセンブリを実装します。

インデックスコンポーネントの実装:

<テンプレート>
 <div>
 <フォーム:model="formModel":rules="rules"ref="loginForm"label-width="90px">
 <FormItem label="ユーザー名" prop="ユーザー名">
 <Input v-model="formModel.username"></Input>
 </フォーム項目>
 <FormItem label="パスワード" prop="パスワード">
 <入力タイプ="パスワード" v-model="formModel.パスワード"></入力>
 </フォーム項目>
 <FormItem label="パスワードを記憶する" prop="記憶する">
 <チェックボックス v-model="formModel.remember"></チェックボックス>
 </フォーム項目>
 <フォーム項目>
 <button @click="onLogin">ログイン</button>
 </フォーム項目>
 </フォーム>
 </div>
</テンプレート>

<スクリプト>
「@/components/form/Input」からInputをインポートします。
'@/components/form/CheckBox' から CheckBox をインポートします。
"@/components/form/FormItem" から FormItem をインポートします。
"@/components/form/Form" からフォームをインポートします。

エクスポートデフォルト{
 データ() {
 const validName = (ルール、値、コールバック) => {
 if (!値) {
 callback(new Error("ユーザー名は空にできません"));
 } そうでない場合 (値 !== "admin") {
 callback(new Error("ユーザー名エラー - admin"));
 } それ以外 {
 折り返し電話();
 }
 };
 const validatePass = (ルール、値、コールバック) => {
 if (!値) {
 コールバック(false);
 } それ以外 {
 折り返し電話();
 }
 };
 戻る {
 フォームモデル: {
 ユーザー名: "",
 パスワード: "",
 覚えておいてください: 間違いです
 },
 ルール:
 ユーザー名: [{ 必須: true、バリデータ: validatorName }],
 パスワード: [{ 必須: true, メッセージ: "パスワードが必要です" }],
 記憶: [{ 必須: true、メッセージ: "パスワードを記憶する必要があります", 検証: v​​alidator: validPass }]
 }
 };
 },
 メソッド: {
 ログイン時() {
 this.$refs.loginForm.validate(isValid => {
 有効かどうか
 alert("ログインに成功しました");
 } それ以外 {
 alert("ログインに失敗しました");
 }
 });
 }
 },
 コンポーネント:
 入力、
 チェックボックス、
 フォーム項目、
 形状
 }
};
</スクリプト>

<スタイル スコープ></style>

ログイン ボタンをクリックすると、グローバル検証メソッドが実行され、this.$refs.xxx を使用して DOM 要素とコンポーネント インスタンスを取得できます。

~ の上にも少し余白を残していますが、これは Input コンポーネントで検証を行うように親コンポーネントに通知するためのものです。現在は this.$parent.$emit() が使用されています。この方法には欠点があります。Input コンポーネントと FormItem コンポーネントが世代で離れている場合、this.$parent を使用して FormItem コンポーネントを取得することはできません。
親要素を見つけてイベントをディスパッチするための上向きループを主に実装するディスパッチ メソッドをカプセル化できます。コードは次のとおりです。

ディスパッチ(イベント名、データ) {
 親を this.$parent とします。
 // 親要素を検索する while (parent) {
 // 親要素は $emit parent.$emit(eventName, data); によってトリガーされます。
 // 親要素を再帰的に検索します。parent = parent.$parent;
 }
}

このメソッドはミックスインを使用して導入できます: mixins/emmiters.js

エクスポートデフォルト{
 メソッド: {
 ディスパッチ(イベント名、データ) {
 親を this.$parent とします。
 // 親要素を検索する while (parent) {
 // 親要素は $emit parent.$emit(eventName, data); によってトリガーされます。
 // 親要素を再帰的に検索します。parent = parent.$parent;
 }
 }
 }
};

入力コンポーネントを変更します。

<テンプレート>
 <div>
 <input :value="値" @input="onInput" v-bind="$attrs" />
 </div>
</テンプレート>

<スクリプト>
emmiter を "@/mixins/emmiter" からインポートします。

エクスポートデフォルト{
 inheritAttrs: false, // トップレベルのコンテナ継承属性を避ける mixins: [emmiter],
 小道具: {
 価値: {
 タイプ: 文字列、
 デフォルト: ""
 }
 },
 データ() {
 戻る {};
 },
 メソッド: {
 入力時(e) {
 // 親コンポーネントに値の変更を通知します this.$emit("input", e.target.value);
 
 // FormItem に検証を実行するように通知します // Input コンポーネントと FormItem コンポーネントの間に世代が存在する可能性があるため、この方法は堅牢ではありません // this.$parent.$emit("validate");
 
 this.dispatch("validate"); // レベル間の問題を解決するために、mixin で emmiter のディスパッチを使用します}
 }
};
</スクリプト>

<スタイル スコープ></style>

要約する

Vue で ElementUI のフォームを模倣する記事はこれで終わりです。Vue で ElementUI のフォームを模倣する関連コンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Vue ElementUI フォームのフォーム検証
  • Vue elementUI フォームのネストされた検証サンプルコード
  • Vue elementUI フォーム検証関数配列の多層ネスト
  • Vue elementui フォーム検証の実装
  • Vueの基本 ElementUIのフォームの詳しい説明

<<:  Linux システムでの virtuoso データベースの詳細なインストールと使用

>>:  Mybatis ページングプラグイン pageHelper の詳細な説明と簡単な例

推薦する

MySQL インデックスクエリ最適化スキルを習得するための記事

序文この記事では、DBA がいないチームが参考にできるように、MySQL の一般的な使用に関するヒン...

VScode設定のリモートデバッグLinuxプログラムの問題を解決する

VScode リモートデバッグ Linux プログラムの問題について見てみましょう。具体的な内容は以...

Linux で FastDFS ファイル サーバーを構築するための実装手順

目次1. ソフトウェアパッケージ2. gccをインストールする3. libfastcommonをイン...

nginx で HSTS を有効にしてブラウザを HTTPS アクセスにリダイレクトする方法の詳細な説明

前回の記事では、https を使用したローカルノードサービスアクセスを実装しました。前回の記事の効果...

Nginx で何ができるかの包括的な分析

序文この記事は、サードパーティのモジュールをロードせずにNginxで処理できることのみに焦点を当てて...

HTML/CSSにおける記号論の詳細な説明

この記事では、ソシュールの言語哲学などの理論に基づいて、CSS の class 属性は不要であると主...

Tomcat 初回展開 Web プロジェクト プロセス図

独自のWebプロジェクトをtomcatディレクトリの下のwebappsディレクトリに配置します。 R...

CSSテキストシャドウの徐々にぼやける効果の実装

テキストシャドウテキストに影を追加します。テキストとテキスト装飾に複数のシャドウを追加することができ...

ログインフォームを実装するためのJavaScript

この記事の例では、ログインフォームを実装するためのJavaScriptの具体的なコードを参考までに共...

Mysql ファジークエリが大文字と小文字を区別するかどうかの詳細な調査

序文最近、私は小さな個人ブログ プロジェクトを書くのに忙しくしています。 「グローバル検索」機能を実...

Linuxシステムのログの詳細な紹介

目次1. ログ関連サービス2. システム内の共通ログファイル1. ログ関連サービスCentOS 6....

JavaScript におけるイベント バブリング メカニズムの詳細な分析

バブリングとは何ですか? DOM イベント フローには、イベント キャプチャ ステージ、ターゲット ...

Linux telnetコマンドの使用

1. はじめにtelnet コマンドは、リモート ホストにログインするために使用されます。これは、T...

CSS3 はドラッグ可能なルービックキューブの 3D 効果を実現します

主に使用される知識ポイント: •css3 3D変換 •ネイティブjsマウスドラッグイベント•表示:グ...

MySQL sql_modeの適切な設定に関する詳細な説明

MySQL sql_modeの適切な設定sql_mode は見落とされやすい変数です。デフォルト値は...