第0期新人任务的一点点小总结
PetnaKanojo Lv2

因为之前js写得太少了,所以mentor就给我布置了这个大概是需要写很多js的任务。git仓库地址

任务大概是实现gitlab里Issue下的List和Board的页面上的一些功能。

Update(19 May 2022):今天在重构我的博客,顺便回顾了我上一版博客中的所有文章,看到这一篇的时候真的觉得青春不再来。虽然这篇文章看起来真的傻得可爱,但是这确确实实是我写的第一个比较复杂的JavaScript的任务&我的总结。人都在成长呀,这些可爱的总结就让它一直跟着我吧~

7.1第一天听到这个任务的时候真的是完全没有头绪的,在脑子里甚至一点实现的方法都不知道应该怎么做,jsdom说实话都忘光了,也没学习过实战使用bootstrap,jquery等等,。第一天的时候下午就只是超级简单地搭了第一个页面最上面的那一小块框框。第一天认识mentor,以前就听说过他,真的接触以后果然就像听说的那样是个超级juju呀。那天是我第一次接触前端现代化构建工具,感觉是真的非常神奇。之后的学习让我真的感觉到其实没有不能做完的事情的。

这次的代码说实话如果打分的话最多1分,还是辛苦分。因为真的是太烂了。(当然了,”ddd”命名我还是真的非常喜欢啊,反正我很喜欢它们w,虽然mentor特意写了(\w+)\1{2,}对这个糟糕的命名变量的方式进行吐槽。)我之前看到过文章说:“给每一个节点都手动绑定事件真的很蠢”,但是我就是用的这样的蠢方法。最开始做的时候我想着的是能写完就最好了,根本没有考虑太多的东西。。结果到最后几天的时候就因为代码结构,渲染dom,还有数据存储的毛病导致写得很痛苦,后面几天的代码产出量都很少。前六天在写大体逻辑和页面结构,除去中间三天,后面六天大概只有前六天一半的时间在肝,说实话也是有点点懈怠了。可能是觉得自己写不好逻辑的原因然后就给自己找了需要休息的借口在作祟。其实应该更加以ddl紧逼自己的。

前半个月WordCounter记录

前半个月WordCounter记录

webpack

这个东西我还没有非常熟练地掌握,等我整理一下代码,学习一下代码的模块化,再来补。但是webpack+babel就像mentor说得那样:“早用早舒服。”

首次更新:使用了超级蠢的方法,一个个函数进行module.exports然后再require,改了一千多行的js结构,感觉比写代码还要累很多。大概就是babel配炸了。

ES6

babel就是用来将es6那些还没有被广泛接受的语法转换成es5,可以让主流浏览器都可以接受,但是我还没实操es6的语法糖,但是看上去感觉很不错!

实时搜索

1
2
3
4
5
/*ddd是类名/id名等*/
$("ddd").bind("input propertychange",function() { //使用bind检测输入框的实时变化,并进行搜索。
var el = function() {/*do something*/};
el($(this).val());
});

可以利用这个进行实时搜索,设置button的disabled的属性,真的挺不错的。

模糊搜索

根据用户输入,将与用户输入匹配的数据全部显示出来。例如

1
2
3
var a = ['ddd','js_err','css_err','errors','display_err'];
/*当用户输入s时显示'js_err','css_err','errors'
用户继续输入e时,此时显示'js_err','css_err'*/

实现方式如下:

1
2
3
4
5
6
var reg = new RegExp(searcharr.join(".*"));
for (var i = 0; i < allLabels.length; i++) {
if (reg.exec(allLabels[i].name)) {
resultarr.push(i);
}
}

此处点名表扬810的小哥哥,原本我想的是很复杂的解决,然后他们跟我讲了直接用正则表达式进行匹配。

然后搭配上上面讲过的实时搜索,就是一个很优雅的实现方式啦。

点击显示窗口之外的地方使显示框关闭

1
2
3
4
5
6
7
8
9
/*一段SO上优秀的实现方法:用于实现点击空白关闭弹窗*/
/*ddd是类名/id名等*/
$(document).mouseup(function(e) {
var _area = $("ddd"); //目标区域
//判断点击区域是否是目标区域
if (!_area.is(e.target) && _area.has(e.target).length === 0) {
//do something
}
});

