blog

elementUI-formの簡単な実装

ビジネスニーズのニーズ分析は、シンプルなスタイルと双方向バインディングとソースコード内のいくつかの基本的なイベントを達成するための知識ポイントをマスターする必要があります多くの無効、サイズ、clear...

Feb 27, 2020 · 4 min. read
シェア

ビジネスニーズ

シンプルなel-formインクルードを実装する:
 データ収集
 フォームの検証

需要分析

* フォームの実装
	データモデル、バリデーションルールを指定する
 グローバルバリデーション validate()
* form-itemを実装する
	label 
 プロパティのプロパティをチェックする
 検証ルール validate()
 エラーメッセージ
* フォーム入力の実装
	データバインディングVモデル
 スタイルアイコンなど

正しい知識の習得が必要

$attrs && $listeners
inheritAttrs
provide && inject

MyInputの実装

ソースコード内の基本的なイベントのいくつかの双方向バインディングとシンプルなスタイルの実装上の入力が無効になっている多くの、サイズ、clearableおよびその他の属性は、この時間の焦点ではありませんアップされません!

<!--
 * 
 * 
 * @LastEditors: lam-jl
 * @LastEditTime: 2020-08-01 20:33:30
 * @FilePath: @/components/form/MyInput.vue
--> 
<template>
 <div class="el-input">
 <input 
 class="el-input__inner" 
 :type="type" 
 :value="value" 
 v-bind="$attrs"		// 親コンポーネントのプロパティのうち、プレースホルダのようにpropsによってバインドされていないものを取得する。
 @input="handleInput"
 @focus="handleFocus"
 @blur="handleBlur"
 @change="handleChange">
 </div>
</template>
<script>
 export default {
 inheritAttrs: false,	// コンポーネントは、登録されていないpropを通常のHTML属性としてレンダリングしない。
 name: 'MyInput',
 componentName: 'MyInput',
 props: {
 type: {
 type: String,
 default: 'text'
 },
 value: {
 type: String,
 default: ''
 },
 },
 data() {
 return {
 focused: false,
 }
 },
 methods: {
 handleInput(e) {
 this.$emit('input', e.target.value)
 },
 handleFocus(event) {
 this.focused = true;
 this.$emit('focus', event);
 },
 handleBlur(event) {
 this.focused = false;
 this.$emit('blur', event);
 // これがバリデーションのトリガーとなることに注意しよう
 this.$parent.$emit('validate')
 },
 handleChange(event) {
 this.$emit('change', event.target.value);
 },
 },
 }
</script>

MyFormItem の実装

まず、ラベルとそのスタイルを実装します。 ここではラベルの長さをコントロールするためにlabelWidthを追加しました。

<template>
 <div class="el-form-item" >
 <label class="el-form-item__label" :style="labelStyle" v-if="label">
 <slot name="label">{{label}}</slot>
 </label>
 <div class="el-form-item__content" :style="contentStyle">
 <slot></slot>
 <div
 v-if="validateMessage"
 class="el-form-item__error">{{validateMessage}}</div>
 </div>
 </div>
</template>
		computed: {
 labelStyle() {
 const ret = {};
 const labelWidth = this.labelWidth;
 if (labelWidth) {
 ret.width = labelWidth;
 }
 return ret;
 },
 contentStyle() {
 const ret = {};
 const label = this.label;
 if (!label && !this.labelWidth) return ret;
 const labelWidth = this.labelWidth;
 if (labelWidth === 'auto') {
 if (this.labelWidth === 'auto') {
 ret.marginLeft = this.computedLabelWidth;
 } 
 } else {
 ret.marginLeft = labelWidth;
 }
 return ret;
 },
 },

次のステップでは、フォームのバリデーションを考えます。 ここでは、elementUIが使用するバリデーションライブラリasync-validatorを参照します。

import Validator from 'async-validator'

今回の問題は、フォームのルールがフォームに書かれていて、フォームアイテムに書かれていないことです。そのため、カプセル化のレイヤーがいくつあるのかわからないまま、親コンポーネントにあるチェックルールを取得するにはどうすればいいのでしょうか? 今回は、provide && injectの使用です。

// MyForm.vue provide() { return { MyForm: this } }, // MyFormItem.vue inject: ["MyForm"],

この時点で、フォームの値情報とチェックルールを取得できます。

// MyFormItem.vue
		mounted () {
 	// ここで、MyInputから送られてきたイベントを受け取り、チェックを行う。
 this.$on('validate', () => {
 this.validate()
 });
 },
 methods: {
 validate() {
 const rules = this.MyForm.rules[this.prop]
 const value = this.MyForm.model[this.prop]
 const validator = new Validator({
 [this.prop]: rules
 })
 ここでバリデータはPromiseを返し、フォームの最終的なグローバルバリデーションを手助けする。
 return validator.validate({
 [this.prop]: value
 }, errors => {
 if(errors) {
 this.validateMessage = errors[0].message
 } else {
 this.validateMessage = ''
 }
 })
 }
 },

さて、この時点で、フォーム送信を確認するための最後のステップを残すのみとなりました。

// index.vue login() { this.$refs.loginForm.validate(isValid => { if(isValid) { alert('ログイン成功') } else { alert('ログイン失敗') } }) } // MyForm.vue validate(cb) { var tasks = this.$children .filter(item => { // ここでは、小道具を含まないすべてのコンポーネントをフィルタリングする。 return item.prop }).map(item => { // Promiseを返した後のフォーム項目のバリデーションをすべて取得する return item.validate() }) Promise.all(tasks) .then(() => { cb(true) }) .catch(() => { cb(false) }) }

穫れる

Read next

Vueの初回レンダリングプロセス

2.レンダリングオプションがあるかどうかを判断し、レンダリングオプションがない場合は、テンプレートテンプレートは、レンダリング関数にコンパイルされたテンプレートから取り出され、DOMをレンダリングし、マウントメソッドを呼び出します。 _initメソッドでは、$マウントへの最後の呼び出しは、2つの$マウントの合計があり、最初のものは、エントリで定義されています-。で定義されています。

Feb 26, 2020 · 8 min read