- 1. 项目中安装并引用
element-ui - 2. 解决一个页面多个
Upload组件,出现 “上传成功之后无法判断是哪个组件” 的问题 - 3. form 表单验证规则
- 3. 使用
vue-cli3.x时,引用element-ui的css文件报错 - 4. 使用分页
el-pagination时,如果没加:total属性的话,即使用了pager这个list也显示不出来 - 5. 使用
v-loading时,需要给其父级增加相对定位position: relative - 6. 使用
dropdown、dropdown-menu、dropdown-item实现点击下拉子菜单更改数据的需求 - 7. 当使用
v-if v-else进行两个el-table数据判断,数据切换时会报错 - 8. 当使用
pug模板进行布局时,table的排序sortable功能无法使用 - 9. 引用
element-ui中的Tree组件时,在IE浏览器中会报错 - 10.
el-table->el-table-column的render-header属性使用示例 - 11.
el-cascader,封装一个公用的组件 - 12.
Uncaught ReferenceError: _MessageBox is not defined浏览器控制台报错,错误导致应用无法正常显示 - 13.
el-form-item自动验证的Bug - 14.
el-select绑定值为对象时使用value-key的示例 - 15.
el-cascader在内部的tags单个标签删除时,getCheckedNodes还是可以正常获取到删除之前的所有节点,导致处理数据时出现 bug - 16.
el-table自定义表头列表中某个单元格的样式 - 17.
el-table多列合并单元格,可以指定某列 - 18.
el-table多列排序
element-ui 中文官网
element-ui 官网组件使用指南
1. 项目中安装并引用 element-ui
安装
npm i element-ui -S
项目中
main.js文件中引用import Vue from 'vue'import ElementUI from 'element-ui'import 'element-ui/lib/theme-chalk/index.css'Vue.use(ElementUI)/* eslint-disable no-new */new Vue({el: '#app',render: h => h(App)})

2. 解决一个页面多个 Upload 组件,出现 “上传成功之后无法判断是哪个组件” 的问题
源码和相应部分页面截图,当前页面有三个上传组件

解决思路:
给【选取文件】这个按钮绑了个点击事件 ,多用了个变量
uploadSign做标记 成功的时候判断标记uploadSign相应的值就好了实现的源码
<template><div><el-form><el-form-item label="身份证正面"><el-row :gutter="30"><el-col :span="8"><div class="grid-content"><el-uploadclass="upload-demo"ref="frontPic"accept="image/png, image/jpeg"name="imgPath":action="imgUploadAPI":before-upload="beforeAvatarUpload":on-success="handleSuccess":limit="1":on-exceed="handleExceed"list-type="picture"><el-button size="small" type="primary" @click="uploadSign=1">选取文件</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件</div></el-upload></div></el-col><el-col :span="8"><div class="grid-content"><img class="show-img" src="@/assets/img/frontPic.png" alt="样图" /></div></el-col></el-row></el-form-item><el-form-item label="身份证背面"><el-row :gutter="30"><el-col :span="8"><div class="grid-content"><el-uploadclass="upload-demo"ref="reversePic"accept="image/png, image/jpeg"name="imgPath":action="imgUploadAPI":before-upload="beforeAvatarUpload":on-success="handleSuccess":limit="1":on-exceed="handleExceed"list-type="picture"><el-button size="small" type="primary" @click="uploadSign=2">选取文件</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件</div></el-upload></div></el-col><el-col :span="8"><div class="grid-content"><img class="show-img" src="@/assets/img/reversePic.png" alt="样图" /></div></el-col></el-row></el-form-item><el-form-item label="身份证SIM卡手持"><el-row :gutter="30"><el-col :span="8"><div class="grid-content"><el-uploadclass="upload-demo"ref="handPic"accept="image/png, image/jpeg"name="imgPath":action="imgUploadAPI":before-upload="beforeAvatarUpload":on-success="handleSuccess":limit="1":on-exceed="handleExceed"list-type="picture"><el-button size="small" type="primary" @click="uploadSign=3">选取文件</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件</div></el-upload></div></el-col><el-col :span="8"><div class="grid-content"><img class="show-img" src="@/assets/img/handPic.png" alt="样图" /></div></el-col></el-row></el-form-item></el-form></div></template><script>import qs from 'qs' // 解决 axios 数据提交格式与后台不一致的问题 -> name=hehe&age=10import { Loading } from 'element-ui'export default {name: 'App',data() {return {// 多个上传组件标记 1 身份证正面;2 身份证背面;3 省份证SIM卡手持uploadSign: null,// 图片上传接口imgUploadAPI: '/jjhServerApi/ab/imgPath',// 信息提交接口postAPI: '/jjhServerApi/ab/insertposn',// 信息提交数据postData: {/*** name 姓名* department 部门* phoneNumber 手机号码* position 职位* certCode 证件号 身份证号* companyId 公司Id* frontPic 身份证正面* reversePic 身份证反面* handPic 手持身份证* lastOperation 该记录最后操作 A:添加操作,D:设置为离职操作*/name: '',phoneNumber: '',department: '',position: '',certCode: '',companyId: '1', // 先写一个假数据frontPic: '',reversePic: '',handPic: '',lastOperation: 'A'}},methods: {// 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。// 判断上传文件类型beforeAvatarUpload: function(file) {const me = thisconst isJPG = file.type === 'image/jpeg'const isPNG = file.type === 'image/png'if (!(isJPG || isPNG)) {me.$message.error('上传的文件只能是 JPG 或者是 PNG 格式的')}},// 文件超出个数限制时的钩子handleExceed(file, fileList) {const me = thisme.$message.warning('只能上传一个文件')},// 文件上传成功时的钩子handleSuccess(res, file) {const me = thisconst sign = me.uploadSign// 判断 code 是否为 0 0 代表成功if (res.code === 0) {// 通过 sign 判断给相应的字段赋值if (sign === 1) {// 正面me.postData.frontPic = JSON.parse(res.result).url} else if (sign === 2) {// 背面me.postData.reversePic = JSON.parse(res.result).url} else if (sign === 3) {// 手持me.postData.handPic = JSON.parse(res.result).url}} else {// 失败回调me.$message.error(`${res.info}`)// 通过 sign 判断清空相应的列表 因为默认会显示出图片其实是失败了,容易造成用户误解if (sign === 1) {// 正面me.$refs.frontPic.clearFiles()} else if (sign === 2) {// 背面me.$refs.reversePic.clearFiles()} else if (sign === 3) {// 手持me.$refs.handPic.clearFiles()}}// 清空标记me.uploadSign = null}}}</script>
效果 gif 图

