Vue项目中的问题汇总(持续更新中)


1.vue循环span标签产生了间隙

代码如下:

<template>
    <div class="box">
        <span v-for="(item,index) in items" ::key="index">{{ item }}</span>
        <span>修改</span>
        <span>删除</span>
    </div>
</template>
<script>
export default {
    data() {
        return {
            items: ['审批', '拒绝审批', '核销']
        }
    },
}
</script>
<style lang="less">
.box{
    span{
        display:inline-block;
        width:40px;
        height:20px
    }
}
</style>

原因和解决方法:

如果有display:inline或是display:inline-block的元素相邻,并且它们之间有强制回车换行,那么就会自动产生一段间隙。

可以在这些元素的父元素上设置font-size:0;,就可以消除换行带来的间隙。

这种情况下,如果代码不换行,就不会产生间隙。

2.ElementUI的表单resetFields()方法无法清空

为每个 form-item 加上 prop 属性(大部分的问题就是出在这

弹框时:

记得使用this.$nextTick(()=>{})

3.Vue3报错: <router-view> can no longer be used directly inside <transition> or <keep-alive>

最近在学习vue3,在搭建项目的时候,使用 keep-alive 的包裹 router-view 会有警告信息

<router-view> can no longer be used directly inside <transition> or <keep-alive>

代码如下:

<transition
  :name="!noTransition ? 'fade-transform' : ''"
  :mode="!noTransition ? 'out-in' : ''"
>
    <keep-alive :include="cachedViews">
        <router-view :key="key" />
    </keep-alive>
</transition>

提示以下警告

[Vue Router warn]: <router-view> can no longer be used directly inside <transition> or <keep-alive>.
Use slot props instead:

<router-view v-slot="{ Component }">
    <transition>
        <component :is="Component" />
    </transition>
</router-view>

从警告信息可以看出是路由包裹出现了问题,现做如下调整

<router-view :key="key" v-slot="{ Component }">
    <transition
        :name="!noTransition ? 'fade-transform' : ''"
        :mode="!noTransition ? 'out-in' : ''"
    >
        <keep-alive :include="cachedViews">
        <component :is="Component"></component>
        </keep-alive>
    </transition>
</router-view>

4.Vue3 reactive不能直接赋值的解决方法

1. 改为ref定义

const arr= ref([])
arr.value = [1, 2, 3]

2. push新增数据

const arr = reactive([])
arr.push(...[1, 2, 3])

3.再封装一层数据,改成对象(推荐!)

const state = reactive({
    arr: []
});
state.arr = [1, 2, 3]

reactive与ref区别

reactive

  1. reactive底层本质是将传入的数据包装成一个Proxy
  2. reactive参数必须是对象(或者数组)类型数据
  3. 如果要让对象的某个元素实现响应式时比较麻烦。需要使用toRefs
  4. reactive都不需要添加value

ref

  1. ref通常用来定义基本类型数据
  2. 如果参数是对象类型时,其实底层的本质还是reactive,内部会通过reactive转为代理对象
  3. ref响应式原理是依赖于Object.defineProperty()get()set()的。
  4. ref操作数据需要.value,在js中需要手动.value,template模板中不需要。

ref、toRef、toRefs的区别

ref:复制,修改响应式数据不影响以前的数据;数据改变,界面自动更新

toRef:引用,修改响应式数据会影响以前的数据;数据改变,界面不自动更新

toRefs

(1)接收一个对象作为参数,它会遍历对象身上所有属性,然后调用单个toRef

(2)将对象的多个属性变成响应式数据,并且要求响应式数据和原始数据关联,且更新响应式数据的时候不会更新界面,用于批量设置多个数据为响应式

5.Vue获取当前页面路由

//当前页面
window.location.href //完整url可以用 
this.$route.path //路由路径可以用 
this.$route.params //路由路径参数 

监听路由

直接在监听后传入一个方法对应的字符串,在路由发生变化的时候自动执行方法

watch: {
    // 如果路由有变化,会再次执行该方法
    '$route': 'fetchData'
},
methods:{
    fetchData () {
      //...
    }
}

如果我们要通过判断路由发生的特定变化来执行方法,可以使用handler

watch:{
    "$route":{
        handler(route){
            const that=this;
            if(route.name=='Hello'){
                that.fetchData();
            }
        }
    }
}

6.Vue请求本地JSON文件的方法

使用vue-cli2.0生成的项目,静态文件是static文件。

使用vue-cli3.0生成的项目,静态文件变成了public文件。(vue3相同)

把json文件放到静态文件里面,使用的时候vue会默认请求到静态文件里面。

案例:

this.$axios.get('data.json')
.then((res) => {
    // 200响应
    console.log(res) // 此处的res对象包含了json的文件信息和数据,看控制台点出来即可
}, (err) => {
    // 500响应
    console.log(err)
})

7.解决script标签写在元素节点前面无法获取元素节点的问题

文档的加载是按照文档树的顺序加载的,所以获取script脚本节点后面加载的元素节点 是获取不了的。

两个方法,如下:

解决方案一:使用onload事件,window.onload当页面加载完成后触发。

由于 script 标签写在div块前面,运行代码会报错,无法获取到box元素,使用window.onload即可解决。

代码说明:

<style>
    .box {
        width: 100px;
        height: 100px;
        background-color: blue;
    }
</style>
<script>
    window.onload=function(){//页面加载完后执行
        var box=document.getElementById("box");
        box.style.background="green";
    }
</script>

<div id="box">我是box</div>

解决方案二: 利用脚本的异步加载,需要用到两个属性 asyncdefer

这两个属性是在外部导入js文件时使用,当外部导入js的文件的script标签在元素节点前面时,同样会存在获取不到元素节点的情况,这时就需要用到asyncdefer

代码说明:

<style>
    .box {
        width: 100px;
        height: 100px;
        background-color: blue;
    }
</style>
<script scr="index.js" async></script>

<div id="box">我是box</div>

创建一个index.js文件

window.onload=function(){//页面加载完后执行
    var box=document.getElementById("box");
    box.style.background="green";
}

详情查看:JS基础篇:JS脚本调用策略

8.justify-content: space-between;没有两端对齐,没有生效

原因:

伪元素::after::before影响

解决方法:

去掉伪元素

代码:

.el-row::before {
    display: none;
}
.el-row::after {
    display: none;
}

9.ElementUI中el-table-column的type为selection时选择框旁边有个点

场景:

使用el-table的多选框时,el-table-columntypeselection时,显示为勾选框。

但是会在勾选框旁边显示一个或多个实心的小点。

原因:

这是因为在设置el-table-column的宽度为30太窄导致的。

<el-table-column type="selection" width="30" align="center" />

解决方法:

将其宽度调大点。

<el-table-column type="selection" width="55" align="center" />

10.Vue 3 ::v-deep usage as a combinator has been deprecated. Use ::v-deep() instead

原因新的vue3.0 单文件规范::v-deep写法已经被废弃了,使用 :deep()替换::v-deep
https://github.com/vuejs/rfcs/blob/master/active-rfcs/0023-scoped-styles-changes.md
https://vuejs.org/api/sfc-css-features.html#scoped-css

/* Vue 2.0 写法 */
::v-deep .carousel-btn.prev {
    left: 270px;
}

/* Vue 3.0 更改为以下写法 */
:deep(.carousel-btn.prev) {
    left: 270px;
}
/* 或是 */
:deep() {
    .class {}
}

深度选择器扩展:

有时我们可能想要明确地制定一个针对子组件的规则。

最初我们支持>>>组合器使选择器“deep”。但是,一些 CSS 预处理器(例如 SASS)在解析它时存在问题,因为这不是一个官方的 CSS 组合器。

我们后来切换到/deep/,它曾经是 CSS 的实际提议添加(甚至在 Chrome 中原生提供),但后来放弃了。这给一些用户造成了困惑,因为他们担心/deep/在 Vue SFC 中使用会使他们的代码在已删除该功能的浏览器中不受支持。然而,与>>>一样,/deep/仅被 Vue 的 SFC 编译器用作编译时提示来重写选择器,并在最终的 CSS 中被删除。

为了避免被丢弃的/deep/组合器的混淆,我们引入了另一个自定义组合::v-deep器,这一次更明确地表明这是一个特定于 Vue 的扩展,并使用伪元素语法,以便任何预处理器都应该能够解析它.

出于兼容性原因,当前的Vue 2 SFC 编译器仍然支持以前版本的深度组合器,这再次让用户感到困惑。在 v3 中,我们弃用了对>>>和的支持/deep/

当我们为 v3 开发新的 SFC 编译器时,我们注意到 CSS 伪元素实际上在语义上不是组合子。伪元素接受参数更符合惯用的 CSS,因此我们也在以::v-deep()这种方式进行工作。如果您不关心显式v-前缀,您也可以使用较短的:deep()变体,它的工作原理完全相同。

仍然支持当前用作组合器的用法::v-deep,但它被认为已弃用并会发出警告。

11.Do not access Object.prototype method ‘hasOwnProperty’ from target object

原因分析:

为何 ESLint 不允许从目标对象调用 Object 原型方法?

在 JS 中,往往通过改变原型链实现继承。一旦原型链发生改变,原先可以访问到的原型属性方法便可能无法访问。考虑最极端的情况,若 obj 原先原型链的最顶端是Object,此时可以通过原型链访问 Object.hasOwnProperty 方法;而若改变后,顶端不再是 Object,那么访问 obj.hasOwnProperty 访问就会得到 undefined。因此,直接从对象访问原型方法,很可能会带来隐藏的 BUG。
为了避免这种细微的 bug,最好总是从 Object.prototype 调用这些方法。即直接在 Object 对象上调用其方法,利用 call 改变其 this 指向到我们的目标对象上,即可安全使用 hasOwnProperty 方法了。

/** 
 * 错误提示:Do not access Object.prototype method 'hasOwnProperty' from target object 
 * 解决方法:foo.hasOwnProperty("bar") 改为 Object.prototype.hasOwnProperty.call(foo, "bar")
 */

12.css display:flex 弹性布局 子标签设置固定宽度无效的问题

出现的情况

当子级盒子宽度之和大于父级盒子宽度的时候,会出现子标签设置固定宽度无效的问题。

表面原因:

一个父标签中嵌入了两个子标签,当父标签设置display:flex之后。即使子标签设置了宽度都是50%,但是如果左边子标签内容多,则左边子标签会挤掉右边子标签的一部分,所以导致了右边的宽度显示有问题。

根本原因:

父元素设置了display:flex,那么所有的子标签都会默认加上flex:0 1 auto;其中1 就是 flex中的flex-shrink 属性,表示开启了元素的收缩功能,所以才会有左边子标签会挤掉右边子标签的一部分的问题。
因此其中一种做法是:我们可以让该标签的自动收缩关闭,即flex:0 0 auto;然后再设置该标签的宽度即可。

解决方法:

//针对需要设置固定宽度的子标签,其中 50% 是根据自己的盒子宽度自定义设置的
//方法1flex: 0 0 auto;
width: 50%;

//方法2flex: 0 0 50%;

//方法3flex-shrink:0;
width: 50%;

//方法4min-width:50%;

12.eslint导致 The “xxx” property should be a constructor vue/require-prop-type-constructor

场景:

在有eslint情况下,使用 String | Number 会报如上错误。

报错原因:

组件props有多种类型时要用数组写法

解决方法:

props: {
    pid: {
      type: [Number, String],//String | Number
      default: 1
    }
  }

13.Vue style里面使用@import引入外部css, 作用域是全局的解决方案

场景:

使用@import引入外部css,作用域却是全局的

<style scoped>
@import "../css/reset.css";
/* 或 */
@import url("../css/reset.css");

</style>

或是
<script>
import "../css/reset.css";
</script>

原因:

使用@import引入外部样式表作用域是全局的

@import并不是引入代码到<style></style>里面,而是发起新的请求获得样式资源,并且没有加scoped

解决方法:

我们只需把@import改成<style src=""></style>引入外部样式,就可以解决样式是全局的问题

<style scoped src="../css/reset.css"></style>
<!-- 这种方法使用会出现一个玄学问题,路由首页使用,reset.css的样式会被本页面的样式覆盖,但是在 非路由首页使用(注:首页没有引入)时,reset.css会在样式最上方,相当于会覆盖本页面样式-->
<style scoped>
/* 本页面样式 */
</style>

14.JS在一个数组中过滤掉另一个数组的简易方法

// 方法1:
let Arr1 = [{
    id: 1
}, {
    id: 12
}, {
    id: 13
}, {
    id: 14
}];

let Arr2 = [{
    id: 1
}, {
    id: 12
}];

let newArr = [];

newArr = Arr1.filter(itemA => {
    return Arr2.every(itemB => {
        return itemB.id !== itemA.id
    })
})

// 方法2:
let arr1 = [1,2,3,4,5,6];
let arr2 = [3,2];

let newArr = [];

Arr1.forEach(item => {
    if (!Arr2.includes(item)) {
        newArr.push(item);
    };
})

// 方法3:
let arr1 = [1,2,3,4,5,6];
let arr2 = [3,2];

let newArr = [];

newArr = arr1.filter(item => arr2.indexOf(item) == -1)

// 方法4:
let arr1 = [1,2,3,4,5,6];
let arr2 = [3,2];

let newArr = [];
function getArrDifference(arr1, arr2) {
    return arr1.concat(arr2).filter(function(v, i, arr) {
        return arr.indexOf(v) === arr.lastIndexOf(v);
    });
}
newArr = getArrDifference(arr1,arr2)

15.解决el_table 固定列下方多了一条线问题

::v-deep{
    .el-table__fixed-right, .el-table__fixed{
        height: 100%!important;;
    }
}

16.解决setInterval方法在if条件语句判断无效的问题

同一页面,如果不通过clearInterval()清除的话,if条件语句的判断都是无效的,会一直定时执行

var timer=null;
var a=1;
if(a===1){
    clearInterval(timer);
    timer=null; 
}else{
    timer = setInterval(()=>{

    }, 1000);
}

17.axios的post请求为什么要使用qs

结论:用不用取决于后端怎么接收参数

axios默认的content-type是application/json,即json格式,后台可以使用字符串进行接收,然后再解析即可

18.关于js的style.width取不到元素的宽度值的问题

以前一直用jquery.width()方法来获取一个元素的当前的宽度。不管该元素是否设置了宽度,CSS样式是内联、外联or内嵌,都可用此方式获得元素当前的宽度。

用原生JS想获取一个元素宽度时,写document.getElementById("id").style.width或者document.getElementById("id").width都取不到值。

原来,在以下情况下,js无法取到.style.width或者.width的值。

  • 1.元素未设置宽度值。
  • 2.元素设置了宽度值,但,设置在内联或外联样式表中,而非内嵌式的。

比如:

css代码

p{
    background:red;
    width:200px;
}

html代码

<p id="p1">一段很长的文字</p>

虽然这种方式取不到宽度值。但却可以设置元素的宽度值。比如:设置p元素宽度为200px:

document.getElementById("p1").style.width ="200px";

所以,只有将元素的样式设置成内嵌式的,才可以通过 document.getElementById("id").style.width 来获取宽度值;
比如:

<p id="p1" style="144px;">一段很长的文字</p>

执行js代码

var w = document.getElementById("p1").style.width; 
alert(w);

执行后输出结果为144px。

那么,对于没有设置宽度的元素、亦或CSS样式非内嵌式的,js原生写法可以通过offsetWidth来获取宽度

即:

document.getElementById("p1").offsetWidth;

对于设置了CSS样式的元素(内联、内嵌、外联)offsetWidth 也都可以获得值

所以,jquerywidth()与js的offsetWidth都可以获取元素的宽度,但有个区别:

  • jquery.width()的值单纯是内容区域的宽度、不包括内外补丁和border。ie6+和chrome相同。
  • offsetWidth :包括了内补丁和border,不包括外补丁。ie6+和chrome相同

19.sass-loader版本问题引发的错误:options has an unknown property ‘prependData’. These properties are valid

原因:npm和sass-loader的版本高了。

由于sass-loader版本不同,loaderOptions 中 additionalData的键名也不同。

sass-loader v8-,这个选项名是"data"
sass-loader v8,这个选项名是"prependData"
sass-loader v10+,这个选项名是"additionalData"

结果:

//原来的
css: {
    loaderOptions: {
        sass: {
            prependData: '@import "@/scss/settings.scss";'
        }
    }
}

//修改后
css: {
    loaderOptions: {
        sass: {
            additionalData: '@import "@/scss/settings.scss";'
        }
    }
}

20.为什么document.addEventListener(‘load’, function(){})不能生效?

原因:在document.addEventListener中本身就不存在监听load事件的,所以就导致代码如果没有报错,但是就是不起作用,不生效。

应该在window对象上监听load事件,所以正确的代码如下:

window.addEventListener("load", function () {
    console.log("load");
})

21.Vue中的render: h => h(App)什么意思?

这是文档里的内容:

在哪里见过呢,就是这里:

new Vue({
    el:"#app",
    router,
    store,
    render: h => h(App)
})

//或
new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

这是我们利用Vue新建项目最常见的一句话,但是这句话是什么意思呢?对于初学者,看到这句话一定是懵逼的(有没有?有没有?)

因为这句写的真是简洁…

那么,参考上面文档中的内容,这句话的意思其实就是:

这是一个ES6箭头函数的写法,还原成一个函数,就是:

render: h =>{
    return h(App)
}

要是还看不懂,再进行还原:

render: function(h) {
    return h(App);
}

然后,别忘了最先贴的官方文档,解释“h”的含义,进一步还原:

render: function(createElement) {
    return createElement(App);
}

而这里的render就是一个渲染函数,而createElement就是创建节点,App就是一般情况下Vuehtml根文件,所以这里实质上就是将App这个html页面进行了渲染,当然在App页面中又有挂载的路由组件,进而可以渲染各种挂载的路由组件

22.【前端技巧】git已经push的代码如何修改commit

  1. 修改倒数第n次的commit,输入命令:

    # 最后的数字1可以是倒数第n次
    git rebase -i HEAD~1
  2. 回车后,按i进入编辑模式,找到需要修改注释的那一行,将其开头的 “pick” 改为 “edit” ,按ESC退出编辑模式,再输入:wq!保存退出。

  3. 更正commit注释内容,输入命令:

    git commit --amend
  4. 回车后,按i进入编辑模式,将第一行中的注释(不是下方注释)修改为正确的内容,按ESC退出编辑模式,再输入:wq!保存退出。

  5. rebase确认,输入命令(该部可省略):

    git rebase --continue
  6. 强制push,输入命令:

    git push --force

    至此,commit的message内容修改完成!

23.Vue3新属性之css中使用v-bind的问题汇总(v-bind in css)

有以下4种定义:

// 进行拼接调用测试的数据
let width = 400

// 直接调用的数据
let div_height = '400px'
let div_color = '#e89393'

// 对象调用的数据
let span = {
    width: '200px',
    height: '200px',
    color: 'green',
}

// 组合调用的数据
let transition = 'cubic-bezier(0, 1.5, .6, 1)'

1.在css中使用,使用v-bind()进行绑定 :

直接使用:完全没有问题

拼接使用:这个在css中没有问题,不过在scss中会出现错误

对象调用:对象的调用和直接使用类似,不过不同的是,需要使用引号的包裹才能正常使用,如果直接书写会报错

组合使用:完全没问题

四种样式写法如下:

.div {
    /* 拼接使用 */
    width: v-bind(width + 'px');
    /* 直接使用 */
    height: v-bind(div_height);
    background: v-bind(div_color);
    }

.span {
  /* 对象调用 */
    width: v-bind('span.width');
    height: v-bind('span.height');
    background: v-bind('span.color');
    display: flex;
    justify-content: center;
    align-items: center;
}

.span_title {
    width: 100px;
    height: 100px;
    background: #000;
    color: white;
    /* 组合使用 */
    transition: all .9s v-bind(transition);
}

.span:hover .span_title {
    border-radius: 50%;
    background: #a5f5b8;
    color: #ff0000;
}

2.在less中使用,使用v-bind()进行绑定 :

直接使用:没有问题

拼接使用存在问题,详见下文

对象调用:没问题

组合使用:没问题

四种样式写法如下:

// 使用变量承接
@height: v-bind(div_height);

.div {
    width: 400px;
    /* 直接使用 */
    height: @height;
    background: v-bind(div_color);

    .span {
        @width: v-bind('span.width');

        /* 对象调用 */
        width: @width;
        height: v-bind('span.height');
        background: v-bind('span.color');
        display: flex;
        justify-content: center;
        align-items: center;

        .span_title {
            @transition: v-bind(transition);
            width: 100px;
            height: 100px;
            background: #000;
            color: white;
            /* 组合使用 */
            transition: all .9s @transition;
        }

        &:hover .span_title {
            border-radius: 50%;
            background: #a5f5b8;
            color: #ff0000;
        }
    }
}

仅对拼接进行修改:

// 定义使用的数据
let width = 400
// 1.直接拼接
@width: v-bind( width + 'px');
width: @width;

// 2.拿到内容后拼接
@width: v-bind(width) + 'px';
width: @width;

// 3.使用时拼接
@width: v-bind(width);
width: @width + 'px';

其中第二种、第三种会没有效果,第一种会直接报错。

解决方式(思路):

将变量的内容在行内样式使用拼接的方式进行定义,然后在定义的less或scss中进行使用,因为定义的样式是行内样式,所以优先级和变量出现的位置,都是在使用之前,所以可以正常使用

使用数据的定义:

// 大部分数据和预先提供的数据一样(这里只写了新增数据)
let test = 400

页面结构:

<!--    改变的内容为下面这行(其他内容和原来内容保持一致)-->
<!--    【在这里对要使用的数据进行单位的绑定】-->
<div class="div" :style="{'--test' :test + 'px'}">
</div>

样式的使用:

// 承接使用
@width: var(--test);

.div {
    /* 使用 */
    width: @width;
    /* 或者直接使用 */
    width: var(--test);
    height: 400px;
    background: red;
}

3.在scss中使用,使用v-bind()进行绑定 :

直接使用:没有问题

拼接使用存在问题

对象调用:没问题

组合使用:没问题

// 使用变量承接
$width: v-bind(width + 'px');
$height: v-bind(div_height);

.div {
    /* 拼接使用 */
    width: $width;//没有生效
    /* 直接使用 */
    height: $height;
    background: v-bind(div_color);

    .span {
        $width: v-bind('span.width');

        /* 对象调用 */
        width: $width;
        height: v-bind('span.height');
        background: v-bind('span.color');
        display: flex;
        justify-content: center;
        align-items: center;

        .span_title {
            $transition: v-bind(transition);
            width: 100px;
            height: 100px;
            background: #000;
            color: white;
            /* 组合使用 */
            transition: all .9s $transition;
        }

        &:hover .span_title {
            border-radius: 50%;
            background: #a5f5b8;
            color: #ff0000;
        }
    }
}

更多详情,查阅:

-Vue3新属性之css中使用v-bind的方法(v-bind in css)

24.设置网页为黑白色

/* 网页为黑白色 ,以表哀悼*/
html {
    filter: grayscale(100%);
    -webkit-filter: grayscale(95%);
    -moz-filter: grayscale(100%);
    -ms-filter: grayscale(100%);
    -o-filter: grayscale(100%);
    filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
    -webkit-filter: grayscale(1);
}

25.解决el-tree点击行上面的操作按钮后,当前行变成白色背景的问题

// 此处是导致:el-tree点击上面的操作按钮后,当前行变成白色背景的根本原因,样式中单独看el-tree-node__content无法查看
.el-tree-node:focus>.el-tree-node__content {
    background-color: #28335f;
}

26.vue 子组件watch监听不到prop的解决

watch 添加immediate: true添加immediate: true添加immediate: true

27.关于Vue eventBus总线传值时的生命周期问题

https://www.jianshu.com/p/b1cb604dd4ae

1.解决vue bus.$emit触发第一次$on监听不到问题

https://www.uoften.com/article/186494.html

28.for of 和 for in 的区别

https://blog.csdn.net/weixin_47148731/article/details/123852461

29.Vue 报错error:0308010C:digital envelope routines::unsupported

原因:其实这不是vue的问题,是nodejs升级引起的构建错误

出现这个错误是因为 node.js V17版本中最近发布的OpenSSL3.0, 而OpenSSL3.0对允许算法和密钥大小增加了严格的限制,可能会对生态系统造成一些影响。

但其实,并不是所有的项目都会出现,比如使用了最新版本的 webpack 工具的项目就能够正常运行,所以得搞清楚其中的具体原因,到底是哪些地方影响了项目运行。

具体详看:

解决方法:

方法1.打开终端(按健win+R弹出窗口,键盘输入cmd,然后敲回车)并按照说明粘贴这些:(不一定行,可能失败了)
Linux & Mac OS (windows git bash)

export NODE_OPTIONS=--openssl-legacy-provider

windows命令提示符:

set NODE_OPTIONS=--openssl-legacy-provider

方法2.尝试卸载Node.js 17+版本并重新安装Node.js 16+版本

方法3.升级webpack
如果我们把 webpack(5.61.0以上版本) 进行升级到较新的版本,就可以解决此类问题。

tips:但是,由于升级构建工具,可能随之带来很多不可知的问题,不少依赖包都会因为不支持而报错,升级带来的成本并不小,所以不推荐升级构建工具。

30.js 模板字符串里面用换行符不起作用

有时候会遇到赋值过程中的字符串需要换行的情况,但是像下面那样直接 \n 是不行的。

this.text = `提示: \n ${this.tip}`

解决方法:

在它的HTML标签元素上,添加css样式设置:white-space:pre-line; 这样以上这段代码就生效了

//html
<div style="white-space:pre-line">{{text}}</div>
//js
this.text = `提示: \n ${this.tip}`

tips:若是要对title进行换行,如下,不需要添加white-space:pre-line,因为样式是对标签里的内容生效的,直接使用即可。

<span :title="`${data[treeProps.label]}\n${data.absolute}`"> {{ data[treeProps.label] }}</span>

31.try catch 无法获取 then 的异常

在 JavaScript 中,try...catch 语句通常用于捕获同步代码块中的错误。然而,当你处理基于 Promise 的异步操作时,try...catch 不能直接捕获 thencatch 方法中的错误。这是因为 thencatch 方法返回的是新的 Promise,而它们中的回调函数是异步执行的。

为了捕获 Promise 中的错误,你应该使用 Promise 链中的.catch()方法,或者在代码中,使用 async/awaittry...catch 结合来捕获异步错误。

使用 .catch() 方法

someAsyncFunction()
    .then((result) => {
        // 处理结果
    })
    .catch((error) => {
        // 捕获错误
        console.error("捕获到错误:", error);
    });

使用 async/awaittry...catch

async function main() {
    try {
        const result = await someAsyncFunction();
        // 处理结果
    } catch (error) {
        // 捕获错误
        console.error("捕获到错误:", error);
    }
}

main();

async/await 的例子中,await 关键字会暂停 async 函数的执行,直到 Promise 解决resolve)或拒绝reject)。如果 Promise拒绝,则 await 表达式会抛出一个错误,这个错误可以被外部的 try...catch 捕获。

