整理Vue项目开发过程中遇到的常见问题2

本文整理了Vue项目开发过程中的常见问题,包括表格事件处理、数据定位、合计行统计、防止快速双击提交、文件下载、上传进度、消息提示自定义、事件监听、npm错误、级联选择器问题、电话号码呼叫、级联下拉菜单滚动、元素滚动显隐、table scoped slot使用、组件数据更新、浏览器调试和input文件上传等,并提供了相应的解决方案。

51 表格当选择项发生变化事件selection-change,翻页 搜索事件也会触发它,要改成手动事件

    // 按人员授权选中事件
    handleSelectWaitChoose (selection, row) {
      const index = this.tableData2.findIndex(item => item.id === row.id)
      if (~index) {
        this.tableData2 = this.tableData2.filter(item => item.id !== row.id)
      } else {
        this.tableData2.push(row)
      }
      this.userIds = this.tableData2.map(v => v.id)
    },
    // 按人员授权全部选中事件
    handleSelectWaitChooseAll (selection, flag) {
      if (selection && selection.length) {
        selection.forEach(item => {
          if (this.tableData2.findIndex(ele => ele.id === item.id) === -1) {
            this.tableData2.push(item)
          }
        })
      } else {
        this.tableData.forEach(item => {
          const index = this.tableData2.findIndex(ele => ele.id === item.id)
          if (index !== -1) {
            this.tableData2.splice(index, 1)
          }
        })
      }
      this.userIds = this.tableData2.map(v => v.id)
    },

52 表格el-table添加数据后自动定位到行前行尾, 注意别忘了 el-table增加ref属性!!!

// 增加一行数据, 限制20行
addRows (obj) {
    const data = JSON.parse(JSON.stringify(obj))
    this.tableData.push(data)
    if (this.tableData.length > 19) {
        this.isAddList = false;
    }
    this.$nextTick(() => {
        //滚动到最后一行
        this.$refs.tableData.bodyWrapper.scrollTop = this.$refs.tableData.bodyWrapper.scrollHeight 
    })
}
this.$refs.tableData.bodyWrapper.scrollTop = 0 //滚动到第一行

53 表格el-table 表尾合计行数据统计功能,表格列必需要设置prop属性,否则不起作用,因为show-summary属性不支持自定义列模板

  //汇总求和
    getSummaries (param) {
      const { columns, data } = param;
      const sums = [];
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = this.$t('baseCommon.totalNumber');
          return;
        }
        const values = data.map(item => Number(item[column.property]));
        if (!values.every(value => isNaN(value)) && (columns[index].property === 'orderedQty')) {
          sums[index] = values.reduce((prev, curr) => {
            const value = Number(curr);
            if (!isNaN(value)) {
              return prev + curr;
            } else {
              return prev;
            }
          }, 0);
          sums[index] += '';
        } else if (columns[index].property === 'sku') {
          const sku = this.tableData.filter(v => v.sku).map(v => v.sku)
          const newSKU = new Set(sku)
          const newArray = Array.from(newSKU)
          sums[index] = newArray.length;
        } else {
          sums[index] = '';
        }

      });
      return sums;
    }

54 vue中阻止快速点击两次提交按钮调两次接口,解决办法: 增加防抖功能

1-先声明一个变量isDisabled: false来控制按钮是否禁用
2-触发请求时设置isDisabled= true
3-请求响应成功后设置isDisabled= false

 55 vue 下载模板需要在post()里面设置响应类型参数{responseType: 'blob'},后台接口响应是数据流,不然下载下来的excell文件会出现乱码

// 下载样板
handleDemo() {
    const query = { ...this.form }
    this.$httpExt().post(this.$api.outbound.downloadTemplate, query, {
        responseType: 'blob'
    }).then(res => {
        if (res.type === 'application/json') {
            this.$message({ message: '暂无导出数据', type: "error" })
            return false
        }
        downloadExcel(res, 'template')
    })
}

//下载封装
export function downloadExcel (res, fileName) {
    const blob = new Blob([res], { type: 'application/vnd.ms-excel;' })
    // 判断是不是ie的浏览器
    if (!!window.ActiveXObject || 'ActiveXObject' in window) {
        window.navigator.msSaveOrOpenBlob(blob, fileName)
    } else {
        const link = document.createElement('a')
        const href = window.URL.createObjectURL(blob)
        link.href = href
        link.download = fileName + new Date().getTime() + '.xls'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(href)
    }
}

 56 vue el-upload组件 批量导入自定义httpRequest方法不会显示上传文件进度条

1 自定义httpRequest方法, 覆盖默认的上传行为,可以自定义上传的实现
2 自定义不会显示上传文件进度条,手动上传与自动上传只能出现一种状态
3 开启自动上传功能时,手动上传会失效
4 开启手动上传功能时,前提要先关闭自动上传功