3. form 表单验证规则
效果 gif 图

直接上源码了,除了正则表达式大多都是官网示例的东西,还有就是
upload上传插件是我手写的规则验证的;
因为upload上传成功后的删除图标是后面生成的,且:on-remove给的方法如果自定义参数的话,就不能正常使用了,所以使用了三个不同的方法来定义删除成功后的钩子<template><div class="container"><el-form ref="dataForm" :model="postData" :rules="rules" label-width="180px"><el-form-item label="员工姓名" prop="name"><el-input v-model="postData.name" type="text" placeholder="请输入员工姓名" autofocus=""></el-input></el-form-item><el-form-item label="手机号码" prop="phoneNumber"><el-input v-model="postData.phoneNumber" type="text" placeholder="请输入手机号码"></el-input></el-form-item><el-form-item label="部门" prop="department"><el-select v-model="postData.department" placeholder="请选择部门"><el-option label="管理层" value="管理层"></el-option><el-option label="研发部" value="研发部"></el-option><el-option label="市场部" value="市场部"></el-option><el-option label="行政部" value="行政部"></el-option></el-select></el-form-item><el-form-item label="职位" prop="position"><el-input v-model="postData.position" type="text" placeholder="请输入职位"></el-input></el-form-item><el-form-item label="身份证号" prop="certCode"><el-input v-model="postData.certCode" type="text" placeholder="请输入身份证号"></el-input></el-form-item><el-form-item label="身份证正面"><el-row :gutter="30"><el-col :span="11"><div class="grid-content"><el-uploadclass="upload-demo"ref="frontPic"accept="image/png, image/jpeg"name="imgPath":action="imgUploadAPI":before-upload="beforeAvatarUpload":on-success="handleSuccess":before-remove="beforeRemove":on-remove="handleRemoveFront":limit="1":on-exceed="handleExceed"list-type="picture"><el-button size="small" type="primary" @click="uploadSign=1">选取文件</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件</div></el-upload></div></el-col><el-col :span="12"><div class="grid-content"><img class="show-img" src="@/assets/img/frontPic.png" alt="样图" /></div></el-col></el-row></el-form-item><el-form-item label="身份证背面"><el-row :gutter="30"><el-col :span="11"><div class="grid-content"><el-uploadclass="upload-demo"ref="reversePic"accept="image/png, image/jpeg"name="imgPath":action="imgUploadAPI":before-upload="beforeAvatarUpload":on-success="handleSuccess":before-remove="beforeRemove":on-remove="handleRemoveReverse":limit="1":on-exceed="handleExceed"list-type="picture"><el-button size="small" type="primary" @click="uploadSign=2">选取文件</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件</div></el-upload></div></el-col><el-col :span="12"><div class="grid-content"><img class="show-img" src="@/assets/img/reversePic.png" alt="样图" /></div></el-col></el-row></el-form-item><el-form-item label="身份证SIM卡手持"><el-row :gutter="30"><el-col :span="11"><div class="grid-content"><el-uploadclass="upload-demo"ref="handPic"accept="image/png, image/jpeg"name="imgPath":action="imgUploadAPI":before-upload="beforeAvatarUpload":on-success="handleSuccess":before-remove="beforeRemove":on-remove="handleRemoveHand":limit="1":on-exceed="handleExceed"list-type="picture"><el-button size="small" type="primary" @click="uploadSign=3">选取文件</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件</div></el-upload></div></el-col><el-col :span="12"><div class="grid-content"><img class="show-img" src="@/assets/img/handPic.png" alt="样图" /></div></el-col></el-row></el-form-item><el-form-item><el-button type="primary" @click="submitForm('dataForm')">立即提交</el-button><el-button @click="resetForm('dataForm')">重置</el-button></el-form-item></el-form></div></template><script>import qs from 'qs' // 解决 axios 数据提交格式与后台不一致的问题 -> name=hehe&age=10import { Loading } from 'element-ui'export default {name: 'App',data() {return {// 多个上传组件标记 1 身份证正面;2 身份证背面;3 省份证SIM卡手持uploadSign: null,// 图片上传接口imgUploadAPI: '/jjhServerApi/ab/imgPath',// 信息提交接口postAPI: '/jjhServerApi/ab/insertposn',// 信息提交数据postData: {/*** name 姓名* department 部门* phoneNumber 手机号码* position 职位* certCode 证件号 身份证号* companyId 公司Id* frontPic 身份证正面* reversePic 身份证反面* handPic 手持身份证* lastOperation 该记录最后操作 A:添加操作,D:设置为离职操作*/name: '',phoneNumber: '',department: '',position: '',certCode: '',companyId: '1', // 先写一个假数据frontPic: '',reversePic: '',handPic: '',lastOperation: 'A'},// 表单定义验证规则 trigger 为触发条件 http://element-cn.eleme.io/#/zh-CN/component/form#biao-dan-yan-zheng 官网地址rules: {// 姓名name: [{ required: true, message: '请输入员工姓名', trigger: 'blur' }],// 手机号码phoneNumber: [{ required: true, message: '请输入手机号码', trigger: 'blur' },{validator: function(rule, value, callback) {var MobileRegex = /^(13[0-9]|147|15[0-9]|17[0-9]|18[0-9])\d{8}$/if (!MobileRegex.test(value)) {callback(new Error('手机号码格式不正确!'))} else {callback()}},trigger: 'blur'}],// 选择部门department: [{required: true,message: '请选择您的部门',trigger: 'change'}],// 职位position: [{ required: true, message: '请输入职位', trigger: 'blur' }],// 身份证号certCode: [{ required: true, message: '请输入身份证号', trigger: 'blur' },{validator: function(rule, value, callback) {var MobileRegex = /(^\d{18}$)|(^\d{17}(\d|X|x)$)/if (!MobileRegex.test(value)) {callback(new Error('身份证号格式不正确!'))} else {callback()}},trigger: 'blur'}]}}},methods: {// 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。beforeAvatarUpload: function(file) {// 判断上传文件类型const me = thisconst isJPG = file.type === 'image/jpeg'const isPNG = file.type === 'image/png'if (!(isJPG || isPNG)) {me.$message.error('上传的文件只能是 JPG 或者是 PNG 格式的')}},// 文件超出个数限制时的钩子handleExceed(file, fileList) {const me = thisme.$message.warning('只能上传一个文件')},// 文件上传成功时的钩子handleSuccess(res, file) {const me = thisconst sign = me.uploadSign// 判断接口返回的 code 是否为 0 0 代表成功if (res.code === 0) {// 通过 sign 判断给相应的字段赋值if (sign === 1) {// 正面me.postData.frontPic = JSON.parse(res.result).url} else if (sign === 2) {// 背面me.postData.reversePic = JSON.parse(res.result).url} else if (sign === 3) {// 手持me.postData.handPic = JSON.parse(res.result).url}} else {// 失败回调me.$message.error(`${res.info}`)// 通过 sign 判断清空相应的列表 因为默认会显示出图片其实是失败了,容易造成用户误解if (sign === 1) {// 正面me.$refs.frontPic.clearFiles()} else if (sign === 2) {// 背面me.$refs.reversePic.clearFiles()} else if (sign === 3) {// 手持me.$refs.handPic.clearFiles()}}// 清空标记me.uploadSign = null},// 删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止上传。beforeRemove(file, fileList) {// 增加一个询问框return this.$confirm(`确定移除 ${file.name}?`)},// 文件列表移除文件时的钩子 因为是三个组件所以便分开写了三个方法,写成一个带参数的试过了不行handleRemoveFront(file, fileList) {const me = thisme.postData.frontPic = ''},handleRemoveReverse(file, fileList) {const me = thisme.postData.reversePic = ''},handleRemoveHand(file, fileList) {const me = thisme.postData.handPic = ''},// 提交数据submitForm(formName) {const me = thisthis.$refs[formName].validate(valid => {// 通过插件自定义全部规则已验证通过if (valid) {if (!me.postData.frontPic) {me.$message.error('请上传您的身份证正面图片')return false}if (!me.postData.reversePic) {me.$message.error('请上传您的身份证反面图片')return false}if (!me.postData.handPic) {me.$message.error('请上传您的身份证SIM卡手持图片')return false}let loading = Loading.service({fullscreen: true,text: '正在请求服务器'})me.axios.post(me.postAPI, qs.stringify(me.postData)).then(response => {loading.close()const getData = response.data// code 为 0 表示成功if (getData.code === 0) {me.$message.success(`${getData.info},即将自动跳转至列表页面`)// 新增成功跳转至 【通讯录管理】页面setTimeout(function() {location.href = 'addresslist.html'}, 2000)} else {me.$message.error(getData.info)}}).catch(error => {console.log(error)me.$message.error('请求服务器失败了,请稍后重试!')})} else {console.log('error submit!!')return false}})},// 重置表单resetForm(formName) {const me = thisthis.$refs[formName].resetFields()// 清空上传的文件// 正面me.$refs.frontPic.clearFiles()// 背面me.$refs.reversePic.clearFiles()// 手持me.$refs.handPic.clearFiles()me.postData.frontPic = ''me.postData.reversePic = ''me.postData.handPic = ''}}}</script><style lang="less">body {.container {form {width: 700px;margin: 0 auto;.show-img {width: 300px;max-width: 100%;}}}}</style>
主要演示下删除上传成功后的效果 gif

