ElementUI 表单验证

1 标准验证规则

Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可。

      <el-form :rules="rules" :model="tmForm">
<el-form-item prop="tmname" label="品牌名称" label-width="100px">
<el-input autocomplete="off" v-model="tmForm.tmname" style="width: 400px"></el-input>
</el-form-item> <el-form-item prop="logourl" label="品牌LOGO" label-width="100px">
<el-upload
class="upload-demo"
action="/api/admin/product/fileUpload"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="tmForm.logourl" :src="tmForm.logourl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过10MB</div>
</el-upload> </el-form-item>
</el-form>

这里出现输入正确也一直有提示的情况,原因是因为el-form表单中的model表单绑定对象使用的是v-model而不是:model

v-model:表示value属性

:model:表示子组件有个prop叫model

      // 表单验证规则
rules: {
tmname: [
{required: true, message: '请输入品牌名', trigger: 'blur'},
{min: 3, max: 5, message: '长度在3到5个字符', trigger: 'blur'}
],
logourl: [
{required: true, message: '请上传品牌LoGo'}
]
}
  • required:是否为必填项,true则会在form-item前出现红色*

  • message:验证失败时出现的提示信息

  • trigger: 验证的时机

    • blur:失去聚焦时验证

    • change:改动时验证

在函数回调中进行表单验证
    addOrUpdateTradeMark() {
this.$refs.ruleForm.validate(async (valid) => {
if (valid) {
await this.$API.tradeMark.reqAddOrUpdateTradeMark(this.tmForm)
this.$message({
message: this.tmForm.id ? `品牌 ${this.tmForm.tmname} 修改成功` : `品牌 ${this.tmForm.tmname} 添加成功`,
type: 'success'
})
this.hiddenDialogForm()
await this.getPageList(this.page)
} else {
return false;
}
});
}

注意async 和 await的位置,应该放在最近的箭头函数处

自定义验证规则

  data() {
var checkTmname = (rule, value, callback) => {
if(value.length >= 2 && value.length <= 5) {
callback()
} else {
callback(new Error('品牌名称应在2-5位字符'))
}
}
return {
...
// 表单验证规则
rules: {
tmname: [
{required: true, message: '请输入品牌名称', trigger: 'blur'},
// {min: 2, max: 5, message: '长度在 2 到 5 个字符', trigger: 'blur'}
{validator: checkTmname, trigger: 'blur'}
],
logourl: [
{required: true, message: '请上传品牌LOGO'}
]
}
}
},

前端

1 静态组件

1.1 注册三级联动全局组件

/src/main.js

import CategorySelect from "@/components/CategorySelect";
Vue.component(CategorySelect.name, CategorySelect)

三级联动组件 /src/components/CategorySelect/index.vue

<template>
<div>
<el-form :inline="true" class="demo-form-inline">
<el-form-item label="一级分类">
<el-select placeholder="请选择">
<el-option label="区域一" value=""></el-option>
<el-option label="区域二" value=""></el-option>
</el-select>
</el-form-item> <el-form-item label="二级分类">
<el-select placeholder="请选择">
<el-option label="区域一" value=""></el-option>
<el-option label="区域二" value=""></el-option>
</el-select>
</el-form-item> <el-form-item label="三级分类">
<el-select placeholder="请选择">
<el-option label="区域一" value=""></el-option>
<el-option label="区域二" value=""></el-option>
</el-select>
</el-form-item> <el-form-item>
<el-button type="primary" @click="">查询</el-button>
</el-form-item>
</el-form> </div>
</template> <script>
export default {
name: "CategorySelect"
}
</script> <style scoped> </style>

在/src/views/product/attr中引入全局组件

<template>
<div>
<el-card style="margin-bottom: 20px"> <category-select/> </el-card>
<el-card style="margin-top: 20px"> </el-card>
</div>
</template> <script>
export default {
name: "index"
}
</script> <style scoped> </style>

2 编写请求接口

/src/api/product/attr.js

import request from "@/utils/request";

export const reqCategoryInfo = (id) => {
return request({
url: `/admin/product/attrInfoList/${id}`,
method: 'get'
})
}

CategorySelect组件加载完成时获取一级分类的属性信息