注意,async/await 是 ES2017 引入的,因此你需要确保你的环境支持这个特性,或者通过 Babel 等工具进行转译。

错误的例子:try…catch 无法捕获 then 中的错误

try {
    someAsyncFunction().then((result) => {
        // 如果这里发生错误,try...catch无法捕获
        throw new Error("这是一个错误");
    });
} catch (error) {
    // 这个catch不会执行,因为上面的错误是在Promise的回调中抛出的
    console.error("这个错误不会被捕获:", error);
}

在上面的例子中,尽管有 try...catch 包围了 someAsyncFunction()的调用,但错误是在 Promisethen 回调中抛出的,因此 try...catch 无法捕获这个错误。要捕获这个错误,你必须在 Promise 链中使用.catch()方法,或者像前面提到的那样使用 async/await

32.vsCode中的css代码提示reference怎么关闭

打开设置搜索,将其取消勾选即可

Code Lens

取消Editor:Code Lens的勾选

33.el-table、vxe-table在修改页面宽度时,表格宽度没有变化,还是初始宽度的问题

父级添加overflow: hidden;

34.vue数组的更新,watcholdValnewVal值一样

场景:在vue2或vue3中,对数组使用push, unshift, splice等操作更新数据,会发现watch监听下的oldValnewVal值一样。