优化将
frontPicreversePichandPic这三个字段用一个数组包着,sign就不用在搞那么多的判断了,这样的话就是012,下面是三个代码片段// 三个上传字段写个数组方便下面使用,就不用一个一个的判断 uploadSign 的值了,直接 me.postData[me.uploadSignString[me.uploadSign]] 即可uploadSignString: ['frontPic', 'reversePic', 'handPic'],// 通过 [me.uploadSignString[me.uploadSign]] 判断给相应的字段赋值me.postData[me.uploadSignString[me.uploadSign]] = JSON.parse(res.result).url// 通过 sign 判断清空相应的列表 因为默认会显示出图片其实是失败了,容易造成用户误解me.$refs[me.uploadSignString[me.uploadSign]].clearFiles()

3. 使用 vue-cli3.x 时,引用 element-ui 的 css 文件报错
- 报错截图

These dependencies were not found:* fonts/element-icons.ttf in ./node_modules/css-loader??ref--6-oneOf-3-1!./node_modules/postcss-loader/src??ref--6-oneOf-3-2!./node_modules/element-ui/lib/theme-chalk/index.css* fonts/element-icons.woff in ./node_modules/css-loader??ref--6-oneOf-3-1!./node_modules/postcss-loader/src??ref--6-oneOf-3-2!./node_modules/element-ui/lib/theme-chalk/index.cssTo install them, you can run: npm install --save fonts/element-icons.ttf fonts/element-icons.woff
- 解决错误
问题 github 参考链接 出现错误的主要原因是在
vue.config.js配置文件中设置了css.modules = true,这个默认的值为false,只要把这个设置去掉问题即可得到解决
4. 使用分页 el-pagination 时,如果没加 :total 属性的话,即使用了 pager 这个 list 也显示不出来
出现问题的代码(我的 html 代码使用的是
pug模板)el-pagination(v-if="cusCrmList.total > 11" @current-change="clientPaginationHandle" :page-size="cusCrmList.size" layout="prev, pager, next, slot, jumper" :current-page.sync="cusCrmList.current" background small prev-text="上一页" next-text="下一页" align="right")span.el-pagination__total 共 {{ cusCrmList.pages }} 页
因为我不需要展示总页数,所以便没加
:total属性,但是这样的话,分页的pager部分就展示不出来了,后来试了试,发现是没加这个的原因,下面是可以正常显示的代码el-pagination(v-if="cusCrmList.total > 11" @current-change="clientPaginationHandle" :page-size="cusCrmList.size" layout="prev, pager, next, slot, jumper" :current-page.sync="cusCrmList.current" :total="cusCrmList.total" background small prev-text="上一页" next-text="下一页" align="right")span.el-pagination__total 共 {{ cusCrmList.pages }} 页
5. 使用
v-loading时,需要给其父级增加相对定位position: relative偶然性
Bug出现在IE上面(本地开发会出现,线上暂未见到),大致就是在某一次强制刷新页面的时候,由于loading的原因,遮住了部分的页面,页面会出现多个错位的loading导致布局看起来有些错乱,刷新也没有用,只能重新打开当前页面,后来发现使用v-loading自动生成的类名是el-loading-mask的标签样式如下.el-loading-mask {position: absolute;z-index: 2000;background-color: rgba(255, 255, 255, 0.9);margin: 0;top: 0;right: 0;bottom: 0;left: 0;-webkit-transition: opacity 0.3s;transition: opacity 0.3s;}
虽然正常情况是标签
display: none了,但是这里的Bug就是在异常情况下(没有隐藏掉),样式如上所示为绝对定位,但是由于父级没给相对定位,所以这里是相对于body去决定定位的,所以这个el-loading-mask的位置是总在页面最顶部,给加v-loading标签的父级加上相对定位 -> position: relative,这样的话及时出现loading未隐藏的Bug也不会影响页面的正常布局
6. 使用 dropdown、dropdown-menu、dropdown-item 实现点击下拉子菜单更改数据的需求
效果 Gif 图

