这是我参与「第四届青训营」笔记创作活动的的第3天
<h1>Code is poetry</h1>
写好js的三原则
- 各司其责
- 组件封装
- 过程抽象
以<轮播图>项目为例
关于用到的函数
[developer.mozilla.org/zh-CN/docs/…] Constructor构造器
Document.querySelectorAll - Web API 接口参考 | MDN (mozilla.org)
返回与指定的选择器组匹配的文档中的元素列表 (使用深度优先的先序遍历文档的节点)。返回的对象是 NodeList
例:.querySelectorAll('.slider-list__item, .slider-list__item--selected'); 使用单引号包裹,并且用逗号隔开,选择器写法与CSS相同
document.querySelector() - Web API 接口参考 | MDN (mozilla.org)
返回文档中与指定选择器或选择器组匹配的第一个 Element对象。 如果找不到匹配项,则返回null。
Array.from() - JavaScript | MDN (mozilla.org)
Array.from() 方法对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
本质:类数组转化为数组
DataTransfer.items - Web API 接口参考 | MDN (mozilla.org)
DataTransfer的items 属性只读,是拖动操作中 数据传输项的列表。该列表包含了操作中每一项目的对应项,如果操作没有项目,则列表为空。
Array.prototype.indexOf() - JavaScript | MDN (mozilla.org)
indexOf() 方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
getSelectedItem(){
const selected = this.container
.querySelector('.slider-list__item--selected');
return selected
}
getSelectedItemIndex(){
return Array.from(this.items).indexOf(this.getSelectedItem());
}
关于getSelectedItemIndex()函数
其大致意思为 返回数组类型的列表中的被选中的滚动页面中的一个的第一个索引
//索引即为序号
slideTo(idx){
const selected = this.getSelectedItem();
if(selected){
selected.className = 'slider-list__item';
}
const item = this.items[idx];
if(item){
item.className = 'slider-list__item--selected';
}
}
slideTo(idx)函数
原理是将标的为slider-list__item--selected与其他slider-list__item的滚动页面调换标的--selected实现滑向其他分页
slideNext(){
const currentIdx = this.getSelectedItemIndex();
const nextIdx = (currentIdx + 1) % this.items.length;
this.slideTo(nextIdx);
}
slideNext()
原理:循环队列的思想
setInterval() - Web API 接口参考 | MDN (mozilla.org)
Window 和 Worker 接口提供的 setInterval() 方法重复调用一个函数或执行一个代码片段,在每次调用之间具有固定的时间间隔。
setInterval({} => {
slider.slideNext();
} ,2000);
通过控制流来实现点
使用自定义事件来解耦
使用div实现四个小圆点
EventTarget.addEventListener() - Web API 接口参考 | MDN (mozilla.org)
EventTarget.addEventListener() 方法将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。 事件目标可以是一个文档上的元素 Element,Document和Window或者任何其他支持事件的对象 (比如 XMLHttpRequest)。
addEventListener()的工作原理是将实现EventListener的函数或对象添加到调用它的EventTarget上的指定事件类型的事件侦听器列表中。
controller.addEventListener('mouseover', evt=>{
const idx = Array.from(buttons).indexOf(evt.target);
if(idx >= 0){
this.slideTo(idx);
this.stop();
}
});
使用大量JavaScript来构造组件的缺点:不够灵活
解决方法:
重构:插件化
解耦
- 将控制元素抽取成插件
- 插件与组件之间通过依赖注入方式建立联系
应用函数&知识
Array.prototype.forEach() - JavaScript | MDN (mozilla.org)
forEach() 方法对数组的每个元素执行一次给定的函数。
关于箭头函数:箭头函数 - JavaScript | MDN (mozilla.org)
基础语法
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
//相当于:(param1, param2, …, paramN) =>{ return expression; }
// 当只有一个参数时,圆括号是可选的:
(singleParam) => { statements }
singleParam => { statements }
// 没有参数的函数应该写成一对圆括号。
() => { statements }
高级语法
//加括号的函数体返回对象字面量表达式:
params => ({foo: bar})
//支持剩余参数和默认参数
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => {
statements }
//同样支持参数列表解构
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6
关于剩余参数:剩余参数 - JavaScript | MDN (mozilla.org)
剩余参数语法允许我们将一个不定数量的参数表示为一个数组。
使用了plugin的相关构造方法,提高了代码的灵活性
在对组件进行修改和删减时,不用修改大量代码
这种插件化(模块化)的思想,对于未来的项目开发中提高改动效率,具有积极意义。
重构:模板化
解耦
- 将HTML模板化,更易于扩展
组件框架
抽象
- 将组件通用模型抽象出来
总结
- 组件设计的原则:封装性、正确性、扩展性、复用性
- 实现组件的步骤:结构设计、展现效果、行为设计
- 三次重构
- 插件化
- 模板化
- 抽象化(组件框架)
过程抽象
- 用来处理局部细节控制的一些方法
- 函数式编程思想的基础应用
Example
操作次数限制
- 一些异步交互
- 一次性的HTTP请求
高阶函数
此种函数的返回值仍为函数,直到根部前,其会一直执行。
执行方式与遍历相似
Once
为了能够让“只执行一次“的需求覆盖不同的事件处理,我们可以将这个需求剥离出来。这个过程我们称为过程抽象。
常用的高阶函数
HOF
为什么要使用高阶函数?
使用高阶函数能大大减少我们使用非纯函数的可能性
而非纯函数越多,可维护性越差
编程范式
命令式与声明式
命令式
其强调怎么做
let list = [1, 2, 3, 4];
let mapl = [];
for(let i = 0; i < list.length; i++) {
mapl.push(list[i] * 2);
}
声明式
其代码更加简洁
let list = [1, 2, 3, 4];
const double = x => x * 2;
list.map(double);
在面对多分支时:
命令式需要新添加分支以及if-else
而声明式直接添加功能即可
写在最后
Javascript作为前端三剑客里的杀手锏,是前端由静态页面到交互式页面的一大跨步
学好Javascript 对我们的前端学习历程,是里程碑式的意义 将使我们无往而不利