- 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-upload
class="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-upload
class="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-upload
class="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=10
import { 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 = this
const isJPG = file.type === 'image/jpeg'
const isPNG = file.type === 'image/png'
if (!(isJPG || isPNG)) {
me.$message.error('上传的文件只能是 JPG 或者是 PNG 格式的')
}
},
// 文件超出个数限制时的钩子
handleExceed(file, fileList) {
const me = this
me.$message.warning('只能上传一个文件')
},
// 文件上传成功时的钩子
handleSuccess(res, file) {
const me = this
const 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-upload
class="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-upload
class="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-upload
class="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=10
import { 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 = this
const isJPG = file.type === 'image/jpeg'
const isPNG = file.type === 'image/png'
if (!(isJPG || isPNG)) {
me.$message.error('上传的文件只能是 JPG 或者是 PNG 格式的')
}
},
// 文件超出个数限制时的钩子
handleExceed(file, fileList) {
const me = this
me.$message.warning('只能上传一个文件')
},
// 文件上传成功时的钩子
handleSuccess(res, file) {
const me = this
const 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 = this
me.postData.frontPic = ''
},
handleRemoveReverse(file, fileList) {
const me = this
me.postData.reversePic = ''
},
handleRemoveHand(file, fileList) {
const me = this
me.postData.handPic = ''
},
// 提交数据
submitForm(formName) {
const me = this
this.$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 = this
this.$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
优化将
frontPic
reversePic
handPic
这三个字段用一个数组包着,sign
就不用在搞那么多的判断了,这样的话就是0
1
2
,下面是三个代码片段// 三个上传字段写个数组方便下面使用,就不用一个一个的判断 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.css
To 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-active
background-color #ecf3ff
color #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-checkbox
node-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-checkbox
node-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
//- 是否保留清空方法待定 clearable
el-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>
// api
import { 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 = MessageBox
const { alert, confirm, prompt } = msgbox
Vue.prototype.$msgbox = msgbox
Vue.prototype.$alert = alert
Vue.prototype.$confirm = confirm
Vue.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-group
v-for="group in options"
:key="group.label"
:label="group.label">
<el-option
v-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>