//自定义上传
async httpRequest(params) {
    let fd = new FormData();
    fd.append("file", params.file);
    fd.append("FileName", params.file.name)
    var options = {  // 设置axios的参数
        headers: {
            'Content-Type': 'multipart/form-data'
        }
    }
    const url = this.$api.outbound.uploadTemplate
    try {
        const res = await this.$httpExt().post(url, fd, options)
        if (res.code === 0) {
            this.$emit('closeDialog', 'dialogLogisticStatusVisible')
            this.$parent.$parent.handleSearch()
            this.$message({ type: 'success', message: this.$t('ABGeneral.isco.importSucc') + res.total + this.$t('ABGeneral.isco.theData') })
        } else {
            this.$refs.upload.clearFiles();
            const h = this.$createElement;
            if (res.data) {
                this.$message({
                    type: 'error',
                    message: h('ul', { style: 'padding:0;margin:0' }, res.data.results.map(v => {
                        return h('li', { style: 'color: #f56c6c;fontSize:12px;' }, this.$t('ABGeneral.isco.the') + v.lineNum + this.$t('ABGeneral.isco.row') + ' - ' + v.errMsg)
                    }))
                });
            } else {
                this.$message({ type: 'error', message: res.msg })
            }
        }
    } catch (error) {
        console.log(22222, error);
    }
}

//上传之前筛选文件类型和大小
handleBeforeUpload(file) {
    const size = file.size / 1024 / 1024
    const isExcel = file.name.includes('.xlsx') || file.name.includes('.xls')
    if (!isExcel) {
        this.$message({ message: this.$t('ABGeneral.isco.isXls'), type: "error" })
        return false
    } else if (size > 1) {
        this.$message({ message: '文件不能超过1M', type: "error" })
        return false
    }
}

 57 渲染函数 & JSX Message 消息提示自定义

const h = this.$createElement;

this.$message({

    type: 'error',

    message: h('ul', { style: 'padding:0;margin:0' }, res.data.results.map(v => {

        return h('li', { style: 'color: #f56c6c;fontSize:12px;' }, this.$t('ABGeneral.isco.the') + v.lineNum + this.$t('ABGeneral.isco.row') + ' - ' + v.errMsg)

    }))

});

58 vue中@keyup.enter没有作用 

注意事项:

1.首先需要知道的是@click和@keyup是不能在一个元素上同时使用的;

2.当我们在项目中引入了第三方组件库时,发现@keyup.enter没有作用时,这时改成@keyup.enter.native就可以啦

eg: <el-input v-model="password" placeholder="请输入密码" @keyup.enter.native="search()"></el-input>

 59 npm 报错: npm ERR Unexpected token in JSON at position 0 while parsing near解决方案

解决方法

删除根目录下 package-lock.json 文件。

npm cache clear --force(试过无效)

 60 批量渲染数据可编辑表格页面直接卡顿,接口响应数据很快,比如入库批量导入一次导入1000的数据

分析原因

由于需要渲染很多的table数据,同时每条table都有嵌套autocomplete,input和select组件,导致特别卡

解决方法

与产品讨论之后,将来需要支持最多1000条数据的导入,所以决定针对导入的数据,不再提供编辑功能

 61 级联选择器组件输入框回显内容空白

分析原因

value id可能重复,参数格式不对

解决方法

1 - 排查树形数据结构中的value值是否是唯一的? 比如一级添加all节点与二级添加all节点,新手很容易设置value是重复的值这样就导致显示有问题

2 - 排查参数格式是否正确?比如要求是数组参数,实际传了字符串

62 点击网页中的电话号码,实现“呼叫功能”

分析原因

< a   href = " tell : //15823456789 " > 拨打电话:15823456789 </a>

 63 级联选择器下拉菜单滚动时不隐藏,下拉菜单pop会自动从顶部或底部弹出问题

分析原因

第三方插件BUG

解决方法

if (this.popElement && this.popElement.offsetHeight) {

const cascaderBrand = this.$refs.cascaderBrand as any

cascaderBrand.dropDownVisible = false

}

.el-popper.el-cascader__dropdown {

position: absolute !important;

transform: translateY(0) !important;

top: 40px !important;

}

<el-cascader
    v-if="categoryList"
    ref="cascaderBrand"
    v-model="selectedBrand"
    :options="categoryList"
    :placeholder="this.$t('brandDirectory.choose')"
    :props="{
      expandTrigger: 'hover',
      value: 'id',
      label: 'categoryName',
      children: 'childrenCategory'
    }"
    :show-all-levels="false"
    :append-to-body="false"
    :popper-options="{
      boundariesElement: 'viewport'
    }"
    @change="handleChange"
  ></el-cascader>

