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 の詳細な説明と簡単な例

推薦する

Vue スキャフォールディング プロジェクトを作成するための詳細な手順

vue スキャフォールディング -> vue.cli大規模で完全に機能する Vue プロジェク...

mysql 5.7.11 winx64.zip インストールと設定方法のグラフィックチュートリアル

MySql データベース システムをインストールして構成します。 1. ダウンロード http://...

Linuxサーバー間のリアルタイムファイル同期の実現

使用シナリオ既存のサーバー A と B の場合、サーバー A の指定されたディレクトリ (たとえば、...

MySQLインデックスの作成について知っておくべきこと

目次序文: 1. インデックスメソッドを作成する2. インデックスを作成するために必要な権限序文: ...

MySQL カーディナリティ統計の簡単な分析

1. カーディナリティとは何ですか?カーディナリティとは、MySQL テーブルの列内の異なる値の数を...

nginx プロキシ サーバーで双方向証明書検証を構成する方法

証明書チェーンを生成するスクリプトを使用して、ルート証明書、中間証明書、および 3 つのクライアント...

HTML テーブルタグチュートリアル (23): 行の境界線の色属性 BORDERCOLORDARK

行ごとに、暗い境界線の色を個別に定義できます。基本的な構文<TR 境界線の色を暗くする=col...

TomcatはXMLを解析し、リフレクションを通じてオブジェクトを作成します。

次のサンプル コードでは、Tomcat が XML を解析し、リフレクションを通じてオブジェクトを作...

ウェブページの読み込み進捗状況バーの詳細な説明(推奨)

(Web ページの読み込み中に、コンテンツが多すぎて読み込みと待機が続くことがあります。このとき、...

HTMLは正規表現を使用してテーブルの例をテストします

以下は、HTML で正規表現を使用してテーブルをチェックするサンプル コードです。具体的なコードの内...

MySQL で珍しい文字を挿入できないときの対処方法 (文字列値が正しくない)

最近、ビジネス側から、一部のユーザー情報の挿入に失敗し、エラー メッセージが「不正な文字列値:&qu...

Webフロントエンドベクターアイコンの使い方

序文フロントエンドページを書くとき、小さなアイコンなどの画像を使うことが多いです。画像を使うとコード...

Vueが初めて要素を取得できなかったときの解決記録

序文Vue で要素を初回取得できない問題の解決方法は、ポップアップ ウィンドウで要素を取得するために...

JavaScript でドラッグ スライダー パズルの検証機能を実装します (html5、canvas)

導入:スライダー ドラッグ検証は現在、多くの場所で使用されています。週末に 1 つ作成しようと思い、...

よく使われる HTML 形式のタグ_Powernode Java Academy

1. タイトルHTML では、<h1></h1> から <h6>...