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
reactive
底层本质是将传入的数据包装成一个Proxy
reactive
参数必须是对象(或者数组)类型数据- 如果要让对象的某个元素实现响应式时比较麻烦。需要使用
toRefs
reactive
都不需要添加value
ref
ref
通常用来定义基本类型数据- 如果参数是对象类型时,其实底层的本质还是
reactive
,内部会通过reactive
转为代理对象 ref
响应式原理是依赖于Object.defineProperty()
的get()
和set()
的。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>
解决方案二: 利用脚本的异步加载,需要用到两个属性 async
和 defer
这两个属性是在外部导入js文件时使用,当外部导入js的文件的
script
标签在元素节点前面时,同样会存在获取不到元素节点的情况,这时就需要用到async
和defer
。
代码说明:
<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-column
的type为selection
时,显示为勾选框。
但是会在勾选框旁边显示一个或多个实心的小点。
原因:
这是因为在设置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 | 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
也都可以获得值
所以,jquery
的width()
与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
就是一般情况下Vue
的html
根文件,所以这里实质上就是将App
这个html
页面进行了渲染,当然在App
页面中又有挂载的路由组件,进而可以渲染各种挂载的路由组件
22.【前端技巧】git已经push的代码如何修改commit
修改倒数第n次的commit,输入命令:
# 最后的数字1可以是倒数第n次 git rebase -i HEAD~1
回车后,按i进入编辑模式,找到需要修改注释的那一行,将其开头的 “pick” 改为 “edit” ,按ESC退出编辑模式,再输入:wq!保存退出。
更正commit注释内容,输入命令:
git commit --amend
回车后,按
i
进入编辑模式,将第一行中的注释(不是下方注释)修改为正确的内容,按ESC退出编辑模式,再输入:wq!
保存退出。rebase确认,输入命令(该部可省略):
git rebase --continue
强制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
不能直接捕获 then
或 catch
方法中的错误。这是因为 then
和 catch
方法返回的是新的 Promise,而它们中的回调函数是异步执行的。
为了捕获 Promise
中的错误,你应该使用 Promise
链中的.catch()
方法,或者在代码中,使用 async/await
与 try...catch
结合来捕获异步错误。
使用 .catch()
方法
someAsyncFunction()
.then((result) => {
// 处理结果
})
.catch((error) => {
// 捕获错误
console.error("捕获到错误:", error);
});
使用 async/await
与 try...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()的调用,但错误是在 Promise
的 then
回调中抛出的,因此 try...catch
无法捕获这个错误。要捕获这个错误,你必须在 Promise 链中使用.catch()
方法,或者像前面提到的那样使用 async/await
。
32.vsCode中的css代码提示reference怎么关闭
打开设置搜索,将其取消勾选即可
Code Lens
取消Editor:Code Lens的勾选
33.el-table、vxe-table在修改页面宽度时,表格宽度没有变化,还是初始宽度的问题
父级添加overflow: hidden;
34.vue数组的更新,watcholdVal
和newVal
值一样
场景:在vue2或vue3中,对数组使用push, unshift, splice
等操作更新数据,会发现watch
监听下的oldVal
和newVal
值一样。
原因如下:
oldVal
和newVal
值一样的原因是它们索引同一个对象/数组。Vue 不会保留修改之前值的副本。- 根据源码,
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.
- 报错原因
组件触发了事件”confirmForm”,但它没有在emit中声明
2.错误代码
const emits = defineEmits("formValidate");
- 正确
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表单提交事件,导致页面刷新。如果有多个表单元素则不会出现这个问题。
原因分析:
- 输入框回车导致页面刷新的原因主要是由于浏览器的默认行为。
- 按照W3C标准的说法是:当 form 元素中只有一个输入框时,在该输入框中按下回车应提交该表单;
- 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>