64 元素滚动时显隐藏出现缝隙以及显示底层内容问题,视觉衔接效果不良好

解决办法

当元素固定时,在中间层放一个空div用背景覆盖最底下的内容

<section class="">内容</section>

<div v-if="isFixed" class="white-background-placeholder"></div>

<div v-if="isFixed" class="search-placeholder"></div> 

65 在el-table scopte slot 里面读取不到this.$ref[xxxx] 打印一直显示undefined

解决办法

slot 内容需要提取到单独的组件里面ref属性才能打印并且会遍历节点

抓取省略号状态----- dom节点内容高度<节点滚动高度,代表会显示省略号,反之就不显示 

      <el-table-column min-width="120" :label="logReportI18.categories">
        <template slot-scope="scope">
          <el-tooltip
            class="item"
            effect="dark"
            :content="scope.row.category_access"
            placement="top-start"
          >
            <!-- slot 里面ref属性要加延时才能取到dom节点, 并且不会遍历节点 -->
            <span class="category" ref="content">
              {{ scope.row.category_access }}
            </span>
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column min-width="120" :label="logReportI18.categories">
        <template slot-scope="scope">
          <!-- slot 内容需要提取到单独的组件里面ref属性才能打印并且会遍历节点 -->
          <baseToolTip :data="scope.row.category_access"></baseToolTip>
        </template>
      </el-table-column>
<!-- baseToolTip组件 -->
<template>
  <el-tooltip
    class="item"
    effect="dark"
    :content="data"
    placement="top-start"
    :disabled="hasThreeDot"
  >
    <span class="category" ref="content">
      {{ data }}
    </span>
  </el-tooltip>
</template>
<script lang="ts">
import Component from "vue-class-component"
import { Prop, Vue } from "vue-property-decorator"
import { Watch } from "vue-property-decorator"

@Component({ name: "BasePopover" })
export default class BasePopover extends Vue {
  @Prop() data!: {}
  hasThreeDot = false
  mounted() {
    this._calHeight()
  }

  @Watch("data")
  dataChange() {
    this.$nextTick(() => {
      this._calHeight()
    })
  }

  _calHeight() {
    if (
      this.$refs.content &&
      (this.$refs.content as HTMLElement).clientHeight <
        (this.$refs.content as HTMLElement).scrollHeight
    ) {
      this.hasThreeDot = false
    } else {
      this.hasThreeDot = true
    }
  }
}
</script>
<style lang="scss" scoped>
.category {
  width: 80%;
  @include ellipsisLn(2);
  word-break: keep-all;
  text-align: left;
}
</style>

66 vue2.0就近调用同一组件 数据视图没有更新, 通过vue-devtools调试工具可以看出数据没有变化

问题描述---在开发时使用v-if处理同一组件时会出现数据视图没有更新的情况,那是因为就近的同一组件的元素会被复用
具体可以参考 https://cn.vuejs.org/v2/guide/conditional.html#用-key-管理可复用的元素

解决办法--- 在动态组件加上Key属性

    <transition name="component">
      <component
        v-if="curEditData.type !== ''"
        :key="curEditData.type"
        class="component"
        :componentData="componentData"
        :moduleErrors="curComponentError && curComponentError.moduleErrors"
        :is="curComponentName"
        @saveAndClose="_handleSaveAndClose"
      />
    </transition>

67 浏览器调试工具查看/修改placeholder值

1.谷歌浏览器设置如下:打开开发者工具,点击右上角三个“.”,进入Settings;

2.找到Preferences——Elements,勾选Show user agent shadow DOM

3.然后在元素的Styles就能修改placeholder的颜色

input.el-input__inner {
  font-family: "Franklin Gothic Book";
}

@mixin place-holder-color {
  color: rgba(0, 0, 0, 0.5) !important;
  font-family: "Franklin Gothic Book";
}
input,textarea {
  &::placeholder {
    @include place-holder-color();
  }
  &::-webkit-input-placeholder {
    @include place-holder-color();
  }
  &:-moz-placeholder {
    @include place-holder-color();
  }
  &::-moz-placeholder {
    @include place-holder-color();
  }
  &:-ms-input-placeholder {
    @include place-holder-color();
  }
}

68 input标签上传文件时无法重复触发change事件

通过e.target.value,给该input的value属性赋空:每次事件触发之后,就立即赋空。相当于是清除了缓存,onchange绑定的函数就可以重复触发了。

  handleChange(e: any) {
    const file = e.target.files[0]
    this.$emit("change", file)
    e.target.value = ""
  }

ToDoList

axios 错误提示 请求200也走catch不能全局做错误提示,导致页面中每个接口都要写错误提示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值