- 官网示例使用的
command="a"属性的值是string,从下面的文档中可以看到这个指令支持 类型:string/number/object,我这里需要使用object类型的值 object类型使用示例的主要源码:<template lang="pug">el-dropdown(:show-timeout="0" @command="filtersStateHandle")span(class="filter-state-title") 状态i(class="el-icon-arrow-down el-icon--right")el-dropdown-menu(slot="dropdown")el-dropdown-item(v-for="(item,index) in filtersStateData" :key="item.value" :command="{ value: item.value }" :class="{ 'filter-state-active': item.value === signFilterData.getServState }") {{ item.text }}template(slot-scope="scope")span {{ scope.row.GET_SERV_STATE }}</template><script>export default {data() {return {// 【状态】字段下来使用的数据filtersStateData: [{ text: "全部", value: "ALL" },{ text: "正常", value: "F0A" },{ text: "主动停机", value: "F0I" },{ text: "欠费双向停机", value: "F0K" },{ text: "拆机", value: "F1X" }],}},methods:{/*** 右侧 header 【状态】 下拉筛选子列表点击回调* @param {object} command 当前点击的元素 key 为 command 的对象值*/filtersStateHandle(command) {// console.log(command);const me = this;// 数据变化me.signFilterData.getServState = command.value;me.getProductDyList();},}}<script><style lang="stylus" scoped>.el-dropdown-menu.filter-state-activebackground-color #ecf3ffcolor #659bfe</style>
7. 当使用
v-if v-else进行两个el-table数据判断,数据切换时会报错报错信息如下
Error in render: "TypeError: _self.$scopedSlots.default is not a function"
原因
是由于两个
el-table组件使用了相同的数据导致解决方法
给两个
el-table组价分别增加一个不同的key属性值
8. 当使用 pug 模板进行布局时,table 的排序 sortable 功能无法使用
这个问题真的是很怪异,翻阅了 github 的 Issues 列表幸好查到了相关的问题文章
issues 链接:[Bug Report] el-table can not sort with Pug template language used. #11531 上述人员提供的成功在线 demo
主要就是写法和官网的有些差异

sortable 写成 :sortable='true' 即可
9. 引用 element-ui 中的 Tree 组件时,在 IE 浏览器中会报错
- 错误重现
- 浏览器版本 IE11
报错截图

示例源码
<el-tree ref="treeDOM" :data="treeData" show-checkboxnode-key="id" default-expand-all:expand-on-click-node="false"><span class="custom-tree-node" slot-scope="{ node, data }">{{ data.name }} ({{ data.roleName }})</span></el-tree>
百度之后找到可参考的文章
vue在IE浏览器下报错Failed to generate render function:SyntaxError: 缺少标识符 in
解决思路
看到这个错误提示的时候,其实我没想到会是
Tree组件的问题,主要是参考上面的文章,测试之后发现确实是这个组件的写法导致的错误; 主要的原因是slot-scope="{ node, data }"这个是es6的对象解构赋值,很显然IE是不支持的,具体的纠错方法是将slot-scope属性的值写成scope这个对象,然后后面使用scope.node或者scope.data的写法去调用子属性即可。
示例源码
<el-tree ref="treeDOM" :data="treeData" show-checkboxnode-key="id" default-expand-all:expand-on-click-node="false"><span class="custom-tree-node" slot-scope="scope">{{ scope.data.name }} ({{ scope.data.roleName }})</span></el-tree>
10.
el-table->el-table-column的render-header属性使用示例需求:表头需要定制为换行的风格
实现:使用
render-header属性,下面是相应的html和javascript代码片段el-table-column(prop="" label="第一行的文本,第二行的文本" show-overflow-tooltip :render-header="renderHeaderHtml")
renderHeaderHtml(h, { column, $index }){const stringArray = column.label.split(',')return h('p', [h('span', stringArray[0]),h('br'),h('span', stringArray[1])])}
11.
el-cascader,封装一个公用的组件组件的完整源码,这个组件是
<template lang="pug">//- 基于 el-cascader 组件,自定义一个角色结构树组件.identity-tree//- 是否保留清空方法待定 clearableel-cascader(ref="identityTree" v-model="selectedOptions" :props="{ checkStrictly: true,lazy: true,lazyLoad: loadHandleNode,leaf: 'isLeaf', label: 'orgnName', value: 'orgnId'}" :show-all-levels="false" @change="cascaderHandleChange" filterable placeholder="请选择" size="mini")</template><script>// apiimport { getSysOrgnInfo } from "@/api/common";export default {name: "IdentityTree",data() {return {selectedOptions: [],// 储存转换后的当前用户信息currentUserInfo: {}};},methods: {/*** 查询部门下拉树结构* id 如果有传 id 值,表示这里请求的是子级的数据,返回一个 peomise,否则表示是一级数据直接返回*/getSysOrgnInfo(orgnId) {// 判断如果传的是 "" 值,表示这里是需要初始化最初的用户身份,否则正常请求接口if (orgnId) {// 获取下级的列表数据return new Promise(resolve => {getSysOrgnInfo({orgnSumId: orgnId}).then(res => {let saveData = res.data.data;console.log(saveData);// 手动将 isLeaf 字段转换成 Boolean 值saveData.forEach(element => {element.isLeaf = !!element.isLeaf;});resolve(saveData);});});} else {// 获取当前用户身份的数据return new Promise(resolve => {let { currentManagerTm } = JSON.parse(JSON.stringify(this.$store.getters.getUserInfo));currentManagerTm.orgnName = currentManagerTm.areaName;currentManagerTm.orgnId = currentManagerTm.areaId;// resolve([currentManagerTm]);// 直接传递当前用户信息// this.$emit("update-component-data", this.currentUserInfo);getSysOrgnInfo({sessionOrgnSumId: currentManagerTm.orgnId}).then(res => {let saveData = res.data.data;// 手动将 isLeaf 字段转换成 Boolean 值saveData.forEach(element => {element.isLeaf = !!element.isLeaf;});resolve(saveData);this.currentUserInfo = saveData[0];// 默认选中当前用户身份,并触发页面加载数据this.selectedOptions = [currentManagerTm.orgnId];this.$emit("update-component-data", saveData[0]);});});/*return new Promise(resolve => {let { currentManagerTm } = JSON.parse(JSON.stringify(this.$store.getters.getUserInfo));getSysOrgnInfo({sessionOrgnSumId: currentManagerTm.areaId}).then(res => {let saveData = res.data.data;console.log(saveData);// 手动将 isLeaf 字段转换成 Boolean 值saveData.forEach(element => {element.isLeaf = !!element.isLeaf;});resolve(saveData);this.$emit("update-component-data", saveData);});});*/}},/*** 部门节点加载函数*/async loadHandleNode(node, resolve) {console.log(node.level);const data = await this.getSysOrgnInfo(node.level === 0 ? "" : node.data.orgnId);resolve(data);},/*** 选中弹窗内部的部门节点加载函数*/cascaderHandleChange(value) {let $identityTree = this.$refs.identityTree;// 由于组件没有单选关闭悬浮窗的回调,所以需要手动关闭$identityTree.toggleDropDownVisible(false);if (value) {// 调用父组件方法,传递当前单选选中的身份对象const checkedNodes = $identityTree.getCheckedNodes();// 判断如果单选无选中值时,传递当前用户信息this.$emit("update-component-data",checkedNodes.length ? checkedNodes[0].data : this.currentUserInfo);}}}};</script>
12.
Uncaught ReferenceError: _MessageBox is not defined浏览器控制台报错,错误导致应用无法正常显示这个错误之前从未遇到过,我什么都没改过,也不知道抽什么风 0.0
参考文章:
https://github.com/ElementUI/babel-plugin-component/issues/31
解决方法:
https://github.com/ElementUI/babel-plugin-component/issues/31#issuecomment-530874578
const msgbox = MessageBoxconst { alert, confirm, prompt } = msgboxVue.prototype.$msgbox = msgboxVue.prototype.$alert = alertVue.prototype.$confirm = confirmVue.prototype.$prompt = prompt
13. el-form-item 自动验证的 Bug
问题描述
首先页面是两个大的模块,由
if else驱动其显示隐藏,,第二个模块中的一个表单元素在每次判断其显示时,会自动验证一下,而且提示还不是我自定义的文本
参考资料
在dialog弹框里放一个form,form里面的一组checkbox加了change验证后,在第二次打开弹框及以后,每次打开dialog弹框,什么都没做,它就自动验证了 #3240 文章给出的解决方法是
this.$refs.baseForm.resetFields();,但是场景和我的有些差异。解决方法
将这个表单元素自身判断使用的
v-if,放到作为其自动响应式布局的父级el-row即可。
14. el-select 绑定值为对象时使用 value-key 的示例
<template><el-select v-model="value" value-key="code" placeholder="请选择"><el-option-groupv-for="group in options":key="group.label":label="group.label"><el-optionv-for="item in group.child":key="item.code":label="item.label":value="item"></el-option></el-option-group></el-select></template>
export default {data() {return {options:[{"code": "01","label": "用户属性","child": [{"calculateFlag": "0","inputFlag": "2","code": "A01001001","label": "用户邮箱","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001002","label": "用户名称","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001003","label": "用户ID","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001004","label": "用户归属省份","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001005","label": "用户归属地市","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001006","label": "用户归属区县","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001007","label": "用户归属渠道","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001008","label": "客户手机号","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001009","label": "客户ID","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001010","label": "客户名称","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "1","code": "A01001011","label": "注册时间","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001012","label": "注册渠道","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001013","label": "个人/企业","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001015","label": "所属行业","firstLevelCode": "01"},{"calculateFlag": "3","inputFlag": "0","code": "A01001016","label": "是否实名","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001017","label": "实名认证类型","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01001018","label": "实名认证时间","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001019","label": "性别","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001020","label": "年龄","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001021","label": "生日","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001022","label": "客户经理","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001023","label": "一人一码客户经理","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001024","label": "一人一码客户经理手机号","firstLevelCode": "01"},{"calculateFlag": "3","inputFlag": "0","code": "A01001026","label": "是否一人一码注册用户(云大使注册)","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001027","label": "一人一码(云大使)二维码ID","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001028","label": "一人一码归属省","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001029","label": "一人一码归属地市","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001030","label": "一人一码归属区县","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01001031","label": "运营商","firstLevelCode": "01"},{"calculateFlag": "3","inputFlag": "0","code": "A01002002","label": "是否资源在用用户","firstLevelCode": "01"},{"calculateFlag": "3","inputFlag": "0","code": "A01002003","label": "是否测试用户","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01002005","label": "到期产品","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01002006","label": "到期时间","firstLevelCode": "01"},{"calculateFlag": "3","inputFlag": "0","code": "A01002008","label": "是否首次到期","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01002010","label": "在网时长","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003001","label": "账户余额","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003002","label": "欠费金额","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "2","code": "A01003003","label": "欠费次数","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003004","label": "总出账金额","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003005","label": "近3月出账金额","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003006","label": "分产品出账金额","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003010","label": "充值金额","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01003013","label": "充值方式","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003015","label": "累计充值次数","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003016","label": "累计充值金额","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003017","label": "累计欠费次数","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003018","label": "累计提现次数","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01003019","label": "日均按需费用","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004016","label": "近30天充值次数","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "2","code": "A01004017","label": "近30天充值金额","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004018","label": "累计订单标准价","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004019","label": "累计订单降配实际价格","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004020","label": "累计订单实际价格","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004021","label": "累计订单现金金额","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004022","label": "累计降配次数","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004023","label": "累计降配订单标准价","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004024","label": "累计降配订单现金","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004025","label": "累计退订次数","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004026","label": "累计退订金额","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01004027","label": "累计优惠券/代金券使用金额","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01005001","label": "产品名称","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01005002","label": "产品类型","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01005011","label": "订单失效时间","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01005012","label": "订单按需或包周期","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01005013","label": "付费类型","firstLevelCode": "01"},{"calculateFlag": "3","inputFlag": "0","code": "A01005021","label": "是否一人一码订单","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01006010","label": "资源个数","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01006011","label": "资源类型","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01006012","label": "资源使用时长","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01006013","label": "资源最晚到期时间","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008001","label": "优惠券/满折优惠券活动名称","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008002","label": "优惠券号","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008003","label": "优惠券名称","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01008004","label": "优惠券领取时间","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01008005","label": "优惠券金额","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01008007","label": "优惠券到期时间","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01008009","label": "优惠券使用金额","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008013","label": "优惠券使用条件","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008014","label": "优惠券发放目的","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008016","label": "满减折扣类型","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008017","label": "代金券号码","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01008019","label": "代金券领取时间","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01008020","label": "代金券金额","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01008022","label": "代金券到期时间","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008031","label": "满折优惠券名称","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008032","label": "满折优惠券券号","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01008033","label": "满折优惠券领取时间","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01008034","label": "满折优惠券金额","firstLevelCode": "01"},{"calculateFlag": "1","inputFlag": "0","code": "A01008036","label": "满折优惠券到期时间","firstLevelCode": "01"},{"calculateFlag": "2","inputFlag": "1","code": "A01008038","label": "满折优惠券使用金额","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008042","label": "满折优惠券使用条件","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01008054","label": "折扣券发放目的","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009001","label": "track","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009002","label": "推广单元","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009003","label": "推广关键词","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009004","label": "推广渠道","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009005","label": "引导登录页面名称","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009006","label": "引导登录页面模块","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009007","label": "引导登录注册模块","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009008","label": "引导页面登录URL","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009009","label": "引导页面注册URL","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009010","label": "引导注册页面名称","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009011","label": "注册访问来源(referer)","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009012","label": "注册track","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009013","label": "注册推广单元","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009014","label": "注册推广计划","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009015","label": "注册推广关键词","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009016","label": "注册推广渠道","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009017","label": "实名渠道","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009018","label": "实名track","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009019","label": "实名推广单元","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009020","label": "实名推广计划","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009021","label": "实名推广关键词","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009022","label": "订单渠道","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009023","label": "订单track","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009024","label": "订单推广单元","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009025","label": "订单推广计划","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01009026","label": "订单推广关键词","firstLevelCode": "01"},{"calculateFlag": "0","inputFlag": "2","code": "A01010002","label": "实名认证状态","firstLevelCode": "01"}]},{"code": "02","label": "用户行为","child": [{"calculateFlag": "0","inputFlag": "2","code": "A02001016","label": "访问来源(referer)","firstLevelCode": "02"},{"calculateFlag": "0","inputFlag": "2","code": "A02001017","label": "访问终端类型","firstLevelCode": "02"},{"calculateFlag": "0","inputFlag": "2","code": "A02002001","label": "近30天浏览页面名称","firstLevelCode": "02"},{"calculateFlag": "2","inputFlag": "1","code": "A02003005","label": "CPU使用率","firstLevelCode": "02"},{"calculateFlag": "2","inputFlag": "1","code": "A02003006","label": "内存使用率","firstLevelCode": "02"},{"calculateFlag": "1","inputFlag": "0","code": "A02008001","label": "最近登录时间","firstLevelCode": "02"},{"calculateFlag": "0","inputFlag": "2","code": "A02009001","label": "故障产品名称","firstLevelCode": "02"},{"calculateFlag": "0","inputFlag": "2","code": "A02009002","label": "故障解决满意度","firstLevelCode": "02"},{"calculateFlag": "0","inputFlag": "2","code": "A02009004","label": "故障原因","firstLevelCode": "02"}]}],value: ''}}}
15. el-cascader 在内部的 tags 单个标签删除时,getCheckedNodes 还是可以正常获取到删除之前的所有节点,导致处理数据时出现 bug
解决方式
这里我将
watch中的同步代码,改为异步,之后就能正常读取到,删除之后的所有标签了源码
// template => html <el-cascader v-else-if="item.type === 'cascader'" v-model="basicInfo[item.name]" :ref="`${item.name}Cascader`" placeholder="全部" :options="commonData[item.selectKey]" :props="{ multiple: true, checkStrictly: true, label: 'activityName', children: 'child', value: 'activityName' }" filterable collapse-tags clearable ></el-cascader> // js => watch /** * 监测活动字段,手动赋值 */ 'basicInfo.activeName': { handler(val) { // 同步会有 bug(tags 删除时,getCheckedNodes 还是可以正常获取到),所以做成异步的 this.$nextTick(() => { if ( this.$refs['activeNameCascader'] && this.$refs['activeNameCascader'][0] ) { // 因为组件是在一个 `v-for`循环中生成的,所以需要使用 [0] const activeCascader = this.$refs['activeNameCascader'][0] const selectedData = this.$refs[ 'activeNameCascader' ][0].getCheckedNodes() // 初始化值时有两种情况: // 1 表头需要动态展示的 也就是 activityName 和 eventTypeName 设置为 null // 2 表头需要固定展示的 let activityType = '', activityName = null, eventTypeName = null const { dataDetailShow, pageNavValue } = this if ( dataDetailShow || ['RelevanceBuyStatistics'].includes(pageNavValue) ) { activityName = eventTypeName = '' } // 有选中值才进行操作 if (selectedData.length) { const levelOne = selectedData.filter((o) => { const { level, checked } = o return level === 1 && checked }) if (levelOne.length) { activityType = levelOne .map((element) => { return element.value }) .join(',') } const levelTwo = selectedData.filter((o) => { const { level, checked } = o return level === 2 && checked }) if (levelTwo.length) { activityName = levelTwo .map((element) => { return element.value }) .join(',') } const levelThree = selectedData.filter((o) => { const { level, checked } = o return level === 3 && checked }) // levelThree 需要截取下划线之后的名称 if (levelThree.length) { let resultFirstName = [] levelThree.forEach((element) => { const { value } = element const index = value.indexOf('_') if (index !== -1) { resultFirstName.push(value.substring(index + 1)) } }) eventTypeName = resultFirstName.join(',') } } // 赋值 this.$set(this.basicInfo, 'activityType', activityType) this.$set(this.basicInfo, 'activityName', activityName) // 活动用户关联购买统计 字段名不同 if (!['RelevanceBuyStatistics'].includes(pageNavValue)) { this.$set(this.basicInfo, 'eventTypeName', eventTypeName) } else { this.$set(this.basicInfo, 'activityFirstName', eventTypeName) } } }) } }16.
el-table自定义表头列表中某个单元格的样式源码:
<template> <el-table :data="tableData" style="width: 100%" :header-cell-style="headerCellStyle"> <el-table-column prop="date" label="各省" width="150"> </el-table-column> <el-table-column label="宽带"> <el-table-column prop="name" label="姓名" width="120"> </el-table-column> <el-table-column label="移动"> <el-table-column prop="province" label="省份" width="120"> </el-table-column> <el-table-column prop="city" label="市区" width="120"> </el-table-column> <el-table-column prop="address" label="地址" width="300"> </el-table-column> <el-table-column prop="zip" label="邮编" width="120"> </el-table-column> </el-table-column> </el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [ { date: "2016-05-03", name: "王小虎", province: "上海", city: "普陀区", address: "上海市普陀区金沙江路 1518 弄", zip: 200333 }, { date: "2016-05-02", name: "王小虎", province: "上海", city: "普陀区", address: "上海市普陀区金沙江路 1518 弄", zip: 200333 }, { date: "2016-05-04", name: "王小虎", province: "上海", city: "普陀区", address: "上海市普陀区金沙江路 1518 弄", zip: 200333 }, { date: "2016-05-01", name: "王小虎", province: "上海", city: "普陀区", address: "上海市普陀区金沙江路 1518 弄", zip: 200333 }, { date: "2016-05-08", name: "王小虎", province: "上海", city: "普陀区", address: "上海市普陀区金沙江路 1518 弄", zip: 200333 }, { date: "2016-05-06", name: "王小虎", province: "上海", city: "普陀区", address: "上海市普陀区金沙江路 1518 弄", zip: 200333 }, { date: "2016-05-07", name: "王小虎", province: "上海", city: "普陀区", address: "上海市普陀区金沙江路 1518 弄", zip: 200333 } ] }; }, methods: { /** * 自定义表头列表中某个单元格的样式 */ headerCellStyle({ column }) { const whitelist = ['各省', '宽带', '移动', '5G'] if (!whitelist.includes(column.label)) { return { backgroundColor: 'red', color: '#333' } } else { return {} } } } } </script>17.
el-table多列合并单元格,可以指定某列源码:
<template> <div> <!-- 指定 count 取默认属性 --> <el-table :data="tableData" :span-method="arraySpanMethod" border style="width: 100%"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="name" label="姓名"> </el-table-column> <el-table-column prop="amount1" sortable label="数值 1"> </el-table-column> <el-table-column prop="amount2" sortable label="数值 2"> </el-table-column> <el-table-column prop="amount3" sortable label="数值 3"> </el-table-column> </el-table> <hr /> <!-- 指定 props --> <el-table :data="tableData" :span-method="arraySpanMethod2" border style="width: 100%"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="name" label="姓名"> </el-table-column> <el-table-column prop="amount1" sortable label="数值 1"> </el-table-column> <el-table-column prop="amount2" sortable label="数值 2"> </el-table-column> <el-table-column prop="amount3" sortable label="数值 3"> </el-table-column> </el-table> </div> </template> <script> export default { data() { return { tableData: [ { id: "12987122", name: "王小1虎", amount1: "234", amount2: "3.2", amount3: 10 }, { id: "12987121", name: "王小虎", amount1: "324", amount2: "4.43", amount3: 12 }, { id: "12987125", name: "王小虎", amount1: "621", amount2: "1.9", amount3: 9 }, { id: "12987125", name: "王小21虎", amount1: "621", amount2: "2.2", amount3: 17 }, { id: "12987126", name: "王小2虎", amount1: "539", amount2: "2.2", amount3: 15 } ], mergeResult: [], mergeResult2: [], props: ["name", "amount2"] }; }, created() { // 指定 count 取默认属性 this.mergeResult = this.mergeColumnCells(this.tableData, 2); // 指定 props this.mergeResult2 = this.mergeColumnCells(this.tableData, 0, this.props); console.log(this.mergeResult); console.log(this.mergeResult2); }, methods: { /** * 多列合并单元格,可以指定某列,下面的 count 和 props 参数,虽然都是非必须的,但是至少得保证有一个 * @param {Array} data 需要处理的数据 * @param {Number} count 非必须参数:需要合并单元格的列的总数量(满足从初始第一列至连续的 count 列的条件) * @param {Array} props 非必须参数:需要合并单元格的数据列对应的属性列表,示例:['id','name'] * @returns {Array} 储存嵌套的每一列需要合并单元格的合并的格数,示例:[[1,1,2,0,1],[1,2,0,1,1]] * 两种不同方式的调用示例: * 指定 count 取默认属性:this.mergeResult = this.mergeColumnCells(this.tableData, 2); * 指定 props:this.mergeResult = this.mergeColumnCells(this.tableData, 0, this.props); * 完整的在线示例地址 [element table 多列合并单元格,可以指定某列](https://codepen.io/sunxiaochuan/pen/wvoOXzG) */ mergeColumnCells(data, count, props) { if (data && data.length && (count || props)) { // 先获取到需要合并的属性列表 props = props || []; // 不存在的话就依照 count 字段开始取默认名称 if (!props.length) { for (const key in data[0]) { if (data[0].hasOwnProperty(key)) { props.push(key); } if (props.length === count) { break; } } } let saveData = []; for (let index = 0; index < props.length; index++) { const prop = props[index]; // 设置初始化值 saveData[index] = []; let dataList = saveData[index]; // 数据计算 for (let i = 0; i < data.length; i++) { const element = data[i]; // 逻辑:默认的第一条 i === 0 数据将初始化单元格数量为 1,从第二条 i === 1 数据开始与上一条数据开始做属性比较,一致的话上一个单元格 += 1,相应的当前单元格需要置为 0,否则为默认值 1 if (i === 0) { dataList.push(1); } else { // 判断与上一条数据对应的属性值是否一致,如果是的话上一个单元格需要自增 1,并设置当前的单元格为 0,否则为 1 const prev = data[i - 1]; if (element[prop] === prev[prop]) { dataList[i - 1] += 1; dataList.push(0); } else { dataList.push(1); } } } } return saveData; } else { return []; } }, arraySpanMethod({ row, column, rowIndex, columnIndex }) { if (columnIndex < 2) { const _row = this.mergeResult[columnIndex][rowIndex]; return [_row, 1]; } }, // 指定 props arraySpanMethod2({ row, column, rowIndex, columnIndex }) { const index = this.props.indexOf(column.property); if (index != -1) { const _row = this.mergeResult2[index][rowIndex]; return [_row, 1]; } } } } </script>18.
el-table多列排序源码:
<template> <el-table :data="tableData" style="width: 100%" :header-cell-class-name='handleHeadAddClass' @sort-change='tableSortChange'> <el-table-column prop="date" label="日期" sortable width="180"> </el-table-column> <el-table-column prop="name" label="姓名" sortable width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [ { date: "2016-05-02", name: "李小虎", address: "上海市普陀区金沙江路 1518 弄" }, { date: "2016-05-04", name: "王小虎", address: "上海市普陀区金沙江路 1517 弄" }, { date: "2016-05-01", name: "安小虎", address: "上海市普陀区金沙江路 1519 弄" }, { date: "2016-05-03", name: "王小虎", address: "上海市普陀区金沙江路 1516 弄" } ], sortPropList: {} }; }, methods: { /** * 报表所有表头都可以进行排序,1 升;2 降 */ tableSortChange({ column, prop, order }) { let sortType = undefined; switch (order) { case "ascending": sortType = "1"; break; case "descending": sortType = "2"; break; default: break; } this.sortPropList[prop] = order; // 获取数据 // this.$set(sortProp, 'sortType', sortType) // this.submitFilterForm(); }, /** * 增加多列排序 */ handleHeadAddClass({ column }) { if (this.sortPropList[column.property]) { column.order = this.sortPropList[column.property]; } } } } </script>
