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% 是根据自己的盒子宽度自定义设置的
//方法1:
flex: 0 0 auto;
width: 50%;//方法2:
flex: 0 0 50%;//方法3:
flex-shrink: 0;
width: 50%;//方法4:
min-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 | Numberdefault: 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
  1. 回车后,按 i 进入编辑模式,找到需要修改注释的那一行,将其开头的 “pick” 改为 “edit” ,按 ESC 退出编辑模式,再输入:wq!保存退出。

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

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

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

git rebase --continue
  1. 强制 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 0.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 0.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 0.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. e m i t 触发第一次 emit触发第一次 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 工具的项目就能够正常运行,所以得搞清楚其中的具体原因,到底是哪些地方影响了项目运行。

具体详看:

  • nodejs 升级引起的构建错误:0308010C:digital envelope routines::unsupported

解决方法:

方法 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
  • Vue 之 computed 和 watch
  • 为什么 Vue3.0 使用 Proxy 实现数据监听(defineProperty 表示不背这个锅)
  • 为什么 Vue3.0 使用 Proxy 实现数据监听(defineProperty 表示不背这个锅)

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>

38.vxe-table 父子不关联,不影响全选功能

场景:表格父子不关联,但此时的全选功能失效

解决方法:
修改 vxe-table\es\table\src\table.js 下的 handleCheckedAllCheckboxRowcheckSelectionStatus 两个方法
按照建议 2 进行修改:加入 showHeader 判断,不推荐使用 1 的一刀切修改方法

详情查看 checkStrictly 父子不关联逻辑调整,父子不关联只控制表格 Body 里的数据关联性,建议父子不关联,不影响全选功能,很多业务场景需要父子不关联的情况下,需要全选功能

39.使用 flex:1 导致 vxe-table 出现滚动一卡一卡的

若因flex:1导致 vxe-table 出现滚动一卡一卡的,给 flex:1 的容器添加 overflow: hidden 就可以

更多查看

  • 1.外层使用 flex 自适应宽度时,表格宽度自适应有问题,每次窗口自适应都会有一个较长的变化过程
  • 2.宽度自适应问题

40.ElMessage offset 修改

element-plus 下生成 eslib 两个文件夹,分别为 ESM 与 CJS 两种格式。

import { ElMessage } from "element-plus"; 方式引入

1.修改 node_modules\element-plus\es\components\message\src\message.mjs 里的 offset 为 60

const messageDefaults = mutable({customClass: "",center: false,dangerouslyUseHTMLString: false,duration: 3e3,icon: void 0,id: "",message: "",onClose: void 0,showClose: false,type: "info",offset: 16, //修改此次为60zIndex: 0,grouping: false,repeatNum: 1,appendTo: isClient ? document.body : void 0,
});

2.修改 node_modules\element-plus\es\components\message\src\message.d.ts 里的 readonly offset: 16readonly offset: 60

export declare const messageDefaults: Mutable<{readonly customClass: "";readonly center: false;readonly dangerouslyUseHTMLString: false;readonly duration: 3000;readonly icon: undefined;readonly id: "";readonly message: "";readonly onClose: undefined;readonly showClose: false;readonly type: "info";readonly offset: 16;//修改此次为60readonly zIndex: 0;readonly grouping: false;readonly repeatNum: 1;readonly appendTo: HTMLElement;
}>;
const { ElMessage } = require("element-plus"); 方式引入

1.修改 node_modules\element-plus\lib\components\message\src\message.js 里的 offset 为 60

const messageDefaults = typescript.mutable({customClass: "",center: false,dangerouslyUseHTMLString: false,duration: 3e3,icon: void 0,id: "",message: "",onClose: void 0,showClose: false,type: "info",offset: 16, //修改此次为60zIndex: 0,grouping: false,repeatNum: 1,appendTo: core.isClient ? document.body : void 0,
});

2.修改 node_modules\element-plus\lib\components\message\src\message.d.ts 里的 readonly offset: 16readonly offset: 60

export declare const messageDefaults: Mutable<{readonly customClass: "";readonly center: false;readonly dangerouslyUseHTMLString: false;readonly duration: 3000;readonly icon: undefined;readonly id: "";readonly message: "";readonly onClose: undefined;readonly showClose: false;readonly type: "info";readonly offset: 16;//修改此次为60readonly zIndex: 0;readonly grouping: false;readonly repeatNum: 1;readonly appendTo: HTMLElement;
}>;

41.有关 form 表单 validate 的使用

第一种写法:

let isValid = await addFormRef.value.validate().catch(err => {return err; // 关键问题在这里
});
if (isValid === true) {return true;
} else {return false;
}