原因如下:

  1. oldValnewVal值一样的原因是它们索引同一个对象/数组。Vue 不会保留修改之前值的副本。
  2. 根据源码,push,unshift,splice三个方法触发后,在这里手动observe,其他方法的变更会在当前的索引上进行更新,所以不需要再执行ob.observeArray

35.Component emitted event “formValidate” but it is neither declared in the emits option nor as an “onFormValidate” prop.

  1. 报错原因
    组件触发了事件”confirmForm”,但它没有在emit中声明

2.错误代码

const emits = defineEmits("formValidate");
  1. 正确
    const emits = defineEmits(["formValidate"]);

tips:如果存在emit未知方法,则不能在 defineEmits 中传入任何值,否则会同样对未定义的事件名提示warning。
但最好显式地声明你的组件将要触发的事件,以提高代码的可维护性和可读性,尤其是在 Vue 3 + TypeScript 中将会报错。

示例:

// 此时假如有其他emits,如"editCell","selectChange"等
// 当你不传递任何参数给 defineEmits 时,它默认允许组件触发任何事件,而不会对事件名进行任何验证
const emits = defineEmits(); //["editCell","selectChange"]

const operateClick = (rowInfo, btn, rowIndex) => {
    if (
        btn.disabled &&
        (btn.disabled === true || btn.disabled(rowInfo, btn) === true)
    )
        return;
    if (btn.clickFun) {
        if (verifyType(btn.clickFun, "Function") === true) {
            btn.clickFun(rowInfo, btn, rowIndex);
        } else {
            emits(btn.clickFun, rowInfo, btn, rowIndex);
        }
    } else {
        console.error("按钮未定义clickFun点击事件回调");
    }
};

