vue自身和其封装组件element

目录


文章参考: 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 分别是什么意思

  1. @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>

在这里插入图片描述

  1. @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宽度来进行换行。

    1. 在具体的el-form-item中设置label-width,

    2. 也可以为整个表单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 详解

  1. 背景
    element的布局方式与bootstrap原理是一样的,将网页划分成若干行,然后每行等分为若干列,基于这样的方式进行布局,形象的成为栅栏布局。
    区别是element可将每行划分为24个分栏,而bootstrap是划分为12个分栏,从使用角度,还是24个分栏更加精细。

  2. 分栏布局
    首先每行使用标签标识,然后每行内的列使用标识,至于每列整行的宽度比例,则使用: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>

在电脑上效果如下:
在这里插入图片描述
在手机上效果如下:
在这里插入图片描述
注意具体的尺寸属性为:

属性 使用说明

  1. 小结
    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的作用有以下几个方面:

  1. 获取DOM元素:通过在DOM元素上添加ref属性,可以在Vue实例中通过$refs对象来访问该DOM元素。这样就可以方便地获取DOM元素的属性、样式或调用DOM元素的方法。例如,可以通过ref来获取表单输入框的值,或者通过ref来操作一个视频播放器的播放、暂停等方法。

  2. 获取组件实例:在使用Vue的组件化开发时,可以通过ref来获取组件实例。这样就可以直接调用组件实例的方法或访问组件实例的属性。例如,可以通过ref来获取一个弹窗组件的实例,然后在需要的时候调用该组件实例的方法来显示或隐藏弹窗。

  3. 动态组件:在使用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或组件。它可以帮助我们更灵活地控制和操作页面上的元素和组件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值