ビジネスニーズ
シンプルな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)
})
}
穫れる





