Element-UI入门

矫情吗;* 2022-09-13 04:30 23阅读 0赞

基本用法

Element-UI 入门

  • 初始化项目并安装 ElementUI

    初始化项目

    vue create element-test

    切换目录运行

    cd element-test
    npm run serve

    安装element-ui

    npm i element-ui -S

  • 全局引入

    import ElementUI from ‘element-ui’
    import ‘element-ui/lib/theme-chalk/index.css’

    Vue.use(ElementUI)

  • 按需引入

    参考官网做法即可:按需引入

    项目打包

    npm run build

    查看dist js文件大小 1.1M左右

    ll dist/js

    -rw-r—r— 1 xxx 197609 118697 9月 27 11:10 chunk-vendors.123827f3.js

  • 插件引用

    vue add element

表单基本用法

  1. el-form 容器,通过 v-model 绑定数据
  2. el-form-item 容器,通过 label 绑定标签
  3. 表单组件通过 v-model 绑定 model 中的数据

表单校验用法

基础用法

  1. 定义校验规则

    data() {
    const userValidator = (rule, value, callback) => {

    1. if (value.length > 3) {
    2. callback()
    3. } else {
    4. callback(new Error('用户名长度必须大于3'))
    5. }

    }
    return {

    1. data: {
    2. user: 'sam',
    3. region: '区域二'
    4. },
    5. rules: {
    6. user: [
    7. { required: true, trigger: 'change', message: '用户名必须录入' },
    8. { validator: userValidator, trigger: 'change' }
    9. ]
    10. }

    }
    },
    methods: {
    onSubmit() {

    1. this.$refs.form.validate((isValid, errors) => {
    2. console.log(isValid, errors)
    3. })

    }
    }

  2. 指定 el-form-item 的 prop 属性(在使用 validate、resetFields 方法的情况下,该属性必填)


    1. <el-input v-model="data.user" placeholder="审批人" clearable></el-input>


动态添加校验规则

  • rulues 删除一个校验规则,现在只包含一个校验规则

    data() {
    return {

    1. data: {
    2. user: '',
    3. region: '',
    4. },
    5. rules: {
    6. user: [
    7. { required: true, trigger: 'change', message: '用户名必须录入' }
    8. ],
    9. },

    }
    },

  • 动态添加 rules

    表单中添加新的校验规则会立即进行校验,是因为这个属性 validate-on-rule-change 默认为 true,改为 false 即可 <el-form inline :model="data" :rules="rules" ref="form" validate-on-rule-change>

    addRule() {
    const userValidator = (rule, value, callback) => {

    1. if (value.length > 3) {
    2. /* this.inputError = '' this.inputValidateStatus = '' */
    3. callback()
    4. } else {
    5. callback(new Error('用户名长度必须大于3'))
    6. }

    }
    const newRule = […this.rules.user, { validator: userValidator, trigger: ‘change’ }]
    this.rules = Object.assign({ }, this.rules, { user: newRule })
    },

注意:新增新规则必须重新生成一个新的 rules 对象,因为 watch 只能监听 rules,而监听不到内部的变化

  • 使用 this.rules = Object.assign({}. this.rules, { user: newRule })
  • 不能使用 this.rules.user.push(newRule)

手动控制校验状态

  • validate-status:验证状态,枚举值,共四种:

    • success:验证成功
    • error:验证失败
    • validating:验证中
    • (空):未验证
  • error:自定义错误提示
  1. data 中新增 error 和 status 变量
  2. 设置 status-icon 属性

    1. <el-form inline :model="data" :rules="rules" ref="form" validate-on-rule-change="false" status-icon>
  3. 设置 el-form-item 属性

    1. <el-form-item label="审批人" prop="user" :error="error" :validate-status="status">
  4. 新增按钮

    1. <el-button type="success" @click="showSuccess">校验成功</el-button>
    2. <el-button type="danger" @click="showError">校验失败</el-button>
    3. <el-button type="warning" @click="showValidating">校验中</el-button>
  5. 在 methods 中定义 status 和 error 的方法

    1. showError() {
    2. this.status = 'error'
    3. this.error = '用户名输入有误'
    4. },
    5. showSuccess() {
    6. this.status = 'success'
    7. this.error = ''
    8. },
    9. showValidating() {
    10. this.status = 'validating'
    11. this.error = ''
    12. },

