0%

前言

最近学习前端项目时学到了数组这块,遍历数组有好多种方式,下面详细记录下,方便后面项目中使用

for 循环
1
2
3
4
for (let index=0; index < someArray.length; index++) {
const elem = someArray[index];
// ···
}

该方式是最基础的方式,如果我们遍历时不想从第一个元素开始,这种方式会很好用,其他方式要做到会很复杂

for-in 循环
1
2
3
for (const key in someArray) {
console.log(key);
}

该循环遍历的是key,不是值,我们一般都是遍历其中的值,所以大部分情况下不太符合我们的要求

数组方法 .forEach()
1
2
3
someArray.forEach((elem, index) => {
console.log(elem, index);
});

该方式是数组的方法,是es6中推出的,大部分情况我用的都是forEach,如果需要index索引,用第二种方式,否则直接用第一种,非常简洁,推荐使用

缺点是这种方式不能提前退出循环,for中可以使用break退出,循环体中不能使用await关键字

for-of 循环:
1
2
3
for (const elem of someArray) {
console.log(elem);
}

for-of 在循环遍历数组时非常有效:

  • 用来遍历数组元素。
  • 可以使用 await
    • 如果有需要,可以轻松地迁移到 for-await-of
  • 甚至可以将 breakcontinue 用于外部作用域。
for-of 和可迭代对象

for-of 不仅可以遍历数组,还可以遍历可迭代对象,例如遍历 Map:

1
2
3
4
5
6
7
8
9
10
11
const myMap = new Map()
.set(false, 'no')
.set(true, 'yes')
;
for (const [key, value] of myMap) {
console.log(key, value);
}

// Output:
// false, 'no'
// true, 'yes'

遍历 myMap 会生成 [键,值] 对,可以通过对其进行解构来直接访问每一对数据。

for-of 和数组索引

数组方法 .entries() 返回一个可迭代的 [index,value] 对。如果使用 for-of 并使用此方法进行解构,可以很方便地访问数组索引:

1
2
3
4
5
6
7
8
9
const arr = ['chocolate', 'vanilla', 'strawberry'];

for (const [index, elem] of arr.entries()) {
console.log(index, elem);
}
// Output:
// 0, 'chocolate'
// 1, 'vanilla'
// 2, 'strawberry'

前言

最近在前端项目上遇到要拼接数组,最简单直接的肯定是遍历,一个个push进去,但是这个不太优雅,所以总结了下js所有拼接数组的方式

for循环
1
2
3
4
5
6
7
8
9
10
11
12
13
function gabungArray(arrayAwal, arrayTambah) {  

for(let i = 0; i < arrayTambah.length; i++) {
arrayAwal.push(arrayTambah[i]);
} return arrayAwal;
}
var array1 = [1,2,3,4,5];
var array2= [6,7,8,9,10];
var array3 = [];
console.log(gabungArray(array1, array3));
// [ 1, 2, 3, 4, 5 ]
console.log(gabungArray(array2, array1));
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
concat函数(推荐)

concat() 方法用于将两个或多个数组合并为一个,与以前不同。 concat 不会改变数组的值,而是将其存储在 new array 中。

1
2
3
4
5
6
7
8
9
var array1 = [1,2,3,4,5];
var array2 = [6,7,8,9,10];
var array3 = array1.concat(array2);
// atau
var array4 = [].concat(array1, array2);
console.log(array3)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(array4)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Reduce函数

Reduce() 方法通过将值从目标数组元素移动到新数组来工作。 所以它变成了一个值。

1
2
3
4
5
6
7
8
var array1 = [1, 2, 3, 4, 5];
var array2 = [6, 7, 8, 9, 10];
var array3 = array2.reduce((newArray, item) => {
newArray.push(item);
return newArray;
}, array1);
console.log(array3);
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
展开运算符(推荐)

这种方法是最好的方法,在我看来,使用扩展运算符,迭代过程会立即在要链接的数组中运行。 使代码更加简洁

1
2
3
4
5
var array1 = [1,2,3,4,5];
var array2 = [6,7,8,9,10];
var array3 = [...array1, ...array2];
console log(array3);
// [1,2,3,4,5,6,7,8,9,10];
总结

concat是es5的写法,兼容性好,扩展运算符是es6新出的语法,数据量较小时(万级别的数量),差别不大,数据量较大时(十万级以上),concat性能较好!

一般前端不会有拼接几万几十万数据的需求,所以看自己喜好用即可,但如果真有,建议还是用concat,虽然差别也是毫秒级的,但是总归是有差别

前言

最近前端项目中有一个需求,tabbar需要增加一个角标显示未读数量,uview中自带badge属性可用,但是遇到了一些小问题,无法响应式更新页面中的数量,下面记录一下

解决

我的tabbar数组中的item是这样的

1
2
3
4
5
6
{
"pagePath": "/pages/a/b",
"text": "消息",
"iconPath": "/static/tab-icons/a.png",
"selectedIconPath": "/static/tab-icons/ab.png"
}

