浅谈vux之x-input使用以及源码解读


Posted in Javascript onNovember 04, 2018

前言

近期项目中使用的vux中的input,以及使用自定义校验规则和动态匹配错误提示,有时间记录下自己的使用经历和源码分析。希望大家多多指正,留言区发表自己宝贵的建议。 详解 列举官方文档中常用的几个属性的使用方法,代码如下

<group ref="group">
  <x-input v-model="name"
  class="vux-input__name"
  title="名字"
  placeholder="tell me your name"
  required
  :is-type="checkNameValid"
  @on-change="onValueChange">
  <div slot="label"
   class="name__icon">
   <icon type="success"></icon>
  </div>
  </x-input>
 </group>

官方文档有详细的解释, required 属性表示此选项为必填, is-type 可以绑定一个函数,作为校验,这个函数得返回一个对象。格式如下

checkValid(name) {
  return {
  valid: name === '三只萌新',
  msg: '你不是萌新'
  }
 }

valid可以设置为你的校验规则,需要返回一个布尔值,msg是错误的提示信息。

vux本身写好几种校验方式,如果使用 email,china-name,china-mobile 这几种方式直接绑定字符串即可。

solt插槽如slot="label"用于自定义title,源码如下

<slot name="label">
 <label class="weui-label"
  :class="labelClass"
  :style="{width: labelWidth || $parent.labelWidth || labelWidthComputed, textAlign: $parent.labelAlign, marginRight: $parent.labelMarginRight}"
  v-if="title"
  v-html="title"
  :for="`vux-x-input-${uuid}`"></label>
 <inline-desc v-if="inlineDesc">{{ inlineDesc }}</inline-desc>
 </slot>

分析:class="labelClass"动态绑定样式以对象的形式返回一个{[className]:Boolean}的格式的对象

labelClass() {
  return {
  'vux-cell-justify':
   this.$parent.labelAlign === 'justify' ||
   this.$parent.$parent.labelAlign === 'justify'
  }
 }

浅谈vux之x-input使用以及源码解读 

同样的方式查看他父级是否有labelAlign属性,vux-cell-justify类名对应的样式没有应用。

使用场景

场景1

假设在一个提交页面,当我们提交时判断输入框中的值是否是符合我们的要求,如果不符合,给出错误提示,如果符合提交后将输入框中的数据清空。

需求:

如果还有停留在本页面我们需要将上一次的数据全部清空

问题:

我们需要初始化值,但是会发现如果我们设置了required后校验还是会触发。如何让数据清空并且让校验也清空。

解决方法:

文档中写了reset可以重置输入框值,清除错误信息

使用方式:

在x-input外层的group标签上绑定ref来访问子组件。因此我们可以通过 this.$refs.group.$children获取到input组件集合并且可以使用组件中定义的reset方法

如果你的项目中已经安装了vux可以通过安装Search node_modules查找node_modules文件夹中vux安装包路径为 vux/src/components/x-input/index.vue 文件 reset方法源码如下:

reset(value = '') {
  this.dirty = false
  this.currentValue = value
  this.firstError = ''
  this.valid = true
 }

回到我们的业务逻辑中当我们点击提交按钮时代码如下

