编程语言
首页 > 编程语言> > 【Vue项目 + 自写java后端】尚品汇(七)后台项目 ElementUI 表单验证 + 三级联动

【Vue项目 + 自写java后端】尚品汇(七)后台项目 ElementUI 表单验证 + 三级联动

作者:互联网

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'}
        ]
      }
在函数回调中进行表单验证
    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;
    }
}

标签:insert,Vue,java,自写,into,pid,values,result,categoryName
来源: https://www.cnblogs.com/tod4/p/16684746.html