/src/components/CategorySelect/index.vue

  mounted() {
this.getCategoryInfo()
},
methods: {
async getCategoryInfo() {
let result = await this.$API.attr.reqCategoryInfo(-1)
if (result.code === 200) {
this.list1 = result.data
}
},

-1代表没有父组件,即一级分类

使用el-select生成三级分类选项

    <el-form :inline="true" class="demo-form-inline" :model="categoryForm">
<el-form-item label="一级分类">
<el-select placeholder="请选择"
@change="list1Handle()"
v-model="categoryForm.category1Id">
<el-option :label="c1.categoryName"
:value="c1.id"
v-for="(c1, index) in list1"
:key="c1.id"
></el-option>
</el-select>
</el-form-item> <el-form-item label="二级分类">
<el-select placeholder="请选择"
@change="list2Handle()"
v-model="categoryForm.category2Id">
<el-option :label="c2.categoryName"
:value="c2.id"
v-for="(c2, index) in list2"
:key="c2.id"
></el-option>
</el-select>
</el-form-item> <el-form-item label="三级分类">
<el-select placeholder="请选择" v-model="categoryForm.category3Id">
<el-option :label="list3 ? c3.categoryName : ''"
:value="c3.id"
v-for="(c3, index) in list3"
:key="c3.id"
></el-option>
</el-select>
</el-form-item> <el-form-item>
<el-button type="primary" @click="">查询</el-button>
</el-form-item>
</el-form>

-model:表单双向绑定的数据对象

:model:双向绑定的数据对象的

@change: 选项发生改变时触发函数

:value='':该项会与上面:model的值进行双向绑定

:key:循环的区别值,不能够省略,否则会出现意想不到的错误,估计是ElementUI提供的组件内部使用了

绑定的函数:

<script>
export default {
name: "CategorySelect",
data() {
return {
list1: [],
list2: [],
list3: [],
categoryForm: {
category1Id: "",
category2Id: "",
category3Id: "",
}
}
},
mounted() {
this.getCategoryInfo()
},
methods: {
async getCategoryInfo() {
let result = await this.$API.attr.reqCategoryInfo(-1)
if (result.code === 200) {
this.list1 = result.data
}
},
async list1Handle() {
this.categoryForm.category2Id = ''
this.categoryForm.category3Id = ''
const {category1Id} = this.categoryForm
let result = await this.$API.attr.reqCategoryInfo(category1Id)
if (result.code === 200) {
this.list2 = result.data
}
},
async list2Handle() {
this.categoryForm.category3Id = ''
const {category2Id} = this.categoryForm
let result = await this.$API.attr.reqCategoryInfo(category2Id)
if (result.code === 200) {
this.list3 = result.data
}
}
}
}
</script>

需要注意的一个点是在一级分类的value改变的时候应该将二三级分类的categoryform.categoryxid置空,否则会出现一个很严重的bug

比如二级分类选定电子书刊,三级分类选择一个电子书,如果这时候没有置空而将二级分类变为其他的选项的话,三级分类的label默认仍为电子书刊的电子书,这是由于二级分类双向绑定的对象的值是上一次残留的结果

后端

这部分后端相对来说简单一些,首先用xpath爬取了一点点数据,放入数据库后利用mybatis逆向工程生成entity、xml以及mapper接口。

insert into t_categoryName(pid, categoryName) values(-1, '图书、音像、电子书刊');
insert into t_categoryName(pid, categoryName) values(-1, '手机')
insert into t_categoryName(pid, categoryName) values(-1, '家用电器');
insert into t_categoryName(pid, categoryName) values(-1, '数码');
insert into t_categoryName(pid, categoryName) values(-1, '家居家装');
insert into t_categoryName(pid, categoryName) values(-1, '电脑办公');
insert into t_categoryName(pid, categoryName) values(-1, '厨具');
insert into t_categoryName(pid, categoryName) values(-1, '个护化妆');
insert into t_categoryName(pid, categoryName) values(-1, '服饰内衣');
insert into t_categoryName(pid, categoryName) values(-1, '钟表');
insert into t_categoryName(pid, categoryName) values(-1, '鞋靴');
insert into t_categoryName(pid, categoryName) values(-1, '母婴');
insert into t_categoryName(pid, categoryName) values(-1, '礼品箱包');
insert into t_categoryName(pid, categoryName) values(-1, '礼品箱包');
insert into t_categoryName(pid, categoryName) values(-1, '食品饮料、保健食品');
insert into t_categoryName(pid, categoryName) values(-1, '珠宝');
insert into t_categoryName(pid, categoryName) values(-1, '运动健康') insert into t_categoryName(pid, categoryName) values(1, '5');
insert into t_categoryName(pid, categoryName) values(1, '电子书刊');
insert into t_categoryName(pid, categoryName) values(1, '音像');
insert into t_categoryName(pid, categoryName) values(1, '英文原版');
insert into t_categoryName(pid, categoryName) values(1, '文艺');
insert into t_categoryName(pid, categoryName) values(1, '少儿');
insert into t_categoryName(pid, categoryName) values(1, '人文社科');
insert into t_categoryName(pid, categoryName) values(1, '经管励志');
insert into t_categoryName(pid, categoryName) values(1, '生活');
insert into t_categoryName(pid, categoryName) values(1, '科技');
insert into t_categoryName(pid, categoryName) values(1, '教育');
insert into t_categoryName(pid, categoryName) values(1, '港台图书');
insert into t_categoryName(pid, categoryName) values(1, '其他'); insert into t_categoryName(pid, categoryName) values(19, '电子书');
insert into t_categoryName(pid, categoryName) values(19, '网络原创')
insert into t_categoryName(pid, categoryName) values(19, '数字杂志');
insert into t_categoryName(pid, categoryName) values(19, '多媒体图书');
insert into t_categoryName(pid, categoryName) values(19, '小说');
insert into t_categoryName(pid, categoryName) values(19, '杂志'); insert into t_categoryName(pid, categoryName) values(20, '音乐');
insert into t_categoryName(pid, categoryName) values(20, '影视教育');
insert into t_categoryName(pid, categoryName) values(20, '音像');

记录逆向工程的一个坑点,如果数据库字段默认不使用下划线方式的话,转换成的实体类的字段全是小写的,而使用之后会将下划线变为驼峰。但是这个记得好像是能在配置文件设置的,懒得查了。。

如:category_name -> categoryName

CategoryHandler.java

@RequestMapping("/admin/product/attrInfoList")
@RestController
public class CategoryHandler {
@Autowired
CategoryService categoryService; @RequestMapping(value = "/{categoryId}", method = RequestMethod.GET)
public ResultEntity<Object> getAttrInfoList(@PathVariable("categoryId") Integer pid) {
List<Category> cateGoryList = categoryService.getCateGoryByPid(pid); return ResultEntity.successWithData(cateGoryList);
}
}

CategoryServiceImpl.java

@Service
public class CategoryServiceImpl implements CategoryService {
@Autowired
private CategoryMapper categoryMapper;
@Override
public List<Category> getCateGoryByPid(int pid) {
CategoryExample categoryExample = new CategoryExample();
categoryExample.createCriteria().andPidEqualTo(pid);
List<Category> categories = categoryMapper.selectByExample(categoryExample); return categories;
}
}

【Vue项目 + 自写java后端】尚品汇(七)后台项目 ElementUI 表单验证 + 三级联动的更多相关文章

  1. vue大型电商项目尚品汇(后台篇)day01

    开始我们后台篇的内容,前面处理了一些事情,去学校完成授位仪式,由校长授位合影,青春不留遗憾,然后还换了一个电脑,征战了四年的神船终于退役了,各种各样的小毛病是真的烦人. 现在正式开始后台篇的内容,做了 ...

  2. vue大型电商项目尚品汇(后台篇)day02

    这几天更新有点小慢,逐渐开始回归状态了.尽快把这个后台做完,要开始vue3了 3.添加修改品牌 用到组件 Dialog 对话框,其中visible.sync这个配置是修改他的显示隐藏的,label-w ...

  3. vue大型电商项目尚品汇(后台篇)day03

    今天把平台属性的管理基本完成了,后台管理做到现在基本也开始熟悉,确实就是对ElementUI的一个熟练程度. 一.平台属性管理 1.动态展示数据 先把接口弄好,应该在第三级标题选择后进行发请求 静态页 ...

  4. vue大型电商项目尚品汇(后台篇)day05

    今天继续是对后台管理部分的一个操作,但是快要结束了,今天结束,明天会进入一个从Vue以来,另外一个名声显著的东西了,一只耳闻从未见识,而且十分的炫酷 他就是------数据可视化Echarts,迫不及 ...

  5. vue大型电商项目尚品汇(后台篇)day04

    昨天太晚就没来得及更新,今天是spu管理界面,这个界面一共有三个界面需要切换,完成了两个界面,而且今天的难度在于最后两个章节,富有一定的逻辑性,当然中间也有很多需要注意的,比如ElementUI的照片 ...

  6. vue大型电商项目尚品汇(后台终结篇)day06 重磅!!!

    自此整个项目前后台,全部搭建完毕. 今天是最后一天,内容很多,而且也比较常用,一个图标类数据可视化,一个后台的权限管理,都是很经典的类型. 一.数据可视化 1.简介 专门的一门学科,有专门研究这个的岗 ...

  7. vue大型电商项目尚品汇(前台篇)day05

    紧急更新第二弹,然后就剩下最后一弹,也就是整个前台的项目 一.购物车 1.加入购物车(新知识点) 加入到购物车是需要接口操作的,因为我们需要将用户的加入到购物车的保存到服务器数据库,你的账号后面才会在 ...

  8. vue大型电商项目尚品汇(前台篇)day05终结篇

    前台部分到此结束,一路走来还挺怀念,今天主要是对整个项目的完成做一个最后的收尾工作,对于功能上的需求没有什么了,主要就是项目上线的一些注意事项. 一.个人中心二级路由 当我们点击查看订单应该跳转到个人 ...

  9. Vue项目之实现登录功能的表单验证!

    Vue项目之实现登录功能的表单验证! 步骤: 配置 Form表单验证; 1.必须给el-from组件绑定model 为表单数据对象 2 给需要验证的表单项 el-form-item 绑定 prop 属 ...

  10. 写一个简单易用可扩展vue表单验证插件(vue-validate-easy)

    写一个vue表单验证插件(vue-validate-easy) 需求 目标:简单易用可扩展 如何简单 开发者要做的 写了一个表单,指定一个name,指定其验证规则. 调用提交表单方法,可以获取验证成功 ...

随机推荐

  1. 弹框tabel

    <el-dialog title="删除数据类型" :visible.sync="isDataType" width="60%" :b ...

  2. InnoDB和MyISAM的区别(超详细)

    1.事务 InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务: ...

  3. renren-fast-vue人人开源前端项目搭建保姆级教程

    1.从gitee上clone项目 git clone https://gitee.com/renrenio/renren-fast-vue.git 2.准备好python环境 需要有Python2以上 ...

  4. Android studio SDK配置

    因为两个月前装过一次Android studio,所以完全按教程走不通. 已有Android studio的情况下,先在configue下配置SDK的位置,这里可能会报一个错,platforms不存在 ...

  5. scroll-view 横向滚动无效

    scroll-view的内层view元素需要: display: inline-block scroll-view的外层元素需要: white-space: nowrap 使得内部组件不换行.

  6. axel多线程下载

    Axel 是一个轻量级下载程序,它和其他加速器一样,对同一个文件建立多个连接,每个连接下载单独的文件片段以更快地完成下载. Axel 通过打开多个 HTTP/FTP 连接来将一个文件进行分段下载,从而 ...

  7. C语言转义序列

    转义序列 含义 \a 报警(ANSIC) \b 退格 \f 换页 \n 换行 \r 回车 \t 水平制表符 \v 垂直制表符 \\ 反斜杆\ \' 单引号 \" 双引号 \? 问号 \0oo ...

  8. [Python]Running multiprocessing

    import multiprocessing as mp import time def name_and_time(name,num): print(f"Hello {name}, cur ...

  9. 如何优化if--else

    1.现状代码 public interface IPay { void pay(); } package com.test.zyj.note.service.impl; import com.test ...

  10. 分布式CAP_BASE博客参考

    https://blog.csdn.net/lixinkuan328/article/details/95535691 CAP 一致性(Consistency) 可用性(Availability) 分 ...