表单属性

  • label-position:标签位置 leftrighttop。如果设置为 leftright 则需要设置 label-width
  • label-width:标签宽度
  • label-suffix:标签后缀,一般会设置个冒号
  • inline:行内表单
  • disabled:设置整个 form 的表单组件全部 disabled,优先级低于表单组件自身的 disabled
  • status-icon:输入框右侧显示校验反馈图标
  • validate-on-rule-change:是否在 rules 属性改变后立即触发一次验证

disbabled

直接看 element-ui\packages\form\src\form.vue ,里面是没有对 disabled 进行处理,而是用 provide 将自身传递给了后代

  1. provide() {
  2. return {
  3. elForm: this
  4. };
  5. },

之后去看 element-ui\packages\input\src\input.vue ,找到 :disabled="inputDisabled" ,这里先判断自身是否有 disabled 属性,再判断祖先是否含有(自身的优先级高一些)。这里使用了 inject 去接收 elForm 和 elFormItem

  1. inject: {
  2. elForm: {
  3. default: ''
  4. },
  5. elFormItem: {
  6. default: ''
  7. }
  8. },
  9. computed: {
  10. inputDisabled() {
  11. return this.disabled || (this.elForm || { }).disabled;
  12. },
  13. }

size

先去看 element-ui\packages\input\src\input.vue ,找到 inputSize ? 'el-input--' + inputSize : '', ,会先找到 _elFormItemSize,之后会去找 elFormItem 里的 elFormItemSize

  1. computed: {
  2. _elFormItemSize() {
  3. return (this.elFormItem || { }).elFormItemSize;
  4. },
  5. inputSize() {
  6. return this.size || this._elFormItemSize || (this.$ELEMENT || { }).size;
  7. },
  8. }

之后去看 element-ui\packages\form\src\form-item.vue ,也是通过 provide 将自身传递给后代

  1. provide() {
  2. return {
  3. elFormItem: this
  4. };
  5. },

这里去找 elFormItemSize,最后发现它是直接找 this.elForm.size

  1. computed: {
  2. _formSize() {
  3. return this.elForm.size;
  4. },
  5. elFormItemSize() {
  6. return this.size || this._formSize;
  7. },
  8. }

ElementUI form 源码

入口

element-ui\src\index.js 是 ElementUI 的入口文件

  • Vue.use(Element) 调用 ElementUI 入口的 install 方法,会加载全部组件

    所有组件在存在 components 数组中

    const install = function(Vue, opts = { }) {
    components.forEach(component => {

    1. Vue.component(component.name, component);

    });
    // 全局引入时不需要写这些
    Vue.prototype.$loading = Loading.service;
    Vue.prototype.$msgbox = MessageBox;
    Vue.prototype.$alert = MessageBox.alert;
    Vue.prototype.$confirm = MessageBox.confirm;
    Vue.prototype.$prompt = MessageBox.prompt;
    Vue.prototype.$notify = Notification;
    Vue.prototype.$message = Message;
    };

按需加载相当于手动调用 Vue.component(xxx.name, xxx)

from.vue

el-form 中容器功能是通过插槽来实现的,自身属性只有两个 labelPositioninline,其余全部向下传递

  1. <template>
  2. <form class="el-form" :class="[ labelPosition ? 'el-form--label-' + labelPosition : '', { 'el-form--inline': inline } ]">
  3. <slot></slot>
  4. </form>
  5. </template>