如果需要使用badge,需要增加一个自带,由于这个是单独定义在一个js文件中的,所有item是没有badge这个字段的,所以我也不想改动这个js中item,在其中加一个badge字段,所以我就直接在请求接口回来后,这样赋值

1
list[0].badge = 1 // list就是上述item的数组,0就是上面第一个,给这个字段赋值个1

发现数据虽然改变 ,但是页面上的数字没改变,刷新后才正确!所以一定是这样加字段不是响应式的

查阅了vue的文档,的确是这样的,如果在实例创建之后添加新的属性到实例上,它不会触发视图更新

所以有如下方法可以解决

1、使用Vue.$set,方法接收三个参数,如果是对象,则

1
this.$set(this.obj, 'badge', 1)

第一个参数是对象,第二个参数是要添加的字段key,第三个字段是value

如果是数组

1
this.$set(this.list, 1, item)

第一个参数是list,第二个参数是index,第三个是item

所以我的代码改为了这样

1
2
3
this.tabBarList[0].badge = 1
//给审批item增加badge字段,需使用$set,否则badge非响应式,无法更新页面
this.$set(this.tabBarList, 0, this.tabBarList[1])

首先给这个0的badge增加一个字段,然后再set赋值,发现可以了

2、使用object.assign方法,这个适合对象,我没有试过,所以不做评论,后续用到了再补充,建议使用第一种

前言

最近在springcloud多模块项目上添加一个新的子模块时,idea中maven层级图显示不正常,和父级显示在同级下,之前就遇到过这个问题,这次遇到又差点忘了,下面记录下

解决

1、首先子模块的pom.xml文件中,一定要添加parent,代码如下

1
2
3
4
5
6
7
..代码省略...
<parent>
<groupId>com.dhsr</groupId>
<artifactId>sirengine</artifactId>
<version>3.4.7</version>
</parent>
...代码省略...

确保上面的groupId,artifactId,version三个属性和父级模块的pom.xml文件中的声明的这三个属性的值一致

2、也是最重要的一步,父级模块的pom.xml文件下一定要添加modules属性,代码如下

1
2
3
<modules>
<module>dev-app</module> <!-- dev-app是子模块pom中声明的artifactId属性的值 -->
</modules>

完成后刷新maven就可以了,这时再查看maven树就是树状了,子模块再父模块下了

注意

两个步骤一个都不能少,少一个都不能显示树状,我就是老是忘记第二步,第一次折腾了多半个小时,一直在子模块下的pom文件折腾,以为是哪里写错了,后来才突然看到父模块中未添加子模块导致的

前言

最近在学css,经常用到一个position属性,有时候也搞不清楚他的值都是什么意思,下面记录一下

作用

position属性用来指定一个元素在网页上的位置,一共有5种定位方式,即position属性主要有五个值。

  • static
  • relative
  • fixed
  • absolute
  • sticky
static 属性值

staticposition属性的默认值。如果省略position属性,浏览器就认为该元素是static定位。

这时,浏览器会按照源码的顺序,决定每个元素的位置,这称为”正常的页面流”(normal flow)。每个块级元素占据自己的区块(block),元素与元素之间不产生重叠,这个位置就是元素的默认位置。

注意,static定位所导致的元素位置,是浏览器自主决定的,所以这时topbottomleftright这四个属性无效

relative 属性值

relative表示,相对于默认位置(即static时的位置)进行偏移,即定位基点是元素的默认位置。

它必须搭配topbottomleftright这四个属性一起使用,用来指定偏移的方向和距离。

1
2
3
4
div {
position: relative;
top: 20px;
}

上面代码中,div元素从默认位置向下偏移20px(即距离顶部20px)。

absolute 属性值

absolute表示,相对于上级元素(一般是父元素)进行偏移,即定位基点是父元素

它有一个重要的限制条件:定位基点(一般是父元素)不能是static定位,否则定位基点就会变成整个网页的根元素html。另外,absolute定位也必须搭配topbottomleftright这四个属性一起使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
HTML 代码如下
<div id="father">
<div id="son"></div>
</div>
*/

#father {
positon: relative;
}
#son {
position: absolute;
top: 20px;
}

上面代码中,父元素是relative定位,子元素是absolute定位,所以子元素的定位基点是父元素,相对于父元素的顶部向下偏移20px。如果父元素是static定位,上例的子元素就是距离网页的顶部向下偏移20px

注意,absolute定位的元素会被”正常页面流”忽略,即在”正常页面流”中,该元素所占空间为零,周边元素不受影响。

fixed 属性值

fixed表示,相对于视口(viewport,浏览器窗口)进行偏移,即定位基点是浏览器窗口。这会导致元素的位置不随页面滚动而变化,好像固定在网页上一样。

它如果搭配topbottomleftright这四个属性一起使用,表示元素的初始位置是基于视口计算的,否则初始位置就是元素的默认位置。