onSubmitClick() {
  if (!this.isInvalid) {
  this.$refs.group.$children.forEach(child => {
   child.reset()
  })
  } else {
  // 展示提示信息
  this.isShowToast = true
  }

本以为这样就可以清空数据了,没想到点击按钮时数据是清空了,但是还是有报错图标显示。

浅谈vux之x-input使用以及源码解读 

通过 vue-devtools可以看到

浅谈vux之x-input使用以及源码解读

valid的值为false查看vux源码查看涉及到valid代码如下

validate() {
 // ...省略与本次无关的校验方法
if (!this.currentValue && this.required) {
  this.valid = false
  this.errors.required = '必填哦'
  this.getError()
  return
  if (typeof this.isType === 'function') {
  /* 
   取出自定义函数中的校验结果 是一个Boolean
   checkNameValid(name) {
   return {
    valid: name === '三只萌新',
    msg: '你不是萌新'
   }
   }
  */
  const validStatus = this.isType(this.currentValue)
  this.valid = validStatus.valid
  if (!this.valid) {
  // 如果校验值无效将自定义校验的msg赋值给errors对象下的format
   this.errors.format = validStatus.msg
   this.forceShowError = true
   this.getError()
   return
  } else {
  // 如果校验值有效则将error对象下的format删除 
   delete this.errors.format
  }
  // 如果都符合将valid赋值为有效
  this.valid = true
 }
}

validate函数校验当前是否有值,是否为必填, 如果当前值的校验方式是函数,将校验结果赋值给valid 。如果valid是false则将自定义的msg统一存储在errors对象下, errors是用来存储不同类型的错误信息 。 然后执行getError函数

getError() {
  let key = Object.keys(this.errors)[0]
  this.firstError = this.errors[key]
  console.log('firstError' + this.firstError)
 }

Object.keys(this.errors)返回errors对象下的所有可枚举属性,并且取第一个作为键名,取出对于的值赋值给firstError ,firstError是提示框文字

<toast v-model="showErrorToast"
  type="text"
  width="auto"
  :time="600">{{ firstError }}</toast>

当点击错误图标判断是否有firstError,shouldToastError未传入值默认为true,点击时如果valide校验为错误时会触发getError函数将错误提示赋值给firstError,所以会将fistError对应的提示信息显示出来。而图标的显示与否与valid有关,其中一个条件是valid为false时才会显示。

<icon @click.native="onClickErrorIcon"
  class="vux-input-icon"
  type="warn"
  :title="!valid ? firstError : ''"
  v-show="showWarn"></icon>
  
 shouldToastError: {
  type: Boolean,
  default: true
 }
 showWarn() {
  return (
  !this.novalidate &&
  !this.equalWith &&
  !this.valid &&
  this.firstError &&
  (this.touched || this.forceShowError)
  )
 }
 onClickErrorIcon() {
  if (this.shouldToastError && this.firstError) {
  this.showErrorToast = true
  }
  this.$emit('on-click-error-icon', this.firstError)
 }

分析了上面的代码,为什么执行了reset方法后,校验报错还是在,原因是valid依然还是false,导致showWarn返回值是ture,而reset中方法中明明将valid设置为true了,为什么最后结果为false。

watch:{
  currentValue(newVal, oldVal) {
   if (newVal && this.equalWith) {
   if (newVal.length === this.equalWith.length) {
    this.hasLengthEqual = true
   }
   this.validateEqual()
   } else {
   this.validate()
   }
  }
}

因为监听了input绑定currentValue的值,当reset方法执行的时候this.currentValue = ' ' 触发了变动执行validate方法,导致再次给this.valid赋值false。

该如何解决这个问题,问题发生的原因是currentValue发生变化导致触发validate方法校验,所以我们只要当执行reset方法后不触发currentValue改变就可以不触发validate方法校验

方法一:

onSubmitClick() {
 this.$refs.group.$children.forEach(child => {
  // 这次reset是将currentValue全部置为""
  child.reset()
 })
 this.$nextTick(() => {
 // 当所以input的值都置为空后在此执行reset方法,这次前后currentValue没有发生变化不会触发validate校验所以valide为true不会导致图标出现
  this.$refs.group.$children.forEach(child => {
  child.reset()
  })
 })
}

方法二: 其实想做的就是在reset方法执行之前将currentValue置为空

created(){
 this.currentValue =
  this.value === undefined || this.value === null
  ? ''
  : this.mask ? this.maskValue(this.value) : this.value
},
props:{
 value: [String, Number]
},
watch:{
 value(val) {
  this.currentValue = val
 }
}

可以通过传入value来改变currentValue的值,将v-model="name"绑定值的方式改为:value="name"

onSubmitClick() {
 this.name = ''
 this.$nextTick(() => {
  this.$refs.group.$children.forEach(child => {
  child.reset()
  })
 })
}

场景2

当我们点击提交时,如果有校验选项不符合规则能提示相匹配的警告

data(){
 return {
  message: '还未填写信息'
 }
}

将message提示信息初始值设置为还未填写信息,当我们未进行填写信息的时候点击提交显示。然后使用on-change函数绑定校验规则,实时更新message对应的提示语,业务逻辑如下:

onValueChange() {
  // 多次使用赋值给变量
  const children = this.$refs.group.$children
  let statusList = []
  // 筛选出有值的,作为是否全部未填的判断依据 如果length小于1则还没填写任何内容
  statusList = children.filter(item => {
  return item.currentValue
  })
  if (statusList.length < 1) {
  this.message = '还未填写信息'
  return
  }
  // 找到第一个没有值的那一项,如果都有则返回undefined
  const firstInvalid = children.find(item => {
  return !item.valid
  })
  if (firstInvalid !== undefined) {
  this.message = `请填写正确的${firstInvalid.title}`
  }
  // 显示的将是否有效赋值给valid增加代码可读性
  this.valid = Boolean(firstInvalid)
 }

github:代码地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 节点操作 以及DOMDocument属性和方法
Dec 06 Javascript
基于Jquery的回车成tab焦点切换效果代码(Enter To Tab )
Nov 14 Javascript
初窥JQuery(二) 事件机制(1)
Nov 25 Javascript
基于jQuery的输入框无值自动显示指定数据的实现代码
Jan 24 Javascript
jQuery中remove()方法用法实例
Dec 25 Javascript
JS对字符串编码的几种方式使用指南
May 14 Javascript
浅谈js控制li标签排序问题 js调用php函数的方法
Oct 16 Javascript
jQuery 插件实现随机自由弹跳气泡样式
Jan 12 Javascript
Koa2微信公众号开发之本地开发调试环境搭建
May 16 Javascript
JavaScript检查数据中是否存在相同的元素(两种方法)
Oct 07 Javascript
微信小程序实现bindtap等事件传参
Apr 08 Javascript
vue-router定义元信息meta操作
Dec 07 Vue.js
小程序实现选择题选择效果
Nov 04 #Javascript
小程序实现单选多选功能
Nov 04 #Javascript
Vuex的基本概念、项目搭建以及入坑点
Nov 04 #Javascript
微信小程序实现登录注册tab切换效果
Dec 29 #Javascript
原生js实现淘宝放大镜效果
Oct 28 #Javascript
微信小程序如何获取手机验证码
Nov 04 #Javascript
微信小程序实现弹出层效果
May 26 #Javascript
You might like
Php获取金书网的书名的实现代码
2010/06/11 PHP
PHP学习笔记 用户注册模块用户类以及验证码类
2011/09/20 PHP
php中计算程序运行时间的类代码
2012/11/03 PHP
浅析PKI加密解密 OpenSSL
2013/07/01 PHP
div li的多行多列 无刷新分页示例代码
2013/10/16 PHP
PHP使用get_headers函数判断远程文件是否存在的方法
2014/11/28 PHP
php远程下载类分享
2016/04/13 PHP
PHP基于swoole多进程操作示例
2019/08/12 PHP
JavaScript的面向对象方法以及差别
2008/03/31 Javascript
javascript 获取所有id中包含某关键字的控件的实现代码
2010/11/25 Javascript
js修改原型的属性使用介绍
2014/01/26 Javascript
现代 JavaScript 开发编程风格Idiomatic.js指南中文版
2014/05/28 Javascript
简介AngularJS中$http服务的用法
2016/02/06 Javascript
每日十条JavaScript经验技巧(一)
2016/06/23 Javascript
Node.js的环境安装配置(使用nvm方式)
2016/10/11 Javascript
详解vue-router和vue-cli以及组件之间的传值
2017/07/04 Javascript
微信小程序判断用户是否需要再次授权获取个人信息
2019/07/18 Javascript
vue使用混入定义全局变量、函数、筛选器的实例代码
2019/07/29 Javascript
微信小程序webview组件交互,内联h5页面并网页实现微信支付实现解析
2019/08/16 Javascript
vue scroll滚动判断的实现(是否滚动到底部、滚动方向、滚动节流、获取滚动区域dom元素)
2020/06/11 Javascript
vue+element-ui表格封装tag标签使用插槽
2020/06/18 Javascript
使用typescript快速开发一个cli的实现示例
2020/12/09 Javascript
Python子类继承父类构造函数详解
2019/02/19 Python
pandas删除指定行详解
2019/04/04 Python
Python OrderedDict的使用案例解析
2019/10/25 Python
Python将列表中的元素转化为数字并排序的示例
2019/12/25 Python
Pandas DataFrame求差集的示例代码
2020/12/13 Python
python实现模拟器爬取抖音评论数据的示例代码
2021/01/06 Python
如何使用PHP session
2015/04/21 面试题
毕业生就业意向书
2014/04/01 职场文书
青年安全生产示范岗事迹材料
2014/05/04 职场文书
药品营销策划方案
2014/06/15 职场文书
幼儿园端午节活动方案
2014/08/25 职场文书
创先争优宣传标语
2014/10/08 职场文书
2014年青年教师工作总结
2014/12/17 职场文书
国庆放假通知怎么写
2015/07/30 职场文书