watch 主要监听 rules 的变化,对 rules 进行变更会去判断 validateOnRuleChange 是否启用,启用则执行一次

  1. watch: {
  2. rules() {
  3. // remove then add event listeners on form-item after form rules change
  4. this.fields.forEach(field => {
  5. field.removeValidateEvents();
  6. field.addValidateEvents();
  7. });
  8. if (this.validateOnRuleChange) {
  9. this.validate(() => { });
  10. }
  11. }
  12. },
  • from validate 对整个表单进行验证

    validate(callback) {
    // 判断有没有表单数据
    if (!this.model) {

    1. console.warn('[Element Warn][Form]model is required for validate to work!');
    2. return;

    }

    let promise;
    // if no callback, return promise
    if (typeof callback !== ‘function’ && window.Promise) {

    1. promise = new window.Promise((resolve, reject) => {
    2. callback = function(valid) {
    3. valid ? resolve(valid) : reject(valid);
    4. };
    5. });

    }

    let valid = true;
    let count = 0;
    // 如果需要验证的fields为空,调用验证时立刻返回callback
    if (this.fields.length === 0 && callback) {

    1. callback(true);

    }
    let invalidFields = { };
    // 依次遍历所有field,一个一个验证
    this.fields.forEach(field => {

    1. // 执行form-item里的validate方法
    2. field.validate('', (message, field) => {
    3. if (message) {
    4. valid = false;
    5. }
    6. invalidFields = objectAssign({ }, invalidFields, field);
    7. // 如果有错误会调用callback
    8. if (typeof callback === 'function' && ++count === this.fields.length) {
    9. callback(valid, invalidFields);
    10. }
    11. });

    });

    if (promise) {

    1. return promise;

    }
    },

form-item.vue

  • is-no-asterisk -> hide-required-asterisk 是否隐藏必填字段的标签旁边的红色星号

当表单验证有误时,文字出现是有动画的,使用的是 Vue 的 transition 组件的动画

  • transition 组件里面有个 slot 插槽(具名插槽 name="error"),这里允许我们自己对错误提示文本的样式进行自定义修改

    $—md-fade-transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;

    .el-zoom-in-top-enter-active,
    .el-zoom-in-top-leave-active {
    opacity: 1;
    transform: scaleY(1);
    transition: $—md-fade-transition;
    transform-origin: center top;
    }
    .el-zoom-in-top-enter,
    .el-zoom-in-top-leave-active {
    opacity: 0;
    transform: scaleY(0);
    }

  • 之前自定义 error,它会立即展示出来效果(在 created 会执行一次)

    watch: {
    error: {

    1. immediate: true,
    2. handler(value) {
    3. this.validateMessage = value;
    4. this.validateState = value ? 'error' : '';
    5. }

    },
    validateStatus(value) {

    1. this.validateState = value;

    }
    },

  • from-item validate 对每一项进行验证

    validate(trigger, callback = noop) {
    this.validateDisabled = false;
    const rules = this.getFilteredRule(trigger);
    // 没有验证规则,直接返回true
    if ((!rules || rules.length === 0) && this.required === undefined) {

    1. callback();
    2. return true;

    }
    // 状态改为验证中
    this.validateState = ‘validating’;

    const descriptor = { };
    // 匹配async-validator第三方库需要的格式,做的处理
    if (rules && rules.length > 0) {

    1. rules.forEach(rule => {
    2. delete rule.trigger;
    3. });

    }
    descriptor[this.prop] = rules;

    // 对rulues进行验证,使用async-validator第三方库
    const validator = new AsyncValidator(descriptor);
    const model = { };
    // async-validator需要验证的数据
    model[this.prop] = this.fieldValue;
    // 验证
    validator.validate(model, { firstFields: true }, (errors, invalidFields) => {

    1. this.validateState = !errors ? 'success' : 'error';
    2. this.validateMessage = errors ? errors[0].message : '';
    3. // 执行回调
    4. callback(this.validateMessage, invalidFields);
    5. // form组件发布validate事件
    6. this.elForm && this.elForm.$emit('validate', this.prop, !errors, this.validateMessage || null);

    });
    },

async-validator

Element 表单校验主要使用了 async-validator 这个库

5767197542ee4357b6f953a57c63a6a7.png