function in loop

这是我在比较后期处理数据的时候碰到的问题,我在一个循环中嵌了一个函数,结果我认为在函数可以读取到循环中的数据时,却它本身形成了closure,传给函数的值就一直只是循环的最后一个值。在自己没法处理的时候问了一下mentor,google查了一下function in loop,然后看到了SO上的这个问题:Javascript: Creating Functions in a For loop,大体就是因为形成了一个闭包(闭包这个之前只存在笔试中以及我看过的js书籍中的名词终于让我在实战中碰到了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//当点击addlist中的label时,在下方的boardlist中显示出新的框框
function addaddadd() {
let index = getAllLabelsIndex();
let length = index.length;
var boardIndexInDisplay = showingBoardarray;
for (let i = 0; i < length ; i++) {
/*下面这行是经过修改的,改成了const*/
const sss = "#" + allLabels[index[i]].name;
$(sss).click(function() {
if(showingBoardarray.indexOf(i) < 0) {
getShowingBoardArray(i);
/*就是下面这行一直出问题*/
$(sss).children().children().children(".checkboxStyle").attr("style","background-color:lightgreen");
showNewBoardWhenClickAL(i);//将点击的label的编号传入函数
console.log("added"+showingBoardarray);
} else {
deleteShowingBoardArray(i);
$(".board").each(function() {
if(parseInt($(this).attr("data-id")) === i) {
$(this).fadeOut(400,function() { //这是一个可爱的回调函数
$(this).remove();
})
}
})
$(sss).children().children().children(".checkboxStyle").attr("style","background-color:transparent");
}
});
}
}

存储数据

用对象进行存储,之后准备写的一个“地图”数据也准备用这个方法存,那个的处理应该比这个简单很多。

同时,在存储数据之前一定要想清楚mvc,mvvp等设计模式的用法,要让数据存储,数据处理,与数据渲染比较清晰地分开。

对于数据更改后的渲染,最好进行一下判断,对进行修改的部分进行重新渲染,而不是对__整个块__进行渲染,这样消耗的资源实在是太多了。

页面拖拽

直接调用的github上的库,Sortable

这个也是对比了几个库,抛弃了最开始的dragula,大概是觉得它的icon太丑了x

以前没有调过库,对一堆API还是有点不知所措的,所以就导致最后三天基本都在对库感觉非常头疼,等最后看清楚文档,学会调用以后,瞬间感觉之前一直花在这个上面的时间真的太蠢了。明显拖拽应该早早就做完,然后就可以对页面上的bug进行进一步完善的。。

这个的实现也是非常简单,这个库其实封装得还可以,你可以获取到拖拽之后的数据,比如你当前拖拽的item的信息,这个item原本是从哪里拖过来的的信息以及最终放置的地方的信息。可以对ghost-class进行样式修改,但是碰到的一个问题就是当这块所有可拖拽的元素都拖出去之后,这一块就没法继续放东西了,这个大概也是我实现上出现的一个bug。

代码大概是这个样子的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Sortable.create(newdivs.getElementsByClassName("board-list")[0],{
group:"boards",
draggable: ".every-issue-to-drag",
onAdd: function(ev) {
var itemIssueIndex = ev.item.getAttribute('index'); //获取的是现在进行改动的issue的index
var labelFromIndex = ev.from.getAttribute('data-board'); //离开的label-board的index
var labelToIndex = ev.item.parentNode.getAttribute('data-board');
if (labelFromIndex !== labelToIndex) {
addData(itemIssueIndex,labelFromIndex,labelToIndex,ev.item);
deleteData(itemIssueIndex,labelFromIndex,ev.from);
render();
}
},
});
function addData(issueIndex, labelFromIndex, labelToIndex,evItem) {
var i = allLabels[labelFromIndex].IssueHave.indexOf(parseInt(issueIndex));
var j = allLabels[labelToIndex].IssueHave.indexOf(parseInt(issueIndex));
if (j >= 0) { //
evItem.setAttribute("style","display:none");
} else {
allLabels[labelToIndex].IssueHave.push(parseInt(issueIndex)); //将原本label中没有的issue添加进去
var labelname = allLabels[labelToIndex].name;
var labelcolor = allLabels[labelToIndex].color;
issue_info[parseInt(issueIndex)].tag.push(labelname);
issue_info[parseInt(issueIndex)].tagColor.push(labelcolor);
var num = allLabels[labelToIndex].IssueHave.length;
evItem.parentNode.parentNode.parentNode.childNodes[0].childNodes[0].childNodes[1].childNodes[0].innerHTML = num;
}
}
/*传入参数为:需要修改的issue的index, 以及删除了哪一个label*/
function deleteData(issueIndex, labelIndex,evItem) {
var i = allLabels[labelIndex].IssueHave.indexOf(parseInt(issueIndex));
var labelname = allLabels[labelIndex].name;
allLabels[labelIndex].IssueHave.splice(i, 1);
var j = issue_info[issueIndex].tag.indexOf(labelname);
issue_info[issueIndex].tag.splice(j,1);
issue_info[issueIndex].tagColor.splice(j,1);
var num = allLabels[labelIndex].IssueHave.length;
evItem.parentNode.parentNode.childNodes[0].childNodes[0].childNodes[1].childNodes[0].innerHTML = num;
}

jQuery

话说这个框架还是真的很不错,省了很多操作dom的麻烦,但是我感觉由于它太方便了,所以其实会让人变笨。以前有人跟我说:“现在jquery已经不是趋势了,原生js才是主流。”在这一次用完以后我也这样感觉了,jquery会让人变懒。而且由于提供了很多方便的操作,很容易让菜鸟对基本dom操作变得不熟悉甚至说不知道。对一些jquery完成的操作也不知道如何使用原生js进行复写。所以这个东西在平时学习的时候还是少用比较好。

bootstrap

mentor跟我说让我尽量自己实现整个网页的样式,其实没怎么用bootstrap,大概就是做了几个btn稍微用了一下,其实个人对于bootstrap的好感不是很好,因为打开很多网页都是bootstrap的扁平化设计,看多了以后其实觉得有点厌烦了,对于千篇一律的这种设计有点点抵触的心理,大概就是这样。

但是不得不承认bootstrap还是很不错的。应该稍微看一下。

字体,icon

fontawesome真的挺不错的,还有就是推荐一个网站,从一个pm那里听说的,阿里巴巴矢量图标库。还有一个选择配色的网站colorHunt

以及Adobe的这个colorWheel,和一个显示渐变色彩的uigradients。这些对于整体设计都挺不错的。

对动态的元素绑定事件

记得使用live

1
2
3
$("xxxx").live('click',function() {
//do something;
})

页面里用js插入了很多html代码,所以很多节点都是动态生成的,直接绑定事件总是失败orz

组件化

这个的重要性是我在快要做完的时候才意识到的,很多无用重复的代码应该进行合理地封装,并且对于显示方式也需要更好地规划。

还有就是要考虑页面在渲染的时候对于资源的消耗,现在只是做本地的,所以可能劣势不是很明显,但是一个稍微合格的前端程序员都应该有这样的意识吧。

总结

大体上就是这些了吧,很多小细节上的坑不再多进行赘述了。这个任务看上去很难,但是我在写了几天之后感觉其实还好,最开始的两天居然还说这个的代码量不是很大,emmmm收回这句话,真的是写的头昏眼花了。。。可能我实在太弱了,很多应该思考到的细节都没有好好解决,而且网页目前有些地方还是有些bug的,数据存储以及渲染都是垃圾的实现方式,甚至local storage都没有实现。mentor说这个任务比较难,我觉得可能是因为在他眼里如果要用优雅的实现方式确实很难吧,谁知道被我写成了这个鬼样子orz。

哦对,最后还是要抨击一下atom,在任务写到第六天的时候,atom直接下午的时候崩了。代码有些地方直接回滚到上一个版本了,但是有些地方却是保存了我最近的修改,当时真的气到不想说话,原本以为比较顺利的任务进度,就被打乱了,所以准备之后立刻迁移到webstorm上面进行代码编写。以前还是atom的死忠粉,但是经常碰到atom的保存问题,让我决定以后只用它写博客和md文档了 :)