工作问题总结

312 阅读4分钟

实习生个人总结

Vue

获取store getters数据 页面动态展示

computed:{
    total:{
        return this.$store['']// 返回仓库值
    }
}
watch:{
// watch 监听computed 动态赋值
    total: function(){ // 不能用箭头函数
        this.pageConfig.total = this.total
    },
    deep: true,
    immediate: true
}

封装组件动态传递样式

<!-- 子组件 -->
<div :style="'text-align:'+style.align+'px'"></div>

prop:{
    style:{}
}

el-table 使用排序sortable排序item项需要绑定prop属性才能生效

判断对象是否为空

// JSON.stringify()
JSON.stringify(obj) == '{}'

// Object.keys(obj)
if(Object.keys(obj).length === 0) //true 为空

合理使用 自定义属性

例子:当input 输入框是循环动态展示的,存在input节点的数量是不可定的,实现回车下一个input框自动获取焦点,并清空下一个input 框的值

// :index 自定义属性 index为for 循环的下标
<el-input v-model="inputPnList[index].inputPn" :index="index"
          @keyup.enter.native="inputEnter(index)" ref="inputs" ></el-input>
          
// 函数
    inputEnter(index) {
      let regu = /^\S{14,18}$/ // 输入框长度最低不能低于14个,不大于18,不能包含空格
      // 获取当前执行的input的 index   item.$attrs.index绑定的自定义属性 跟 传入的index 进行比较
      const currentIndex = this.$refs.inputs.findIndex(item => item.$attrs.index === index);
      if (currentIndex !== -1) {
        const nextIndex = (currentIndex + 1) % this.$refs.inputs.length;
        let inputIndex
        if (regu.test(this.$refs.inputs[currentIndex].value)) {
          if (currentIndex === nextIndex) {
            // 只有一个输入框
            console.log('只有一个输入框');
          } else {
          // 获取到下一个聚焦 的自定义属性index
            inputIndex = this.$refs.inputs[nextIndex].$attrs.index
            // this.$refs.inputs[nextIndex].value = '' // 会报错
            // 清空值
            this.inputPnList[inputIndex].inputPn = ''
            this.$refs.inputs[nextIndex].focus();
          }
        } else {
          this.$message.warning('输入框字符应为14~18,且不能包含空格')
        }
      }
    }

