предисловие
Давно не писал статьи, немного изучил webpack, некоторые базовые компоненты, а сегодня привожу туториал по компоненту валидации формы (element.iviewui) (как новичок, после всего опыта многих проекты, могу дать несколько советов новичкам
Узнайте о плавании фитнес:
github技术文档Техническая документация будет постоянно обновляться
Краткое содержание
- Объяснение принципа
- отправка и передача // взаимодействие родитель-потомок
- Представляем async-validator // плагин проверки формы
- дизайн формы / и API
- form-item
- input
визуализация
1. Объяснение принципа
рассмотреть возможность
Давайте посмотрим, что мы можем использовать форму для запуска проверки в целом или один вход для запуска элемента формы для проверки. Детская обувь может все еще чувствовать, что она все еще не понимает, так что можно продолжать чтение.
2. Распространение и трансляция
Зачем использовать трансляцию и распространение? Обычно мы стараемся не использовать vuex и bus (event bus) для компонентов, не имеющих никакого отношения к делу.
Ниже присылаю код для вещания и рассылки. Привязываем компонент, который нужно вызватьthis.$on('event',res=>()), Посредством распределения и широковещательных вызовов$emit.
- Диспетчер ищет и звонит только 1
- Вещание смотрит вниз, чтобы вызвать несколько
- Примечание⚠️Все компоненты должны быть прописаны
name - миксером
mixinsиспользовать
emitter.js
/**
* 递归使用 call 方式this指向
* @param componentName // 需要找的组件的名称
* @param eventName // 事件名称
* @param params // 需要传递的参数
*/
function broadcast(componentName, eventName, params) {
// 循环子节点找到名称一样的子节点 否则 递归 当前子节点
this.$children.map(child=>{
if (componentName===child.$options.name) {
child.$emit.apply(child,[eventName].concat(params))
}else {
broadcast.apply(child,[componentName,eventName].concat(params))
}
})
}
export default {
methods: {
/**
* 派发 (向上查找) (一个)
* @param componentName // 需要找的组件的名称
* @param eventName // 事件名称
* @param params // 需要传递的参数
*/
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;//$parent 找到最近的父节点 $root 根节点
let name = parent.$options.name; // 获取当前组件实例的name
// 如果当前有节点 && 当前没名称 且 当前名称等于需要传进来的名称的时候就去查找当前的节点
// 循环出当前名称的一样的组件实例
while (parent && (!name||name!==componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
// 有节点表示当前找到了name一样的实例
if (parent) {
parent.$emit.apply(parent,[eventName].concat(params))
}
},
/**
* 广播 (向下查找) (广播多个)
* @param componentName // 需要找的组件的名称
* @param eventName // 事件名称
* @param params // 需要传递的参数
*/
broadcast(componentName, eventName, params) {
broadcast.call(this,componentName, eventName, params)
}
}
}
3.async-validator
не знаюasync-validatorВы можете перейти на официальный сайт, чтобы увидетьgithub
yarn add async-validator // 因为当前这个插件是需要打包到项目里的所以不能加-D
4. Дизайн API
Давайте посмотрим нижеelementИзображение официального сайта`
-
formЕсть 2 введенных поля:rulesправила и:modelЗначение текущей формы будет переданоmodelстоимость иrulesсовпадение для проверки. -
form-itemЕсть 2 введенных поляlableа такжеprop(prop) должен прийти иformсопоставьте, чтобы получить текущийform-itemзначение -
inputНа самом деле существуют текущие@inputМетоды.v-modelя не буду объяснять
form
- мы в
formСначала начните вводить все текущиеform-itemэкземпляр (получить) -
createdМетоды, которые связывают и удаляют текущий экземпляр в начале жизненного цикла. Обычно привязки вызываются перед запуском домена страницы и должны бытьdomЗавершена загрузка -
provideИспользуйте с inject, чтобы дочерние компоненты могли вызывать методы и данные текущего родительского компонента. - Замечания написаны ниже и их можно есть с уверенностью (можно проверить после тестирования)
form.vue
<template>
<form>
<slot></slot>
</form>
</template>
<script>
export default {
name: "aiForm",
provide(){ // [不懂的可以看看](https://cn.vuejs.org/v2/api/#provide-inject)
return {
form: this
}
},
props: {
// 当前 form 的model
model: {
type: Object
},
// 验证
rules: {
type: Object
}
},
data(){
return{
fields: [] // 储存当前的 form-item的实例
}
},
created(){
// 存当前实例
let that =this;
this.$on('on-form-item-add',item=>{
if (item) {
that.fields.push(item)
}
});
// 删除当前有的实例
this.$on('on-form-item-remove',item=>{
if (item.prop) {// 如果当前没有prop的话表示当前不要进行删除(因为没有注入)
that.fields.splice(that.fields.indexOf(item),1)
}
})
},
methods:{
/**
* 清空
*/
resetFields(){//添加resetFields方法使用的时候调用即可
/**
* 当前所有当form-item 进行赋值
*/
this.fields.forEach(field => {
field.resetField();
});
},
/**
* 校验 公开方法:全部校验数据,支持 Promise
*/
validate(callback){
return new Promise(resolve=>{
/**
* 当前所有当form-item 进行校验
*/
let valid = true; // 默认是通过
let count = 0; // 来匹配当前是否是全部检查完
this.fields.forEach(field => {
// 每个实例都会有 validation 的校验的方法
field.validation('',error=>{
// 只要有一个不符合那么当前的校验就是未通过的
if (error) {
valid = false;
}
// 通过当前检查完所有的form-item的时候才会调用
if (++count === this.fields.length) {
resolve(valid);// 方法使用then
if (typeof callback === 'function') {
callback(valid);// 直接调用注入的回调方法
}
}
});
});
})
}
}
}
</script>
5.form-item
-
form-itemЭто сложнее, давайте поговорим об этом по порядку -
isRequiredопределить, требуется ли это в настоящее время -
validateStateопределить текущий статус проверки -
validateMessageтекущее значение ошибки -
inject: ['form']мы можем пройтиthis.from.xxxдля вызова события и значения родительского компонента -
computedвнизfieldValueМожет постоянно меняться, поэтому мы используем вычисляемые свойства -
initialValueЗначение по умолчанию, которое мы имеем вmountedкогда и когда в настоящее время требуется проверка (propиногда) будет назначать -
mixins: [Emitter]Микшер — это метод внутри, а дата может часто использоваться в текущем вызове и может быть помещена в микшер. - нас
form-itemбудет передан вinputдва методаblurа такжеchange(ввод используется изначально@input)пройти черезformвходящая контрольная суммаrulesвнутриtriggerсудить
form-item.vue
<template>
<div>
<label :class="isRequired?'ai-form-item-label-required':''">{{label}}</label>
<div>
<slot></slot>
<div class="ai-form-item-message" v-if="validateState==='error'">{{validateMessage}}</div>
</div>
</div>
</template>
<script>
import Emitter from '../../mixins/emitter';
import schema from 'async-validator';
export default {
name: "aiFormItem",
mixins: [Emitter],
inject: ['form'],
props: {
label: {
type: String,
default: ''
},
prop:{
type: String
},
},
computed:{
fieldValue () {
return this.form.model[this.prop];
},
},
data(){
return {
initialValue: '', // 储存默认值
isRequired: false, // 当前的是否有问题
validateState: '', // 是否校验成功
validateMessage: '', // 校验失败文案
}
},
methods:{
/**
* 绑定事件 进行是否 required 校验
*/
setRules(){
let that = this;
let rules = this.getRules();//拿到父组件过滤后当前需要使用的规则
if (rules.length) {
// every 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)
// some 只要有一个符合就返回true
this.isRequired = rules.some(rule=>{
// 如果当前校验规则中有必填项,则标记出来
return rule.required;
})
}
/**
* blur 事件
*/
this.$on('on-form-blur',that.onFieldBlur);
/**
* change 事件
*/
this.$on('on-form-change',that.onFieldChange)
},
/**
* 从 Form 的 rules 属性中,获取当前 FormItem 的校验规则
*/
getRules () {
let that = this;
let rules = that.form.rules;
rules = rules?rules[that.prop]:[];
return [].concat(rules||[])//这种写法可以让规则肯定是一个数组的形式
},
/**
* Blur 进行表单验证
*/
onFieldBlur(){
this.validation('blur')
},
/**
* change 进行表单验证
*/
onFieldChange(){
this.validation('change')
},
/**
* 只支持 blur 和 change,所以过滤出符合要求的 rule 规则
*/
getFilteredRule (trigger) {
let rules = this.getRules();
// !res.trigger 没有调用方式的时候默认就校验的
// filter 过滤出当前需要的规则
return rules.filter(res=>!res.trigger || res.trigger.indexOf(trigger)!==-1)
},
/**
* 校验数据
* @param trigger 校验类型
* @param callback 回调函数
*/
validation(trigger,callback=function () {}){
// blur 和 change 是否有当前方式的规则
let rules = this.getFilteredRule(trigger);
// 判断当前是否有规则
if (!rules || rules.length === 0) {
return
}
// 设置状态为校验中
// async-validator的使用形式
this.validateState = 'validating';
var validator = new schema({[this.prop]: rules});
// firstFields: true 只会校验一个
validator.validate({[this.prop]: this.fieldValue}, { firstFields: true },(errors, fields) => {
this.validateState = !errors ? 'success' : 'error';
this.validateMessage = errors ? errors[0].message : '';
callback(this.validateMessage);
});
},
/**
* 清空当前的 form-item
*/
resetField(){
this.form.model[this.prop] = this.initialValue;
}
},
// 组件渲染时,将实例缓存在 Form 中
mounted(){
// 如果没有传入 prop,则无需校验,也就无需缓存
if (this.prop) {
this.dispatch('aiForm','on-form-item-add', this);
// 设置初始值,以便在重置时恢复默认值
this.initialValue = this.fieldValue;
// 添加表单校验
this.setRules()
}
},
// 组件销毁前,将实例从 Form 的缓存中移除
beforeDestroy(){
this.dispatch('iForm', 'on-form-item-remove', this);
},
}
</script>
<style scoped>
<!--当前css-->
.ai-form-item-label-required:before{
content: '*';
color: red;
}
.ai-form-item-message {
color: red;
}
</style>
5.input
-
valueподдержка одного входа - потому что в настоящее время
inputВведенные параметры не могут быть размещены напрямуюinputОн используется в нем, поэтому сначала назначаетсяdefaultValueзатем используйтеwatchприходи и уходиdefaultValueНазначение достигает привязки, измененной родительским компонентом
<template>
<input type="text"
@input="handleInput" // change
@blur="handleBlur"
:value="defaultValue"
>
</template>
<script>
import Emitter from '../../mixins/emitter.js'
export default {
name: "aiInput",
mixins: [Emitter],
props: {
value: {
type: String,
default: ''
}
},
data(){
return {
defaultValue: this.value
}
},
watch:{
value (val) {
this.defaultValue = val;
}
},
methods:{
/**
* change 事件
* @param event
*/
handleInput(event){
// 当前model 赋值
this.defaultValue = event.target.value;
// vue 原生的方法 return 出去
this.$emit('input',event.target.value);
// 将当前的值发送到 aiFormItem 进行校验
this.dispatch('aiFormItem','on-form-change',event.target.value)
},
/**
* blur 事件
* @param event
*/
handleBlur(event){
// vue 原生的方法 return 出去
this.$emit('blur',event.target.value);
// 将当前的值发送到 aiFormItem 进行校验
this.dispatch('aiFormItem','on-form-blur',event.target.value)
}
}
}
</script>
наконец
Наконец, дайте последний доступный метод использования
<template>
<div class="home">
<button @click="changeButton">测试</button>
<ai-form ref="formItems" :model="formValidate" :rules="ruleValidate">
<ai-form-item label="用户名" prop="name">
<ai-input v-model="formValidate.name"/>
</ai-form-item>
</ai-form>
</div>
</template>
<script>
import AiForm from "../components/form/form";
import AiFormItem from "../components/form/form-item";
import AiInput from "../components/input/ai-input";
export default {
name: 'home',
components: {AiInput, AiFormItem, AiForm},],
data(){
return{
formValidate: {
name: '123z',
mail: ''
},
ruleValidate: {
name: [
{ required: true, message: '用户名不能为空', trigger: 'blur' },
],
}
}
},
methods:{
changeButton(){
this.$refs.formItems.resetFields() // 清空方法
this.$refs.formItems.validate() // 验证方法
.then(res=>{
console.log(res)
})
}
},
}
</script>
резюме
Может быть, мои друзья до сих пор не понимают. . Как говорится, мастер ведет дверь, а практика в человеке. Замечаний по коду достаточно. Если вы все еще не понимаете, вы можете присоединиться к группе и спросить своих друзей,
Если вы ищете надежный внутренний толчок (район Пекина), вы можете оставить сообщение +. знак равно