如何写好JavaScript
什么才是好的JavaScript代码
写好JS的一些原则
- 各司其责:HTML、CSS和JavaScript分离
- 组件封装:更多是与UI打交道,所有封装很重要
- 过程抽象:在处理UI交互的细节的时候,需要对数据抽象,过程抽象,让代码拥有扩展的能力,更加通用
深夜食堂
怎么样去切换样式
版本一
const btn = document.getElementById('modeBtn');
btn.addEventListener('click',(e)=>{
const body = document.body;
if(e.target.innerHTML ==='☀'){
body.style.backgroundColor = 'black';
body.style.color = 'white';
e.target.innerHTML = '🌙';
}else{
body.style.backgroundColor = 'white';
body.style.color = 'black';
e.target.innerHTML = '☀';
}
});
版本二
const btn = document.getElementById('modeBtn');
btn.addEventListener('click',(e)=>{
const body= document.body;
if(body.classNmae !== 'night'){
body.className = 'night';
}else{
body.className = '';
}
});
以上版本一代码有什么问题呢?
如果来优化,该怎么做呢?
- 用javascript来替代了css
- 若想改动颜色,则会改动js代码,版本二代码就不会改动
- 在团队里,希望看到第二个代码的
版本二比起上一版本好在哪里
- 各司其责
结论
- HTML/CSS/JS各司其责
- 应当避免不必要的由JS直接操作样式
- 可以用class来表示状态
- 纯展示类交互寻求零JS方案
组件封装
例子:用原生JS写一个电脑网站的轮播图,应该怎么实现?
结构
- 轮播图是一个典型的列表结构,我们可以用无序列表ul元素来实现
.slider{
position:relative;
width:400px;
height:300px;
}
.slider-picture{
position:relative;
list-style-type: none;
}
.one,.noe-item{
position:absolute;
transition: opacity 1s;
opacity: 0;/*设置透明度 */
}
img{
width:400px;
height:300px;
}
.one:first-child {
opacity: 1;
}
.one-item{
list-style-type: none;
position:absolute;
transition: opacity 1s;
opacity:1;
}
window.onload = () => {
let itemList = document.getElementsByClassName('one')
let index = 0
setInterval(() => {
itemList[index].style.opacity = 0
index = (index + 1) % itemList.length
itemList[index].style.opacity = 1
}, 2000)
// for (let item of itemList) {
// } 4 % 2 [1, 2, 3]
}
表现
- 使用CSS绝对定位将图片重叠在同一个位置
- 轮播图切换的状态使用修饰符(modifier)
- 轮播图的切换动画使用CSS transition
行为:API
- Slider
+getSelectedItem()
当前选中的图片元素
+getSelectedItemIndex()
当前选中的图片元素在这个列表的下标
+Slide To()
会SildeTo到某个特定的index的元素上
+SlideNext()
轮播下一张图片
+SlidePrevious()
轮播上一张图片
总结
- 组件设计的原则:封装性、正确性、扩展性、复用性
- 实现组件的步骤:结构设计、展现效果、行为设计
- 三次重构:插件化、模板化、抽象化(组件框架)
javascript编码原则之过程抽象
过程抽象
- 用来处理局部细节控制的一些方法
- 函数式编程思想的基础应用
react中应用过程抽象比较多的就是hooks
高阶函数
once
- 为了能够让只执行依次的需求覆盖不同的事件处理,我们可以将这个需求剥离出来,这个过程我们称为过程抽象
function once(fn){}
return function(...args){
if(fn){
const ret = fn.apply(this.args);
fn = null;
return ret;
}
}
HOF
- 以函数作为参数
- 以函数作为返回值
- 常用于作为函数装饰器
- once
- Throttle
- Debounce
跟随鼠标,但是是在停止之后再跟随的
- Consumer/2
每隔一个时间,再去调用function的
- Iteratlive
会返回一个新的函数
思考和讨论
- 为什么要使用高阶函数?
- 什么是纯函数?(eg: add()函数)
得出来的值不可能会有其他值,是确定的。而非纯函数,每次得出的结果都是不一样的
编程范式
命令式
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);
声明式的写法天然的比命令式可扩展性
总结
- 过程抽象/HOF/装饰器
- 命令式/声明式
javascript代码质量优化之路
交通灯状态切换
- 实现一个切换多个交通灯状态切换的功能
感受
学习这四节课,让我清楚的知道了实际操作的重要性,不光要听,最主要的是自己会,很多时候,听完了再去操作会发现自己又不会了,而且无从下手