这种写法的主要问题在于:

  1. 错误处理的逻辑问题:
  • 使用了 await 关键字直接等待 addFormRef.value.validate() 的结果,这要求 validate() 方法返回一个 Promise
  • 通过 .catch(err => { return err; }) 处理任何可能出现的错误,将错误直接返回给 isValid。这种方式下,当验证失败(发生错误)且没有正确抛出被 catch 捕获时,catch 会捕获错误并返回错误对象
  • 错误对象不是 truefalse ,而是一个包含错误信息的对象,这可能导致判断结果不准确
  • 这时 isValid 的值会是一个错误对象,而不是预期的 boolean
  1. 类型判断问题:
  • if (valid === true) 使用严格相等,期望比较的是布尔值
  • 但如果 isValid 是错误对象,这个比较就会失败
  • 导致验证失败时的逻辑可能不符合预期,出现误判

第二种写法:

const isValid = await new Promise(resolve => {addFormRef.value.validate(valid => resolve(valid));
});

这种写法更好:

  1. 使用了 Element Plus 表单验证的标准回调方式
  2. validate 方法的回调函数直接接收验证结果(boolean 值)
  3. 直接使用 Promise 包装验证过程,通过 Promise resolve 正确返回验证结果(布尔值)
  4. 确保 isValid 一定是布尔值,不会出现额外类型判断的问题
总结:

推荐使用第二种写法,因为:

  1. 代码更简洁
  2. 错误处理更准确,第一种写法在处理验证失败的情况时可能会有问题,因为错误对象与 true 的比较会导致不准确的结果
  3. 返回结果更可靠,因为它总是能得到正确的布尔值结果
  4. 符合 Element Plus 表单验证的标准用法

如果需要处理错误,建议使用这种写法:

const isValid = await new Promise((resolve, reject) => {addFormRef.value.validate((valid, errors) => {if (valid) {resolve(true);} else {reject(errors);}});
}).catch(errors => {console.error(errors);return false;
});

42.解决el-popup-parent–hidden 会携带 width: calc(100% - 8px) 样式的问题

场景:使用el-drawerel-message-boxel-dialog打开弹框时,body 会添加一个 class: el-popup-parent--hidden,此时会概率携带一个类似width: calc(100% - 8px)的样式;

更多查看:el-popup-parent–hidden

解决方法: 1.重写 el-popup-parent–hidden 的样式

.el-popup-parent--hidden {width: 100% !important;
}

2.在 main.js 中添加关闭 dialog 滚动条配置

// 此方法未验证会不会影响到弹框的滚动条,慎用
// vue2
import ElementUI from "element-ui";
// vue3
import ElementPlus from "element-plus";
import "element-ui/lib/theme-chalk/index.css";
// 关闭dialog滚动条
ElementUI.Dialog.props.lockScroll.default = false;
ElementPlus.Dialog.props.lockScroll.default = false;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/503498.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ffmpeg7.0 合并2个 aac 文件

ffmpeg7.0 将2个aac文件合并。 #include <stdio.h>// 之所以增加__cplusplus的宏定义&#xff0c;是为了同时兼容gcc编译器和g编译器 #ifdef __cplusplus extern "C" { #endif #include <libavformat/avformat.h> #include <libavcodec/avcodec.h>…

Midjourney 应用:框架总结

Midjourney 应用&#xff1a;框架总结 官方的模板很简单&#xff0c;分成四个部分&#xff1a; 主体细节 & 背景风格、媒介、艺术家参数 我的总结 其实按照官方模板写&#xff0c;你已经能超过 90% 的初学者&#xff0c;但根据我的实验&#xff0c;我细化了他们的模板的…

JVM实战—OOM的定位和解决

1.如何对系统的OOM异常进行监控和报警 (1)最佳的解决方案 最佳的OOM监控方案就是&#xff1a;建立一套监控平台&#xff0c;比如搭建Zabbix、Open-Falcon之类的监控平台。如果有监控平台&#xff0c;就可以接入系统异常的监控和报警&#xff0c;可以设置当系统出现OOM异常&…

JVM实战—13.OOM的生产案例

