这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
各司其职
案例: 深夜食堂实现白天模式和夜晚模式切换的三个版本
1.版本一,使用js来操作样式
const btn=document.querySelector('button');
btn.addEventListener('click',(e)=>{
const body=document.body
if(e.target.innerHTML=='白天'){
body.style.color='black';
body.style.backgroundColor='white';
e.target.innerHTML="夜晚";
}else{
body.style.color='white';
body.style.backgroundColor='black';
e.target.innerHTML="白天";
}
})
代码链接code.juejin.cn/pen/7189589…
2.版本二,使用js操作className
const btn=document.querySelector('button');
btn.addEventListener('click',(e)=>{
const body=document.body;
if(e.target.innerHTML=='夜晚'){
body.className='night';
e.target.innerHTML='白天'
}else{
body.className='';
e.target.innerHTML='夜晚';
}
})
代码链接 code.juejin.cn/pen/7189819…
3.版本三,零js
1.使用checkbox来实现状态切换
2.使用label标签的for属性将状态切换绑定到id为modeBtn的元素上
3.使用::after,通过content的设置来实现modeBtn元素内容的改变
4.通过动画transition: all 1s实现动画过渡效果
代码链接 code.juejin.cn/pen/7189827…
结论:
让html、css、js各司其职,html负责页面框架构建,css负责样式渲染和动画效果,js负责交互和操作事件的。尽量避免不必要的由js直接操作样式,可以用className来表示状态,纯展示类的可以用零js
组件封装
组件是指web页面上抽出的一个个包含模板(html)、样式(css)、功能(js)的单元,好的组件具有封装性、正确性、扩展性、复用性这四大特性
轮播图
1.组件封装的方法:
- 结构设计
- 展现效果
- 行为设计
API(功能)
event(控制流)
实践
1.通过将不是第一张的图片设置为
transition: opacity 1s; opacity: 0;
第一张图片设置为
transition: opacity 1s; opacity: 1;
将图片实现重叠
2.通过改变className来实现轮播
3.通过index来实现控制
4.用自定义事件实现小圆点和图片之间的状态跟随
const detail = { index: idx }
const event = new CustomEvent('slide', { bubbles: true, detail })
this.container.dispatchEvent(event)
this.container.addEventListener('slide', evt => {
const idx = evt.detail.index
const selected = controller.querySelector('.slide-list_control-button--selected');
if (selected) selected.className = 'slide-list_control-button';
buttons[idx].className = 'slide-list_control-button--selected';
})
自定义事件:
juejin.cn/post/699015…
轮播图-2 - 码上掘金 (juejin.cn)
2.优化
1.优化考虑的方向可以是组件的灵活性,如:是否可以删除这个两边的按钮。为了达到这个目的,我们可以采用解耦的方式,将控制元素抽取成插件,插件与组件之间通过依赖注入的方式建立联系
定义注册插件方法
registerPlugins(...plugins) {
plugins.forEach(plugins => plugins(this));
}
调用注册插件方法
slider.registerPlugins(pluginController, pluginPrevious, pluginNext)
标签有id就可以直接用id来得到元素,但是该id不能被占位
2.由于如果有html的改变我们还需要去改动html代码,所以,为了进一步优化,我们可以将html模板化
code.juejin.cn/pen/7192066…
3.这就是优化的终点了吗?当然不是,我们还可以将组件通用模型给抽象出来(组件框架)
4.扩展点:1.插件和组件可以融合在一起,子组件作为父组件的插件 2.这里只对html进行了模板化,没有对css进行模板化,如果我们后续打算更改样式可能会有一定的麻烦,所以我们还可以对css进行模板化
过程抽象
定义
通过高阶函数来将过程抽象,如:为了实现只执行一次这个过程,我们实现一个名为once的高阶函数。
高阶函数:参数为函数,返回值也是函数的函数,通常用作装饰函数,如HOF0就是一个等价高阶函数
function FOF0(fn){
return function(...args){
return fn.apply(this,args);
}
}
//其返回的函数和传入的函数一样
常用高阶函数
- once
- Throttle 节流函数
- Debounce 防抖函数
- Consumer/2 延时调用函数
- Iterative 可迭代函数
once
function once(fn){
return function(...args){
if(fn){
const ret=fn.apply(this.args);
fn=null;
return ret;
}
}
}
Throttle
节流函数,用于页面滚动,mmoucemove等事件,对频率做出限制
Debounce
防抖函数,用于自动保存,当页面内容一直在发生变化的时候不会自动保存,只有当页面的内容在多少秒内不变的时候才会保存
Consumer
如果这里有一个按钮,设置的延时时间是1s,你要连续点击它100下,那么它会每隔一秒加一下,一直加到100下为止
Iterative
实现批量操作
为什么要使用高阶函数
纯函数:结果是可以预料的,输出是确定的,在任何时候输入结果A都能得到结果B,其输入输出简单,对它的测试也简单;
非纯函数是有副作用的,结果是不可估量的,输出是由外部环境所决定的,对它的测试相对复杂,在测试时需要创建特定的环境。
一般来说高阶函数是纯函数。大量使用纯函数有助于提升一个库的可维护性
命令式和声明式
编程范式分为命令式和声明式,声明式比命令式有更多的可扩展性