36.absolute 固定在滚动容器里面失效

场景:一个浮层,固定在滚动容器内部的底部,滚动容器relative定位,浮层absolute定位,但是发现随着内容的增加,开始出现滚动条了,这个浮层定位就随着滚动条一起滚上去了

解决方法:
就把position:absolute 换成sticky

position: sticky;

若当滚动容器的内容不满一屏时,即没有滚动条产生时,这个浮层就自动弹上去了。可以给滚动容器一个弹性布局,给滚动内容添加flex-grow:1,自动占满,即可解决。

//滚动容器
display: flex;
flex-direction: column;

//滚动内容
flex-grow:1;

37.el-form表单输入框回车事件导致页面刷新问题

场景:当el-form表单仅有一个el-input输入框的时候,在el-input输入框中回车,会触发默认的el-form表单提交事件,导致页面刷新。如果有多个表单元素则不会出现这个问题。

原因分析:

  1. 输入框回车导致页面刷新的原因主要是由于浏览器的默认行为。
  2. 按照W3C标准的说法是:当 form 元素中只有一个输入框时,在该输入框中按下回车应提交该表单;
  3. el-form本质上也是表单(可通过F12查看网页源码,el-form会转为form表单),所以遵循HTML默认规则。

解决方法:给el-form表单上加一个@submit.native.prevent,阻止表单提交的默认行为。

注:vue3,需要使用 @submit.enter.prevent,原因:vue3中移除 v-on.native 修饰符

<!-- Vue2 + element UI 禁用表单提交 -->
<!-- 在<from> 中添加@submit.native.prevent -->
<el-form @submit.native.prevent></el-form>

<!-- Vue3 + element Plus 禁用表单提交 -->
<!-- 在<from>中添加@submit.enter.prevent   -->
<el-form @submit.enter.prevent></el-form>

文章作者: 弈心
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 弈心 !
评论
  目录