目录
- 一、vue 监听键盘回车事件 @keyup.enter
- 二、vue.config.js中devServer.proxy配置说明及配置正确不生效问题解决
- vue中ref的作用
文章参考: https://www.cnblogs.com/yangai/tag/%E5%89%8D%E7%AB%AF/
ruoyi登录页面: https://www.yii666.com/blog/381438.html
一、vue 监听键盘回车事件 @keyup.enter
@keyup.enter.native和@click.native.prevent 分别是什么意思
- @keyup.enter.native
一般vue自身的监听组件,是这样写 v-on: 等价于 @符
<input v-on:keyup.enter="submit">
<input @keyup.enter="submit">
但是, 如果用了封装组件的话,比如element,这个时候使用按键修饰符需要加上.native
<el-input v-model="account" placeholder="请输入账号" @keyup.enter.native="search()"></el-input>
- @click.native.prevent
2-1.在封装好的组件上使用,所以要加上.native才能click
2-2.prevent就相当于event.preventDefault()
jQuery 事件 - preventDefault() 方法
preventDefault() 方法阻止元素发生默认的行为(例如,当点击提交按钮时阻止对表单的提交)
官方文档上说的.native是监听组件根元素的原生事件 添加native修饰符号这个是为了防止出现给组件绑定click事件不执行的情况,
参考链接:keyup.enter.native&click.native.prevent
vue el-switch 绑定数值时注意问题
- vue el-switch 绑定数值时要用
<el-switch v-model="value"
:active-value="1"
:inactive-value="0"
active-color="#13ce66"
inactive-color="#ff4949">
</el-switch>
- vue el-switch 绑定String时要用
<el-switch v-model="value"
active-value="1"
inactive-value="0"
active-color="#13ce66"
inactive-color="#ff4949">
</el-switch>
布局组件el-row和el-col 详解
element ui中表单el-form的label如何设置宽度
-
element ui中表单el-form的label设置宽度
测试要求把输入框前面的名字带括号的把括号部分显示在下一行,可以通过设置前面的label宽度来进行换行。-
在具体的el-form-item中设置label-width,
-
也可以为整个表单el-form设置label-width,这样整个页面的label宽度统一。
例:
<el-form label-width="100px">
//在el-form 设置 label宽度 label-width=“120px”
-
<el-form :model="ruleFormOne" :rules="rules" ref="ruleFormOne" label-width="120px">
<el-form-item label="活动标题:" prop="name">
<el-input
:disabled="isDisabledPart"
class="p-inputCount"
type="text"
v-model="ruleFormOne.name"
placeholder="请输入标题,限16个字"
maxlength = "16"
style="width: 300px"
@input = "formatName"
show-word-limit
clearable
>
</el-input>
</el-form-item>
//在el-form-item 重置label宽度,label-width=“50px”
<el-form-item label="" label-width="50px" >
活动期间内,会员每拥有
<span class="inline-block">
<el-form-item
prop="items[0].eventtimes" >
<el-input
v-model="ruleFormOne.items[0].eventtimes"
:disabled="true"
style="width: 60px"
class="input-width"
clearable>
</el-input>
</el-form-item>
</span>
</el-form>
Element 布局组件el-row和el-col 详解
-
背景
element的布局方式与bootstrap原理是一样的,将网页划分成若干行,然后每行等分为若干列,基于这样的方式进行布局,形象的成为栅栏布局。
区别是element可将每行划分为24个分栏,而bootstrap是划分为12个分栏,从使用角度,还是24个分栏更加精细。 -
分栏布局
首先每行使用标签标识,然后每行内的列使用标识,至于每列整行的宽度比例,则使用:span属性进行设置。
如下代码,即为将1行等分为2列,为了便于区分列,我们为列添加了不同的样式,另外注意是分割线,此处用于区分不同的示例。
<template>
<div>
<span>每行24分栏布局</span>
<el-row>
<el-col :span="12" class="lightgreen-box">示例1</el-col>
<el-col :span="12" class="orange-box">示例1</el-col>
</el-row>
<el-divider></el-divider>
</div>
</template>
<style scoped>
.lightgreen-box {
background-color: lightgreen;
height: 24px;
}
.orange-box {
background-color: orange;
height: 24px;
}
</style>
效果如下:
————————————————
3. 分栏间隔
有时候想为不同分栏之间设定一定的间隔,可以使用标签的:gutter属性,注意默认间隔为0。
此时需要注意的是,下面的写法,间隔是不生效的。
<span>分栏间隔 无效</span>
<el-row :gutter="50">
<el-col :span="8" class="lightgreen-box">示例2</el-col>
<el-col :span="8" class="orange-box">示例2</el-col>
<el-col :span="8" class="lightgreen-box">示例2</el-col>
</el-row>
<el-divider></el-divider>
需要在分栏里面新增元素,才能实现分栏间隔,代码修改如下则间隔生效。
<span>分栏间隔 有效</span>
<el-row :gutter="24">
<el-col :span="8">
<div class="lightgreen-box">示例3</div>
</el-col>
<el-col :span="8">
<div class="orange-box">示例3</div>
</el-col>
<el-col :span="8">
<div class="lightgreen-box">示例3</div>
</el-col>
</el-row>
<el-divider></el-divider>
上面两个示例效果如下:
4. 分栏偏移
有时候想让某个分栏不从左边显示,而是直接显示到中间或者右侧,例如右侧导航栏,我们希望它处于右侧且占据页面1/3的宽度。此时可以借助offset属性来实现,表示偏移量。
此时,想占据1/3宽度,则:span应为8,偏移量应为24-8=16,所以代码如下:
<span>分栏偏移</span>
<el-row>
<el-col :span="8" :offset="16">
<div class="lightgreen-box">示例4</div>
</el-col>
</el-row>
<el-divider></el-divider>
效果如下:
5. 对齐方式
row组件的type="flex"启动flex布局,再通过row组件的justify属性调整排版方式,属性值分别有:
justify=center 居中对齐
justify=start 左对齐
justify=end 右对齐
justify=space-between 空格间距在中间对齐
justify=space-around 左右各占半格空格对齐
如果想让整个行居左、居中、居右对齐,则可以直接设置的对齐方式。
此时需要先设置type="flex"来启用对齐方式,然后通过justify属性来设置具体的对齐方式,例如下面的例子实现了居中对齐。
<span>对齐方式</span>
<el-row type="flex" justify="center">
<el-col :span="12">
<div class="lightgreen-box">示例5</div>
</el-col>
</el-row>
<el-divider></el-divider>
效果如下:
6. 响应式布局
element和bootstrap的响应式布局原理相同,都是通过为列设置不同分辨率下的占用宽度比例来实现的。
例如我们想实现在比较大的分辨率(电脑),每分栏占据屏幕宽度的1/4,而在比较小宽度(手机),每分栏占据屏幕全部宽度。这样就能保证在手机上也能完整显示内容,则可以使用如下代码:
<span>响应式布局</span>
<el-row>
<el-col :lg="6" :xs="24" class="lightgreen-box">示例6</el-col>
<el-col :lg="6" :xs="24" class="orange-box">示例6</el-col>
<el-col :lg="6" :xs="24" class="lightgreen-box">示例6</el-col>
<el-col :lg="6" :xs="24" class="orange-box">示例6</el-col>
</el-row>
在电脑上效果如下:
在手机上效果如下:
注意具体的尺寸属性为:
属性 使用说明
- 小结
element的布局跟bootstrap原理是一样的,使用起来也比较方便,具体的参数其实不需要都记住,只要知道用法,使用时去官网查询即可。
参考: https://blog.csdn.net/zxlyx/article/details/125895348
——————————————————
使用Element-UI中输入框转换成文本域
在使用Vue+Element-UI框架项目过程中,如果不仔细看Element官网,你会发现表单控件中没有文本域。但当你仔细阅读el-input控件时,你会发现输入框和文本域是共用一个控件,只不过文本域需要加属性type=“textarea”
<el-form-item label="项目简介" prop="brief">
<el-input type="textarea" rows=3 v-model="form.brief" placeholder="请输入项目简介" />
</el-form-item>
</el-form>
Vue-自定义表单验证(rule,value,callback)callback的意思
前言
-
最近需要验证合同编号是否在数据库已经存在,自定义表单验证。
-
表单验证大家都知道form绑定rules,prop绑定值与form.值一样,必填,失去焦点触发 提示信息。
-
自定义验证规则具体使用场景和它的三个参数意思和使用
-
当我们明白了 validator 3个参数意思,我们就可以随机组合我们自己的验证规则了
自定义验证规则
prop绑定值: [
{
validator: (rule, value, callback) => {
console.log('验证规则信息',rule);
console.log('输入框的值',value);
// 1. callback()为空通过验证
// 2. callback(new Error('未通过验证,抛出异常'))
// callback 可以打印输出
console.log('是否通过验证规则', callback);
},
// 失去焦点触发
trigger: "blur",
},
],
使用场景 - 正则验证是否是手机号
test()方法:用于检测字符串中指定的值,匹配成功返回true,匹配失败返回false
prop的值: [
{ validator: (rule, value, callback) {
// 手机号正则表达式
const reg = /^[1][3,4,5,7,8][0-9]{9}$/
if (value == '' || value == undefined || value == null) {
callback()
} else {
// 正则失败false,取反true抛出异常
if (!reg.test(value) && value != '') {
// 抛出异常,验证规则有错
callback(new Error('请输入正确的电话号码'))
} else {
callback()
}
}
// 输入框值变化一次执行一次
}, trigger: "change" },
],
使用场景-多选判断是否选中
checkListmain是data里面数据,是多选v-model绑定的值,是一个数组
prop绑定值: [
{ required: true, message: "请输入合同编号", trigger: "blur" },
{
validator: async (rule, value, callback) => {
// 发请求
const res = await adrepetition(value);
console.log("合同编号", res
// 判断状态码
if (res.code == 200) {
callback();
} else {
callback(new Error("合同编号重复,请重新输入"));
}
},
trigger: "blur",
},
],
使用场景 ltkj-project-manager 金额输入框校验
<el-row>
<!-- -->
<el-col :span="12">
<el-form-item label="项目金额" prop="amount">
<el-input v-model.trim="form.amount"
placeholder="请输入项目金额"
></el-input>
</el-form-item>
</el-col>
callback提示信息不对的问题
// 表单参数
return {
form: {},
// 表单校验
rules: {
amount: [
// 1. 这样写,提示信息 永远是 message: "项目金额不能为空", 而不显示validatorMoney 里 callback(new Error('只能输入数字')); 信息
// {
// required: true, message: "项目金额不能为空",
// validator: validatorMoney, trigger: 'blur'
// }
// 2. 不同的提示信息,一定要用2 这样,两个{}分开的:
{required: true, message: "项目金额不能为空", trigger: 'blur'},
{validator: validatorMoney, trigger: 'blur' }
],
}
const validatorMoney = (rule, value, callback) => {
let isVal = value.toString() //先转换成字符串类型
let regnumDot = /[^\d.]/g
if (isVal === '') {
callback(new Error('请输入金额'));
} else if (regnumDot.test(isVal)) {
// this.form.money = isVal.replace(/[^\d.]/g, ""); //清除“数字”和“.”以外的字符
callback(new Error('只能输入数字'));
} else if (isVal.indexOf('.') === 0) {
this.form.money = parseFloat('0' + isVal);
} else if (isVal.indexOf('.') < 0 && isVal != "") {
this.form.money = parseFloat(isVal); //如果没有小数点,首位不能为类似于 01、02的金额
} else if (isVal.split(".").length - 1 > 1) {
this.form.money = isVal.replace(/\.{2,}/g, "."); //只保留第一个. 清除多余的
} else if (isVal.indexOf('.') >= 1) {
alert("isVal.indexOf('.')=" + isVal.indexOf('.'));
this.form.money = isVal.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');//只能输入两个小数
callback(new Error('只能输入两个小数'));
} else {
}
console.log("validatorMoney success...go on ");
callback();
}
el-table scope.row 和 scope.$index,及利用splice方法实现table行的上移下移
elementui tabel组件scope.$inde
的使用
tabel组件的自定义列模板中可以使用scope.row获取当前行的数据,而scope.$index获取的是当前行的数据在数组中的索引(tabel表格绑定的数据是一个数组,数组中每一个对象就相当于一行的数据)
使用如下 splice 方法
通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
array.splice(start, deleteCount, item1, item2,…)
start: 修改的开始位置
deleteCount:要移除或要替换的元素个数。(如果为0,则添加元素)
item1, item2, … :要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。
const months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
// inserts at index 1
console.log(months);
// output: Array ["Jan", "Feb", "March", "April", "June"]
months.splice(4, 1, 'May');
// replaces 1 element at index 4
console.log(months);
// output: Array ["Jan", "Feb", "March", "April", "May"]
months.splice(1, 3);
console.log(months);
// output: Array ["Jan", "May"]
/** 删除按钮操作 */
handleMemberDelete(scope) {
const row = scope.row;
if (row.id) {
// 调用后端删除DB数据
const uid = row.userId ;
this.$modal.confirm('是否确认删除项目人员编号为"' + uid + '"的数据项?').then(() => {
this.loading = true;
return delProjectMember(uid);
}).then(() => {
this.loading = false;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
}).finally(() => {
this.loading = false;
});
}
// 删除空行,
this.materialList.splice(scope.$index, 1);
},
二、vue.config.js中devServer.proxy配置说明及配置正确不生效问题解决
Vue项目devServer.proxy代理配置详解的是一个非常常见的需求,下面这篇文章主要给大家介绍了关于vue.config.js中devServer.proxy配置说明及配置正确不生效问题解决的相关资料,需要的朋友可以参考下
proxy 配置确认、解析
devServer: {
https: true, // 开启https模式
// 配置服务器代理
proxy: {
'/api': { // 匹配访问路径中含有 '/api' 的路径
target: 'http://localhost:3000/', // 测试地址、目标地址
changeOrigin: true,
ws: true, // 是否开启 webSocket 代理
pathRewrite: { // 请求路径重写
'^/api': '', //重写请求路径
},
}
}
},
原因 一
百度最多的解释
- 配置写错了 (解决:复制粘贴上面的实例下去改)
- 路径没有匹配上 (解决:看本文的详解部分)
原因二
这个原因得注意一下
- 方式是给我们开发环境用的 ,其次是我们的请求要被开发服务器接收到,且不能匹配到请求,然后我们的请求就会被代理到配置的URL。
- 注释掉,或者改为本地路径,否则代理不会生效
比如说我之前的全局 http.js 配置文件是这样写的
const http = axios.create({
baseURL: 'http://localhost:3000/',
})
所以不论是 生产 还是 开发 环境下,我的请求都会发送给我们配置的baseURL,而不会走我们的代理!!!。
所以我们得修改一下配置,使我们的生产路径在生产环境下才生效
let baseURL = "/";
if (process.env.NODE_ENV === 'production') {
baseURL = 'http://localhost:3000/';
}
const http = axios.create({
baseURL,
})
这样在开发环境下,我们的 baseURL = “/”, 代理就可以生效了。
注意
- 还有一点就是,即使我们的代理生效了,但是在浏览器请求头中展示的也不是配置的代理地址;
- 所以测的时候得多问问后端请求过去没有,或者自己node搭个简易的服务器看看成没成功;
- 不要一根筋的死盯浏览器的请求头地址。
详解
请求路径必须带有标识!!!
proxy: {
'/api': {
...
}
}
- 用代理首先你得有一个标识,表明你的这个连接要使用代理;
- 不然的话 html css js 这些静态资源都跑去代理。
- 上述key ‘/api’ 就是告诉 node , 我接口用 /api 开头的才使用代理,所以想被代理的接口 都写成 /api/xx/xx
- 出现问题: 请求路径没有 /api ,使用 pathRewrite 解决
pathRewrite
pathRewrite: { // 请求路径重写
'^/api': '', //重写请求路径
},
pathRewrite的key值 ^/api 就是一个正则表达式。
pathRewrite的value值 为替换后的路径。
这里的话就是将匹配成功的地址当做一个字符串,然后执行 js 的 replace 方法,将执行成功的最终结果作为最后的请求路径。
-
比如:
-
我们有一个请求 axios.get(“/api/aa/bb/cc”) ;
-
根据我们这里配置的 proxy, 带有 /api 的请求路径就需要进行代理: 且 /api/aa/bb/cc 路径中含有 /api ,所以该请求就需要代理。
-
将路径当做字符串执行, “/api/aa/bb/cc”.replace(/^/api/, “”)
-
执行结果: /aa/bb/cc
-
最终的请求路径变成了 http://localhost:3000/aa/bb/cc 不含/api;
而 axios.get(“/ee/ff/dd”) 这个请求就不会进行代理,因为匹配不上我们预设的规则 (请求路径没有 /api)
最终的请求路径变成了 http://localhost:3000/ee/ff/dd, 和原路径一致;
又比如说我们的配置为
pathRewrite: { // 请求路径重写
'^/api': '/rewrite', //重写请求路径
}
那么我们的请求 axios.get(“/api/aa/bb/cc”) ;
会执行 “/api/aa/bb/cc”.replace(/^/api/, “/rewrite”);
最终的请求路径变成了 http://localhost:3000/rewrite/aa/bb/cc;
将 /rewrite 替换了开头的/api。
changeOrigin
假设,如果你的前端服务器是 http://localhost:3000,后端是 http://localhost:8082。
那么后端通过 request.getHeader(“Host”) 获取依旧是 http://localhost:3000。
如果你设置了 changeOrigin: true,那么后端通过 request.getHeader(“Host”) 获取才是 http://localhost:8082。代理服务器此时会根据请求的 target 地址修改 Host。
6. 上传组件 <el-upload
关于el-upload上传 携带额外参数,后台接受对应参数的方法
场景:在页面上增加一个上传按钮,并且鼠标悬停在上传按钮的同时,增加消息提示功能,输出提示信息,上传完成,后台接受详细的图片信息。另外支持自定义的上传参数,并且后端能接收到相应的自定义参数。
实现: VUE +SpringBoot
首先前端代码如下:
<el-table-column
label="上传学历材料"
align="center"
prop="xlUrl"
>
<!-- test -->
<template v-slot="scope">
<div class="Educational-materials">
<el-upload
class="avatar-uploader"
:auto-upload="true"
:headers="XlUpload.headers"
:action="
XlUpload.url +
'?updateSupport=' +
XlUpload.updateSupport
"
accept="image/jpeg,image/png"
:show-file-list="false"
:on-success="
(response, file) =>
handleXlSuccess(response, file, scope.row)
"
:before-upload="beforeXlUpload"
:data="multipartFile"
>
<img :src="scope.row.xlUrl" class="avatar" />
</el-upload>
</div>
</template>
</el-table-column>
暂时只需要关注ref、action、data参数。el-upload 其他的属性信息可参照 element官网:
-
action:必选参数,上传的地址 string
-
data:上传时附带的额外参数 object类型–multipartFile
-
ref:主要为了能在下面手动操作upload 的dom元素
-
上面idNo是写死的初始值999999,可以在上传之前 动态获取 idNo的值,
利用文件上传组件中的处理钩子函数
验证:1
验证:2
<el-upload 放在表格 <el-table里,自动上传+反显+预览
<el-table-column
label="上传发票"
align="center"
prop="addrList"
min-width="200px"
>
<template slot-scope="scope">
<el-upload
class="upload-demo"
:action="imgUplod.url + '?updateSupport=' + imgUplod.updateSupport"
:headers="imgUplod.headers"
:on-remove="(file, payfileList) => imgRemove(file, payfileList, scope.row)"
:before-upload="beforeImgUpload"
:on-success="(response, file, payfileList) => imgSuccess(response, file, payfileList, scope.row)"
:file-list="scope.row.addrList"
list-type="picture"
:auto-upload="true"
accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf,.JPG,.JPEG,.PBG,.GIF,.BMP,.PDF"
>
<i class="el-icon-plus avatar-uploader-icon" style="color: #1890ff"></i>
<span style="color: #1890ff">上传发票</span>
</el-upload>
</template>
</el-table-column>
return {
initPayCurrentPage: 1, //当前页码
initPayPageSize: 10, //每页显示数量
payfileList: [],
add_pay_list: [],
pay_form: {
payRecordId: '',
paymentList: [],
},
imgUplod: {
// 是否显示弹出层(用户导入)
open: false,
// 弹出层标题(用户导入)
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: "Bearer " + getToken() },
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/attachment/upload/pic"
},
---
}
method: {
imgSuccess (res, file, fileList, scope) {
if (res.code == 200) {
if (res.data) {
this.$nextTick(() => {
scope.addrList.push(res.data)
})
}
}
},
/** 提交按钮 */
submitForm () {
this.pay_form.paymentList = this.add_pay_list
console.log(this.pay_form);
this.buttonLoading = true;
addFeeClaimPayment(this.pay_form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
}).finally(() => {
this.buttonLoading = false;
});
}
},
}
注: el-upload组件报TypeError: Cannot create property ‘uid‘ on string错误解决方法
记录一个element组件的el-upload组件的一个小坑
今天发现使用el-upload上传文件,上传没有问题,点详情看文件时就会报一个错误,错误如下:
TypeError: Cannot create property ‘uid’ on string ‘https://xxxx.com/upload/20230506/1683346602758.png’
组件代码的模板代码如下:
由于后台返回的addrList 一开始是图片地址url 数组String[],
结果还是报上面那个错误,我这时就有点纳闷了,然后查了下文档
看完恍然大悟,需要的是 对象数组, 不能是单纯的url字符串数组,代码改如下:
this.dataForm.img_url = data.data.img_url ? data.data.img_url.split(',').map(url =>{return {url}}) : [];
完美解决
五、补充一下 <el-upload 关于请求头,增加token参数的问题。
查看官网,可以看到如果想设置上传的请求头,使用headers参数即可。
<el-form-item label="上传模板:" prop="fileId">
<el-upload
ref="exampleUploadRef"
:file-list="fileList"//上传的文件显示列表, 格式如: [{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}]
:action="postUrl"//上传文件的路径
:limit="1"//设置最大允许上传个数
list-type="text"//文件列表的类型,默认是text
accept=".doc,.docx" //接受上传的文件类型
class="avatar-uploader"
:before-remove="beforeRemove"//删除文件之前的钩子,若返回 false 或者返回 Promise 且被 reject,则停止删除停止执行handleRemove事件
:before-upload="beforeUpload"//上传文件之前的钩子,进行判断文件大小和格式是否符合
:on-remove="handleRemove" //文件列表移除文件时的钩子
:name="fileName"//上传的文件字段名
:data="otherParam"//上传时附带的额外参数(如用户信息、业务标识等)
:headers="headers"//设置上传的请求头部
:on-preview="handlePreview"//点击文件列表中已上传的文件时的钩子
:on-exceed="handleExceed" //定义超出限制时的行为(文件超出个数限制时的钩子)
:multiple="false"//是否支持多选文件(默认是否)
:on-success="uploadSuccess"//文件上传成功时的钩子
:on-error="errorMessage"//文件上传失败时的钩子
:on-change="handleChange"//文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
>
<div class="uploadIcon">
<el-icon>
<Plus />
</el-icon>
</div>
<template #tip>
<div class="el-upload__tip text-red">只能上传doc/docx文件</div>
</template>
</el-upload>
</el-form-item>
<script>
export default {
setup() {
const token = store.getters["login_store/token"];
const data = reactive({
fileName: "multipartFiles",//用于指定上传文件的字段名,也就是在后端接收上传文件时需要使用的字段名。在前端发送上传请求时,请求头中会包含该字段名和对应的文件数据,后端就可以通过这个字段名获取到上传的文件数据
headers: {
Authorization: "Bearer " + token //获取token数据
},
otherParam: {
bucketName: "fastabp",
fileType: "personalData",
unzip: false
},
fileList:[],
postUrl :""
})
const beforeRemove = (file, uploadFiles) => {
if(this.status=='view'){
ElMessage({
message: "不允许删除!",
type: "error",
offset: 60
});
return false
}else{
return true
}
};
//文件移除操作
const handleRemove(file, fileList){
data.fileList=fileList//或者data.fileList = []; //清空fileList所有数组
},
//上传文件失败
const errorMessage = (response) => {
return ElMessage({
message: "文件上传失败,请联系管理员",
type: "error",
offset: 60
});
};
//上传文件成功
const uploadSuccess = (response, file, fileList) => {
data.fileList.push({//得到的文件数据转换成 name url方式
name: file.fileOrigName,
url: file.filePreviewUrl
});
};
//文件超出个数限制时的钩子
const handleExceed = (files, fileList) => {};
//点击文件列表中已上传的文件时的钩子,进行下载
const handlePreview = (file) => {
console.log("file", file);
var link = document.createElement("a"); //定义一个a标签
link.download = file.name; //下载后的文件名称
link.href = file.url; //需要生成一个 URL 来实现下载
link.click(); //模拟在按钮上实现一次鼠标点击
window.URL.revokeObjectURL(link.href);
};
const handleChange = (uploadFile, uploadFiles) => {};
//判断上传之前文件的格式
const beforeUpload = (file) => {
const isLt20M = file.size / 1024 / 1024 < 20;
if (!isLt20M) {
ElMessage({
message: "上传图片大小不能超过 20MB!",
type: "error",
offset: 60
});
}
var fileType = file.name.substring(file.name.lastIndexOf(".") + 1);
const isFile = fileType === "doc" || fileType === "docx";
if (!isFile) {
ElMessage({
message: "请选择正确的文件格式",
type: "error",
offset: 60
});
return false;
}
return isLt20M && isFile;
};
onMounted(async () => {
data.postUrl = "http://XXXXX/file/uploadFile";
});
}
}
</script>
<style lang="scss" scoped>
//修改上传图标的样式
.uploadIcon {
border: 1px dashed var(--el-border-color);
border-radius: 5px;
padding: 2px 12px;
}
</style>
token: 一般是前端在第一次登录的时候,由后端生成一个字符串传给前端,前端保存下来,每次请求后台接口的时候,都携带这个token。而后端拦截到请求时,会校验请求参数中的token值。如果校验通过。那就不用再次登录,省去了频繁登录的问题。
前端我是采用cookie保存token的。步骤如下,前三步是先决条件。
第一步、先安装cookie
cnpm i -S js-cookie
第二步、安装完成之后,在需要使用的地方,import引入即可。
import Cookies from 'js-cookie'
第三步、 el-upload 使用token前,先确保我们登录验证时,已经先保存了token
# token 为后端返回的字符串
# tokenKey 为自定义的字符串, 示例:"TOKEN_KEY"
Cookies.set(tokenKey, token)
第四步、el-upload增加:headers参数,如下:
第五步、data中增加参数如下:
其中 **Cookies.get(tokenKey)**就是之前登录时,保存在cookie中的token,tokenKey就是保存时自定义的字符串"TOKEN_KEY"
以上就可以完成,el-upload上传时携带token。
Element:设置el-input宽度 及label 对齐
<el-form-item label="审批人">
<el-col :span="8">
<el-input v-model="formInline.user" placeholder="审批人"></el-input>
</el-col>
</el-form-item>
上方图中的input输入框好像没有对齐,查阅文档可知,Form组件中有个叫label-width的属性,设置成100px看看
<el-form :model="formInline"
:label-position="labelPosition"
:inline="false"
label-width="100px"
>
vue中ref的作用
开发过程中,常常需要动态操作elmentui组件: 下拉框 el-select、Tree、<treeselect、组件问题以及清除选中状态,
一开始通过设置值为空的方式,如下:
// 公司名称change变化
tenantChange (value) {
this.form.tenantId = value.deptId
this.form.tenantName = value.deptName
// todo 清空部门选择
this.form.deptId = ''
this.form.deptName = ''
},
结果出现 unknown ,不理想。
借助 ref选中dom元素、组件,调用其自身方法来清空:
# 以树形下拉框举例:清除下拉框选中项
<el-col :span="8">
<el-form-item
label="部门名称:"
prop="deptName"
v-if="false"
>
<el-input
v-model="form.deptName"
placeholder="请输入部门名称"
/>
</el-form-item>
<el-form-item label="部门名称:" prop="deptId" >
<treeselect
ref="treeselect"
v-model="form.deptId"
:options="deptOptions"
:show-count="true"
placeholder="请选择部门"
@select="deptChange"
clearable
@clear="clearSelectVal"
/>
</el-form-item>
</el-col>
————————————————
## 1. 首先在目标组件上添加 ref="treeselect"
## 2. 在想清空的地方,调用目标组件的clear方法
// 公司名称change变化
tenantChange (value) {
this.form.tenantId = value.deptId
this.form.tenantName = value.deptName
// todo 清空部门选择
// this.form.deptId = ''
// this.form.deptName = ''
// debugger;
// 公司名称变化时,清空部门选择,借助 ref和$refs.
this.$refs.treeselect.clear();
},
// 部门名称change变化
deptChange (value) {
this.form.deptId = value.id;
this.form.deptName = value.label;
},
这里就需要用到 vue中的ref
在Vue中,ref是一个用于在模板中获取DOM元素或组件实例的特殊属性。它可以用来在Vue实例中直接操作DOM元素或组件实例,而无需经过Vue的响应式系统。
ref的作用有以下几个方面:
-
获取DOM元素:通过在DOM元素上添加ref属性,可以在Vue实例中通过$refs对象来访问该DOM元素。这样就可以方便地获取DOM元素的属性、样式或调用DOM元素的方法。例如,可以通过ref来获取表单输入框的值,或者通过ref来操作一个视频播放器的播放、暂停等方法。
-
获取组件实例:在使用Vue的组件化开发时,可以通过ref来获取组件实例。这样就可以直接调用组件实例的方法或访问组件实例的属性。例如,可以通过ref来获取一个弹窗组件的实例,然后在需要的时候调用该组件实例的方法来显示或隐藏弹窗。
-
动态组件:在使用Vue的动态组件时,可以通过ref来控制动态组件的切换。通过给动态组件添加ref属性,然后在Vue实例中通过$refs对象来访问该动态组件,就可以动态地切换不同的组件。
参考一, Vue vue-treeselect组件 清空选中值
参考二,假设我们有一个HelloWorld组件:
<template>
<p>Hello {{ name }}!</p>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
name: {
type: String,
required: true
}
}
}
</script>
我们可以在父组件中使用该组件:
<template>
<p>
<hello-world ref="hello" name="John"></hello-world>
</p>
</template>
<script>
import HelloWorld from './HelloWorld.vue'
export default {
components: {
HelloWorld
},
mounted() {
this.$refs.hello.name = 'Jane'
}
}
</script>
在这个例子中,我们使用ref属性获取到HelloWorld组件的实例,并且可以在mounted生命周期钩子函数中修改其name属性的值。
需要注意的是,ref只在组件的渲染期间有效,即在组件渲染完成后, r e f s 对象才会被填充。 r e f 属性可以在同一个元素上使用多次,此时 refs对象才会被填充。ref属性可以在同一个元素上使用多次,此时 refs对象才会被填充。ref属性可以在同一个元素上使用多次,此时refs对象会变成一个包含了多个属性的对象。
总结一下,ref在Vue中的作用主要是用于获取DOM元素或组件实例,以方便在Vue实例中直接操作DOM或组件。它可以帮助我们更灵活地控制和操作页面上的元素和组件。