这个插件基本流程如下:

  • 按照 rule 的规则生成 rules,并指定每个字段的规范
  • 根据 rules 生成验证器 const validator = new Validator(rules)
  • 对验证器进行验证 validator.validate(source, [options], callback)
  • 匹配 source 中的字段对应规则,全部通过或出错调用 callback

    import Validator from ‘async-validator’

    // 规则描述
    const rules = {
    name: { type: ‘string’, require: true },
    }
    // 根据规则生成验证器
    const validator = new Validator(rules)
    // 要验证的数据源
    const source = {
    name: ‘bird’,
    }
    // 验证后的回调函数
    function callBack(errors, fields) {
    if (errors) {

    1. // 验证不通过,errors是一个数组,记录那些不通过的错误信息
    2. // fields 是所有数据源的字段名,即source中的name

    }
    // 验证通过后的逻辑
    }
    // 验证数据源是否符合规则(如果验证时有一个不通过,终止验证下个规则[一个字段多个规则情况])
    validator.validate(source, { firstFields: true }, callBack)

Rules

  • 函数方式:{ name(rule, value, callback, sources, options) }
  • 对象方式:{ name: { type: 'string', required: true } }
  • 数组方式:{ name: [{ type: 'string' }, { required: true }] }

Rules 默认规则

  • type:要验证的数据类型

    • string:必须是 String 类型
    • number:必须是 Number 类型
    • boolean:必须是 Boolean 类型
    • method:必须是 Function 类型
    • regexp:必须是 RegExp 类型
    • array:必须是 Array.isArray 通过的数组
    • object:必须是 Array.isArray 不通过的类型的 Object 类型
    • date:必须是 Date 对象的实例
    • interger:必须是 Number 类型的正整数
    • float:必须是 Number 类型的浮点数
    • enum:预先定义 enum,值必须是 enum 某个值
    • url:必须符合链接格式
    • hex:必须是 16 进制
    • email:必须符合邮件格式
    • any:任意数据类型
  • required:是否必填
  • pattern:使用正则来验证 pattern: '[^ \x22]+'(前后空格不匹配)
  • min:数据长度的最小值(数据类型必须是 stringarray
  • max:数据长度的最大值(数据类型必须是 stringarray
  • len:数据长度必须等于这个值(数据类型必须是 stringarray
  • enum:数据的值必须等于这个枚举数组中的某个元素
  • transform:钩子函数,在开始验证之前对数据预先处理 transform(value) { return value.trim() }
  • message:报错提示信息,可以是字符串或标签 message: () => this.$t('name')(不过这种变化不是实时的,想要实时的需要放在 computed 里面)
  • validator:自定义验证函数以及报错信息 validator(rule, value, callback)
  • deep rules 深度验证处理 object 或 array 类型,使用 fieldsdefaultField

    1. const url = ['http://www.xx.com', 'http://www.xx.cn']
    2. const rules1 = {
    3. urls: {
    4. type: 'array',
    5. require: true,
    6. defaultField: { type: url },
    7. },
    8. }
    9. const obj = {
    10. name: 'bird',
    11. age: 12,
    12. addr: 'xxx',
    13. }
    14. const rules2 = {
    15. ids: {
    16. type: 'object',
    17. require: true,
    18. fields: {
    19. name: { type: 'string', require: true },
    20. age: { type: 'number', require: true, transform: Number },
    21. addr: { type: 'string', require: true },
    22. },
    23. },
    24. }

发表评论

表情:
评论列表 (有 0 条评论,23人围观)

还没有评论,来说两句吧...

相关阅读

    相关 ElementUI 分页

    一、概述 当我们向后台请求大量数据的时候,并要在页面展示出来,请求的数据可能上百条数据或者更多的时候,并不想在一个页面展示,这就需要使用分页功能来去完成了。 本次所使用

    相关 ElementUI 快速入门

    一、概述 Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库指南 了解设计指南,帮助产品设计人员搭建逻辑清晰、结构合理且高效易用的产