1
2
3
4
div {
position: fixed;
top: 0;
}

上面代码中,div元素始终在视口顶部,不随网页滚动而变化。

sticky 属性值

sticky跟前面四个属性值都不一样,它会产生动态效果,很像relativefixed的结合:一些时候是relative定位(定位基点是自身默认位置),另一些时候自动变成fixed定位(定位基点是视口)。

因此,它能够形成”动态固定”的效果。比如,网页的搜索工具栏,初始加载时在自己的默认位置(relative定位)。

等到页面重新向上滚动回到原位,工具栏也会回到默认位置。

sticky生效的前提是,必须搭配topbottomleftright这四个属性一起使用,不能省略,否则等同于relative定位,不产生”动态固定”的效果。原因是这四个属性用来定义”偏移距离”,浏览器把它当作sticky的生效门槛。

它的具体规则是,当页面滚动,父元素开始脱离视口时(即部分不可见),只要与sticky元素的距离达到生效门槛,relative定位自动切换为fixed定位;等到父元素完全脱离视口时(即完全不可见),fixed定位自动切换回relative定位。

请看下面的示例代码。(注意,除了已被淘汰的 IE 以外,其他浏览器目前都支持sticky。但是,Safari 浏览器需要加上浏览器前缀-webkit-。)

1
2
3
4
5
#toolbar {
position: -webkit-sticky; /* safari 浏览器 */
position: sticky; /* 其他浏览器 */
top: 20px;
}

上面代码中,页面向下滚动时,#toolbar的父元素开始脱离视口,一旦视口的顶部与#toolbar的距离小于20px(门槛值),#toolbar就自动变为fixed定位,保持与视口顶部20px的距离。页面继续向下滚动,父元素彻底离开视口(即整个父元素完全不可见),#toolbar恢复成relative定位。

前言

今天在打包一个前端项目时报错,如题所示,Vue项目当dev命令运行时能正常运行,打包后却报错UglifyJs Unexpected token: punc (,),但是能顺利打出来,看一下原webpack.prod.conf.js

1
2
3
4
5
6
7
8
9
10
 plugins: [
...
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
]

经过一番思考后对比其他项目打算换一个压缩插件uglifyjs-webpack-plugin,而不使用webpack内置插件,结果就解决了!

1
"uglifyjs-webpack-plugin": "^1.1.1"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
plugins: [
...
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false,
drop_debugger: true,
drop_console: true
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
...
]
注意

是1.1.1版本,我刚开始用的最新的2.x的版本反而报错,没看具体原因,换成1.1.1后完全正常

前言

最近在改前端项目中遇到了一个问题,就是固定前两列后,前两列的会错位

原因

由于table在数据请求后,渲染异常的问题;因此,解决办法就是让table重新布局

解决

官方提供了doLayout方法,来解决重新布局的问题

doLayout 对 Table 进行重新布局。当 Table 或其祖先元素由隐藏切换为显示时,可能需要调用此方法

doLayout的使用方式

找到请求数据后的地方,立刻获取更新后的DOM

1
2
3
4
this.$nextTick(() => {
this.$refs.multipleTable.doLayout();
});

前言

最近使用uni开发小程序的时候遇到了一个问题,我想要设置页面的背景色,但是在style标签中怎么写都不生效,

看了无数的帖子,都是说设置page { background-color: rgb(240, 240, 240); }这个就好使,但是我的就是不生效

解决

后经过多方测试,发现,我们一般写style样式都是系统自动生成的,如下

1
2
<style lang="scss" scoped>
</style>

问题就出现在scoped上,它的意思大家应该都懂,vue组件中为了样式隔离,做到私有化,添加scoped属性以表示它只属于当下的模块,局部有效

所以去掉后,代码如下

1
2
3
4
5
<style>
page {
background-color: rgb(240, 240, 240);
}
</style>

背景色正常显示

前言

最近在做前端项目中遇到过一个问题,使用flex布局时,设置右对齐方式应该如下,justify-content: flex-end时,但是并没有生效

解决

需要同时设置左边距为auto

1
margin-left: auto;
原理

margin-left如果不设置的话默认就是0,父容器width定宽后,margin-left取值为auto,则会自动占据剩余的全部宽度

前言

最近有个需求,一个表中有连个时间字段,一个开始时间,一个结束时间,下载再新增数据时,需要判断是否有重合

实现

例如开始时间字段:start_time 结束时间字段:end_time

a 和 b 是输入的字段

1
2
3
4
5
SELECT * FROM test_table
WHERE
(start_time >= a AND start_time <= b)
OR (start_time <= a AND end_time >= b)
OR (end_time >= a AND end_time <= b)

1:判断数据库中的某行数据是否在输入的时间段之内

2:判断数据库中的某行数据是否包含输入的时间段

3:判断结束时间是否在输入的时间段内

有满足其一就表示时间重合