vue使用地图

  • GD原生(不推荐)
  • vue-amap(饿了么封装的插件,推荐使用官方使用文档
  • maptalks官方文档(地图随着滚动条滚动 - 给地图:position: absolute;-父盒子:position: relative;)

高德原生隐藏 label,html自定义文本提示框:操作文本框的display属性进行动态显示和隐藏,marker添加自定义事件:

marker.on('click', 函数名/函数体)

父组件传递子组件class

传class选择器名称即可!!!

09d0f8fddefa0600fec7f2f9ccf67a9.png

el-form 表单验证

// 输入框不能有空格值
// 输入值为空验证函数
noEmptyFun(rule, value, callback) {
    if (/\s/.test(value)) {
        callback(new Error('输入值不能包含空格'))
    } else {
        callback()
    }
},
// 使用
{ validator: this.noEmptyFun, trigger: 'blur' }

// 限制输入框字符大小 blur:输入框失去焦点触发
{ type: 'string', max: 30, message: '字符数最大不得超过30', trigger: 'blur' },

// 限制输入框输入值只能包含英文,数字,中文和-符号
{ pattern: /^[\u4E00-\u9FA5A-Za-z0-9\-]*$/, message: '只能包含中文、英文、数字和 - 符号', trigger:'blur' }

限制el-date-picker取值,不可取未来值

<el-date-picker :picker-options="pickerOptions"></el-date-picker>

// data对象
pickerOptions: {
    disabledDate(time) {
        return time.getTime() > Date.now()
    }
}

原生input checkBox

v-model绑定的数组是checkedIds,当checkbox的选中状态改变时,checkedIds数组会自动更新,如果某个checkbox的id值在checkedIds数组中,则表示该checkbox被选中。

// template 
<input type="checkbox" :value="item.id" class="leftLightCheckBox" v-model="checkBoxIds">

data(){
 return {
     checkBoxIds:[]
 }
}

使用递归组件循环创建菜单

<!-- 父组件 -->
<el-menu>
    <nav-item :routeData="item"  v-for="item in route" :key="item.id"></nav-item>
</el-menu>

<!-- 子组件 navItem -->
<template>
    <div>
    <!-- 判断传入的路由是否包含children且child 大于 0 -->
        <el-submenu v-if="routeData.children && routeData.children.length > 0" :key="routeData.id">
                <template slot="title">菜单名称</template>
                <!-- 使用递归 遍历子路由 -->
                <nav-item v-for="item of routerData.children"
                          :routeData = "item"
                          :key = "routeData.path">
                </nav-item>
        </el-submenu>
        <el-menu-item v-else :key="routeData.path" :index="routeData.path">
            <router-link>菜单名</router-link>
        </el-menu-item>
    </div>
</template>
<script>
export default{
    name:"navItem", // 组件名
    props:{
        routeData:{
            type:Object,
            require:true,
        }
    }
}
</script>

el-form 搭配 el-upload

data() {
    // 自定义验证规则 判断上传文件
     const validateUpload = (rule, value, callback) => {
         if (this.cartUpdateForm.file.length > 0) {
             callback();                    
         } else {
             callback(new Error('请选择要上传的文件'));
         }
     }
     return {
      cartUpdateRules:{// 绑定的规则
        file: [
          { required: true, validator: validateUpload, trigger: 'change' }
        ]
      },
      cartUpdateForm:{ // 表单
        file: []
      },
     }
}

methods: {
    beforeUpload(file) {
      // 在上传之前的处理,例如限制文件大小和类型
      if (file.type !== 'text/plain') {
        this.$Message.error('请上传 .txt 格式的文件');
      } else {
       // 赋值表单值
        this.cartUpdateForm.file = [file]
      }
      return false
    },
    this.$refs.cartUpdateForm.validate((valid) => {
        if (valid) {
     }
    
}

JS

指定位置插入字符串

// soucre:原字符串,start:插入的位置,newStr:插入的字符串
function insertStr(soure, start, newStr){   
   return soure.slice(0, start) + newStr + soure.slice(start);
}

引入公共文件代码 export default方式的文件

// 公共文件 utils.js
export default{
    changeArr: () => {
        //// 实现代码
    }
}

// 引入
import utils from '文件路径'

// 使用
utils.changeArr()

引入公共文件代码 export function多个导出

export function getAAA(){
    return request.get('')
}

// 获得客户审核详情
export function setAAA(){
    return request.get('')
}
...
// 引入
import { getAAA,setAAA } from '文件'
import a from '文件'
import {a} from '文件'
前者会将整个文件导入,而后者只会导入a函数

切换tb镜像

npm config set registry http://registry.npm.taobao.org
// 使用:正常 npm 就行 已经切换下载源

模板字符串使用图片,添加点击事件

data(){
    return { img:require(路径) }
},
mounted(){
   // 将方法挂载到window (不挂载访问不了方法,访问的是window.clearLabel方法)
   // 因为vue的代码分编译前和编译后 动态添加的属于编译后
    window.clearLabel = this.clearLabel
},
methods:{
    clearLabel(){ //代码块 }
}
`<img src="${this.img}" class="icon-img" onclick="clearLabel()">`

封装全局防抖/节流函数

export default {
// 防抖 结束调用函数后 delay 时间过后再触发函数
  debounce (func, delay) {
    let timer = null;

    return function () {
      const context = this;
      const args = arguments;

      clearTimeout(timer);
      timer = setTimeout(() => {
        console.log(timer);
        func.apply(context, args);
      }, delay);
    }
  },
  // 节流 delay 时间内只执行一次
  throttle (func, delay) {
    let lastTime = 0
    return function(...args){
        let now = Date.now(),that = this // 获取当前时间戳
        if(now - lastTime >= delay){
            func.apply(that,args) // 调用函数
            lastTime = now; // 重置lastTime
        }
    }
  }
}

使用全局防抖/节流函数

import utils from '@/js/utils.js'

getSearch:utils.debounce(() => { //调用 },300)

getSearch:utils.throttle(() => { //调用 },300)

CSS

元素垂直水平居中

//  flex 布局
.parentBox {
    display:flex;
    justify-content: center;
    align-items: center;
}
// 定位 + 定位
.parentBox {
    position: relative;
}
.childBox {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

el-table 修改斑马纹 和 鼠标移入效果

// 修改奇数行斑马纹颜色
.el-table__body tr.el-table__row--striped td{
	background: @defaultBalackColor !important;
}
// 鼠标移入效果
.el-table__body .el-table__row.hover-row td{
	background-color: @hoverBlackColor !important;
}

el-table 自适应高度

方法一

// html
<div class="table-box">
    <el-table height="100%"></el-table>
</div>
// css
.table-box {
    height: 100%; / flex: 1; 使用其中一个即可
    position: relative;
    /deep/.el-table {
        position: absolute;
   }
}

方法二

// html
<div :style="{height:transferHeight+'px'}">
    <el-table height="100%"></el-table>
</div>

// js
data(){
    // 外盒高度 : 可视区高度 - 其他占位高度
    transferHeight: window.innerHeight-this.otherTotalHeight,
    // 可视区高度
    screenHeight: window.innerHeight,
    // 其他占位高度
    otherTotalHeight: 48+135,
},
watch:{
    // 监听可视区高度 从而改变table外盒的高度
    screenHeight(val){
        this.screenHeight = val;
        this.transferHeight = this.screenHeight-this.otherTotalHeight;
    }
}

修改el-table表头,行样式

<el-table :cell-style="{padding:0,backgroundColor:'#2B2D34',color:'#D0D0D0'}"
          :header-cell-style="{background:'red',color:'#FFFFFF'}">
</el-table>

通过flex 布局 + position 实现

解决element table 宽高自适应 - 掘金 (juejin.cn)

修改滚动条样式

CSDN MDN

element 表格有固定列时滚动不齐有迟滞性

博客园

image.png

网络

将blob数据类型转为json数据

let blob = new Blob([JSON.stringify({name: '张三', age: 18}).encode('utf-8')], {type: 'application/json;charset=UTF-8'}); 
// 创建一个 FileReader 对象 
let reader = new FileReader(); 
// 当 FileReader 完成读取时
reader.onload = function() { 
// 将读取结果保存到 content 变量中 
let content = reader.result; 
// 解析 JSON 字符串 
let data = JSON.parse(content); 
console.log(data); // 输出:{name: "张三", age: 18} 
}; 
// 开始读取 Blob 对象,并指定编码方式为 UTF-8 
reader.readAsText(blob, 'utf-8');

上传formData 类型给后端

// 配置请求头
axios({
      method: 'post',
      url: uri,
      data: data,
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
// 试用 FormData对象
let formData = new FormData()
formData.append('file', pdfBlob)
formData.append('path', path)
// 调用接口
this.fileUpload(formData)

对后端返回的文件流走下载流程

const disposition = res.headers['content-disposition'];  
let fileName = disposition.substring(disposition.indexOf('filename=') + 9, disposition.length); 

fileName = decodeURI(escape(fileName));  
const content = res.data;  
let url = window.URL.createObjectURL(new Blob([content])); // 根据返回的文件流生成 路径
let link = document.createElement("a");// 动态创建 a标签
link.style.display = "none";// 隐藏创建的a标签
link.href = url;// 赋值 a标签 的href属性
link.setAttribute("download", fileName);// 设置a标签 download 属性
document.body.appendChild(link);  // 添加到页面
link.click(); // 触发a 标签下载事件
this.$message.success("下载中,请稍等");  
window.URL.revokeObjectURL(link.href);  // 释放 通过 `URL.createObjectURL()` 创建的 URL 对象
document.body.removeChild(link); // 清除 a 标签

get 传递 数组

axios get 传递数组的参数默认操作诡异,会转换成这种格式arr[]=value

参考文献

image.png

// 方法一
let arr = [1,2,3]
axios({url: '/user/',
    params: {
        id: arr + '',    // 重点在这数组加上'',即可变为 "1,2,3"
    }
}
所形成的url为: /user?id=1,2,3    等价于 /user?id=1&id=2&id=3
// 方法二  Qs.stringify

// qs库应该是axios安装时会自带的

const qs = require('qs');

axios.get(url, {
    params:{
        arr: [1,2,3]
    },
    paramsSerializer: function(params) {
        return Qs.stringify(params, {arrayFormat: 'repeat'})
    }
}) // 为'id=1&id=2&id=3'

中断网络请求

AbortController 接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求。 AbortController - Web API 接口参考