开发过程中踩到的问题集

276 阅读4分钟

vue3踩坑

引入vue-router

几个细节:

  • npm install vue-router@next,或者4.0.6版本,不能直接npm install vue-router

  • 需要从vue-router里面引入两个函数createRouter,createWebHistory,之前的我们直接引入Router

vue3:
import { createRouter,createWebHistory} from "vue-router";
const router = createRouter({
    history: createWebHistory(),
    routes
});

vue2:
import { Router} from "vue-router";
const router = new Router({
    routes
})
  • 组件必须要有.vue后缀,要不然会找不到文件(可以是vite的原因)

  • @这个东西好像也没用,会找不到文件

  • 注意是history不是model,还有就是createWebHistory()记得加上()

react 改变数组

cloud.tencent.com/developer/a… 数组不能用push

react hook中的setTodos方法传入的数组会对原来的数据进行覆盖,这里需要注意传入的数组和原先的数组不能指向同一内存地址,也就是或setTodos方法的参数只能是todos的副本,而不能是引用,如果是引用则不会更新。

setTodos([
  ...todos,
  {
    text: "Learn Hooks"
  }
]);

echart 横坐标在ios不会显示,因为ios 处理时间new Dates(time),time不能是'-',可改成'/'

new Date(time..replace(/-/g,"/")).getTime()

页面两个不同状体切换,会出现闪一下,可以改成路由的方式

react

 if(this.state.selectedFieldId.includes(item.field)){
        let index = this.state.selectedFieldId.indexOf(item.field)
        
        this.state.selectedField.splice(index,1)
        this.state.selectedFieldId.splice(index,1)
        this.setState({
          selectedField: this.state.selectedField,
          selectedFieldId: this.state.selectedFieldId
        });
        console.log('index:',index, this.state.selectedFieldId)
    } else {
        this.state.selectedField.push(item)
        this.state.selectedFieldId.push(item.field)
        this.setState({
          selectedField: this.state.selectedField,
          selectedFieldId:  this.state.selectedFieldId
          // selectedField: [...this.state.selectedField,item],
          // selectedFieldId: [...this.state.selectedFieldId,item.field]
        });
      console.log( this.state.selectedFieldId)
    } 

echart 混合图,需要加上zindex

ant design TimePicker 默认点击才能滚动,浮动层默认是以body进行定位的

Modal层滚动的时候body整体页面并没有滚动,所以导致浮动层不会跟随滚动. 解决方法就是使用TimePicker中的getPopupContainer属性来改变浮动层绑定的元素,Select和DatePicker同理。

TimePicker改成不需要点击就出现滚动条

.ant-picker-time-panel-column{
    overflow-y: auto;
}

同时在移动端TimePicker下面的操作按钮没有居中对齐,手动设置

.ant-picker-ranges{
    display: flex;
    justify-content: space-between;
    align-items: center;
}

创建全局组件

 let div = document.createElement('div');
 document.body.appendChild(div);

创建一个div,插到body里,再通过ReactDOM,将属性和你要写的组件样子传入,如

ReactDOM.render(React.createElement(Loading, props), div); 最后在你不需要它的时候,摧毁它,如

ReactDOM.unmountComponentAtNode(div);
document.body.removeChild(div);

el-table 树状结构 设置默认展开行

elementUi table的默认展开问题-CSDN社区

el-table 树状结构需要设置左对齐,不然看不清层级结构

treeselect组件 远程搜索 编辑 反显内容 unknown的问题,设置默认值,并且定义hack 布尔值重新渲染

this.backFillOptions = [ 
{ id: res.companyInfo.companyName, 
label: res.companyInfo.companyName, 
} ] 
this.hack =! this.hack


<treeselect 
v-if="hack" 
key="t1" 
v-model="companyName" 
:async="true" 
searchPromptText="输入搜索" 
:default-options="backFillOptions" 
:load-options="loadOptions" 
placeholder="输入搜索再选择事业部名称" 
@select="changeCompanyName" /> 

<treeselect 
v-else 
key="t2"
v-model="companyName" 
:async="true" 
searchPromptText="输入搜索" 
:default-options="backFillOptions" 
:load-options="loadOptions" 
placeholder="输入搜索再选择事业部名称" 
@select="changeCompanyName" />

vue 对象的属性没有初始化,赋值不会响应(不会被监听)

el-upload 自定义上传

  1. 无提交按钮::http-request="httpRequest" 自定义httpRequest函数

  2. :auto-upload="false" 有提交按钮:在提交按钮时触发自定义请求接口

上传时候设置FormData,但是打印为{},并且直接使用axios不能成功,使用axios拦截的公共接口才执行通

直接打印是看不到的,要用FormData的get()和getAll()方法

同时校验多个子表单,任何一个没填都显示一个错误,使用自定义校验

var checkWater = (rule, value, callback) => {
  let waterMid = this.$refs.waterMid.value;
  let waterUpper = this.$refs.waterUpper.value;
  if( value && waterMid && waterUpper ){
    callback()
  } else if(!this.form.waterDifference) {
    callback()
  }else {
    callback(new Error('请填写阈值范围'))
  } 
}

el-select联动,不会清空错误,要手动clearValidate;并且被联动的选不中,需要$forceUpdate

this.$refs.form.clearValidate('departmentId')