大纲 1.每秒仅上百请求的系统为何会OOM(RPC超时时间设置过长导致QPS翻几倍) 2.Jetty服务器的NIO机制如何导致堆外内存溢出(S区太小 禁NIO的显式GC) 3.一次微服务架构下的RPC调用引发的OOM故障排查实践(MAT案例) 4.一次没有WHERE条件的SQL语句引发的OOM问题排查实践(使用MA…

【银河麒麟高级服务器操作系统实例】tcp半链接数溢出分析及处理全过程

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://document.kylinos.cn 服务器环境以及配置 系统环境 物理机/虚拟机/云…

visual studio 自动调整代码格式的问题:

1.取消自动调整格式 2.如果是想让代码显得更紧凑&#xff0c;上面的不动&#xff0c;按这个来&#xff1a;

javaEE-网络原理-1初识

目录 一.网络发展史 1.独立模式 2.网络互联 二.局域网LAN 1.基于网线直连&#xff1a; 2.基于集线器组件&#xff1a; 3.基于交换机组件&#xff1a; 4.基于交换机和路由器组件 ​编辑 三、广域网WAN 四、网络通信基础 1.ip地址 2.端口号&#xff1a; 3.协议 4.五…

三维卷积( 3D CNN)

三维卷积&#xff08; 3D CNN&#xff09; 1.什么是三维卷积 1.1 三维卷积简介 二维卷积是在单通道的一帧图像上进行滑窗操作&#xff0c;输入是高度H宽度W的二维矩阵。 三维卷积输入多了深度C这个维度&#xff0c;输入是高度H宽度W深度C的三维矩阵。在卷积神经网络中&…

黄仁勋演讲总结(2种显卡,1个开源大模型,1个数据采集平台)

研发算力显卡RTX50系列&#xff0c;PC端显卡GB10&#xff0c;开源大模型Cosmos&#xff08;用于机器人和自动驾驶&#xff09;&#xff0c; Isaac GR00T&#xff08;人形机器人的数据采集平台&#xff09;。 新一代 RTX 50 系列显卡 RTX 50 系列 GPU&#xff0c;相对之前系列&a…

阿尔法linux开发板ping不通百度

我使用的阿尔法linux板子&#xff0c;发现按照《03【正点原子】I.MX6U网络环境TFTP&NFS搭建手册V1.3.2》一套操作下来&#xff0c;还是没办法实现板子上网。 我总结了下面方法&#xff0c;我如何实现联网和互ping通&#xff0c;大致总结下三步 一、pc端的wifi网络&#xf…

使用图像过滤器在 C# 中执行边缘检测、平滑、浮雕等

图像过滤器可让您对图像中的像素执行操作。这是一个相当大的示例,因此您可能需要花一些时间浏览代码。 在一种图像滤镜中,您有一个称为滤镜内核的值数组。对于图像中的每个像素,您将内核置于该像素的中心。然后将内核下的每个像素的值乘以相应的内核值。将它们相加,除以“…

数值分析速成复习笔记

请确保你有10hour的有效学习时间&#xff0c;保你拿90 证明部分 编程部分

如何快速上手一个鸿蒙工程

作为一名鸿蒙程序猿&#xff0c;当你换了一家公司&#xff0c;或者被交接了一个已有的业务。前辈在找你之前十分钟写了一个他都看不懂的交接文档&#xff0c;然后把一个鸿蒙工程交接给你了&#xff0c;说以后就是你负责了。之后几天你的状态大概就是下边这样的&#xff0c;一堆…

asammdf python库解析MF4文件(一)cut and filter

目录 cutfilter asammdf 是一个功能强大的 Python 库&#xff0c;专门用于处理汽车行业常用的 MDF&#xff08;Measured Data Format&#xff09;文件 这篇文章主要介绍mdf库的cut和filter函数 cut cut函数主要用于裁剪数据&#xff0c;比如你的MF4文件是一个100s的数据&…

性能测试01|性能测试理论

目录 一、性能测试概述 二、性能测试的分类 1、基准测试 2、负载测试 3、稳定性测试 4、压力测试 5、并发测试 三、性能测试的指标 1、响应时间 2、并发用户数 3、吞吐量 4、点击数 5、错误率 6、资源利用率 四、性能测试流程 1、性能需求分析 2、性能测试计划…

基于SpringBoot的斯诺克球馆预约购票管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

【JavaWeb】2. 通用基础代码

以下内容来源&#xff1a;编程导航。 无论在任何后端项目中&#xff0c;都可以复用的代码。 1、自定义异常 自定义错误码&#xff0c;对错误进行收敛&#xff0c;便于前端统一处理。 &#x1f4a1; 这里有 2 个小技巧&#xff1a; 自定义错误码时&#xff0c;建议跟主流的错…

获取IP地区

包 https://packagist.org/packages/geoip2/geoip2#v3.1.0 用composer加载包 composer require geoip2/geoip2 mmdb下载 https://github.com/P3TERX/GeoLite.mmdb?tabreadme-ov-file

企业国外传输大文件到国内该怎么做?

在全球化的商业环境中&#xff0c;企业跨国传输大文件已成为日常运营的重要组成部分。无论是项目合作、数据分析还是文件备份&#xff0c;高效且安全的文件传输对于企业的竞争力和业务连续性至关重要。 企业跨国传输文件的需求重要性 首先&#xff0c;跨国传输大文件能够显著提…

HTML+CSS+JS制作中华传统文化主题网站(内附源码,含5个页面)

一、作品介绍 HTMLCSSJS制作一个中华传统文化主题网站&#xff0c;包含首页、文化艺术页、传统工艺页、文化遗产页、关于我们页等5个静态页面。其中每个页面都包含一个导航栏、一个主要区域和一个底部区域。 二、页面结构 1. 顶部导航区 包含网站 Logo、主导航菜单&#xff…