el-tree只能在同级拖拽,使用:allow-drop = allowDrop

el-date-time-picker 设定不可选时间范围精确到秒,需要加selectableRange

let str = '12:12:12'
let pickOptions = {
   disableDate: (time) =>{
        return time.getTime() > Date.now()
    },
    selectableRange: str + ' - 23:59:59'  
}
可以设置str,str就是临界的开始位置,它之前的值就不能选

下载文件

后端返回一堆乱码,前端需要设置responseType : 'blob'

element el-select 数据太多导致卡顿

解决方案:采用懒加载

<template>
<div class="flex-between-center edit-row" >
    <el-select v-model="choose" placeholder="请选择" filterable
        v-el-select-loadmore:rangeNumber="loadMore(rangeNumber)" size="small" 
        @change="handleMachineChange"
        style="width: 280px"
        :filter-method="filterMethod">
        <el-option
        v-for="(item, index) in finalList" 
        :label="`${item.machineNo} (${item.machineName})`" 
        :value="item.machineNo" 
        :key="index">
        </el-option>
    </el-select>
</div>  
</template>
<script>
export default {
    // model: {
    //     prop: 'choose',
    //     event: 'change'
    // },

    props:{
        machineList: {
            type: Array,
            default: ()=>[]
        },
        value: {
            type: String,
            default: ''
        }
    }, 
    watch: {
        value(newVal){
            this.choose = newVal
        },
        choose(newVal,oldVal){
            this.$emit("input", this.choose)
        },
        // 执行2次,是因为请求了2次。  machineList有上千条
        machineList:{
            handler(){
                this.currentList = []
                // 深拷贝
                this.currentList = this.machineList.slice(0)
                this.handleList()
            },
            immediate: true ,
            deep: true
        },

    },
  
    directives: {
        'el-select-loadmore':{
            bind(el, binding){
                const selectDom = el.querySelector(".el-select-dropdown .el-select-dropdown__wrap");
                if(selectDom){
                    selectDom.addEventListener("scroll", function(){
                    // const condition = this.scrollHeight - this.scrollTop <= this.clientHeight;
                    //    不加条件才对,有待研究
                        // if(condition) binding.value()
                        binding.value()
                    })
                } 
            }
        }
    },
    computed: {
        finalList(){
            return this.currentList.slice(0, this.rangeNumber)
        }
    },
    data(){
        return {
            currentList: [],
            rangeNumber: 10,
            choose: this.value
        }
    },
    mounted(){// 切换的时候,这里不执行},
    methods:{
        filterMethod(val){
            if(val){
                this.currentList = this.machineList.filter((item)=>{
                    if(item.machineNo.includes(val) || item.machineName.includes(val)){
                        return item
                    }
                })
            }else{
                this.currentList = this.machineList
            }
        },
        handleList(){     
            let index0 = -1 
            let item0 = this.currentList.find((item, index)=>{
                if(item.machineNo == this.choose) {
                    index0 = index
                }
                return item.machineNo == this.choose
            })
            // 修改:在展示前,循环总数据把选中的放在list的最前面
            if(index0 > 0){
                this.currentList.splice(index0,1)
                this.currentList.splice(0,0, item0)
            } 
        },
        loadMore(n){
            return () => this.rangeNumber +=5
        },
        handleMachineChange(e){
            this.$emit('change',this.choose)
        }
    }
}
</script>

el-input监听paste事件

el-input v-model="val" placeholder="请输入内容" @paste.native.capture.prevent="handlePaste"/>

//获取粘贴的值
let clip = e.clipboardData.getData('Text') 
this.val = clip

map遍历异步

 async handleQrCode (ids) {
 ...
     let promises = list.map(async (item, i) => {
       return {
         ...item,
         equipQrcodePath: (images[i]),
         equipQrcodeFullPath: await formatFileUrl(images[i]),
       } 
      })
     this.qrCodeEquips = await Promise.all(promises);
 }

forEach遍历异步换成for 循环遍历异步

 async handleQrCode (ids) {
 ...
  if(files && files.length>0){
    for(let item of files) {
       item.fullPath = await formatFileUrl(item.path);
     }
   }
 }

在form种使用button,必须设置type=button,不然会跳走

使用position:relative 和 absolute实现相对于父元素的FIXED定位的实现

想让特定子元素相对于父元素"fixed"定位,也就是说,剩余的子元素不定位。那可以分开来想,如果添加一个祖先元素assistor,有两个祖先元素,一个用于辅助定位,一个用于包裹不定位的内容。

只要assistor和parent一样大,看起来就像是子元素child相对于父元素parent固定定位了。

<div class="assistor">
  <div class="parent">
    <div class="child"></div>
    <div class="placeholder"></div>
  </div>
</div>
.assistor {
  position: relative; /*关键点*/
  display: block;
  width: 500px;
  height: 300px;
  margin: 100px auto 0 auto;
  background-color: #ddd;
}
.parent {
  width: 500px;
  height: 300px;
  background-color: #888;
  overflow: auto; /*关键点*/
}
.child {
  position: absolute; /*关键点*/
  width: 120px;
  height: 120px;
  margin: 100px 50px;
  background-color: #333;
}
.placeholder {
  width: 1000px;
  height: 1000px;
}

小程序踩坑

小程序踩坑记