1. toggle button
See the Pen toggle button via css by lu (@luchen) on CodePen.
小记:
有几个重要点呐:
- input 的id与 label的for属性对应,使得label可以检测input的check事件,否则点label是不能触发check的。
- css3中:checked 属性,” + “兄弟选择符。使得可以对选中状态下的label进行css编写
- todo 用transform,尽量不用left这些。以达到平滑效果 【done】
确实过渡会平滑很多。
2. scrollbar
See the Pen js实现滚动条 by lu (@luchen) on CodePen.
recipe:
- scrollTop
- height(div高度)
- 文档内容高度(如果是普通的box里面的,则ele.scrollHeight)
这边是以一个小的div为例。
如果想全局滚动条,类似于阮一峰es6教程上的那种效果。
则应该相应的变为
|
|
补充知识:
element.scrollTop是滚动过程中文档超出视窗的部分,它的最大值就是document.height-element.height,即为progressbar为100%的时候。
两幅图可以说明:还有一种纯css做的方法
CSS only scroll indicator。思路主要就是用一个斜对角的图形,然后z-index =-1,只留出height为比如2px的区域,这样滚动条动时,显示的部分就在慢慢变宽。
3. 模拟操作
很久以前我萌还在用jquery的时候,很喜欢用的一个函数是trigger,但是离开了jquery,还有什么方法可以实现同样的问题,楼主一直很困惑…一直到看了mdn的相关api,具体demo请戳自定义事件及触发
划重点就是:
|
|
See the Pen trigger event by lu (@luchen) on CodePen.
references:
4. css做tab切换
todo
- background-clip: 裁剪,从 border-box开始。
- background-origin: 显示图片,从padding-box开始
to summary:
- background详解
- css div p(div下的所有子元素,包括孙子), div>p(div的直接子元素中的p),div+p(div的直接后兄弟,1个),div~p(div后面的所有p兄弟)
5. slider
楼主在开发这部分组件,用的是原生的html5的input中的type=range,实现了这么几个功能:
- 滑动+tooltip
- 左侧部分高亮
- step滑动
- 显示step tick
基本按照ant-design的接口来写的。但是遇到一个尴尬的问题就是…没有办法实现范围选择…需要重新开发..
recipe:
html5 input(type:range)
选择器:
6. 无限滚动
楼主最近在用vue开发cnode的移动端,首页部分有滚动列表,因为我们之前提到过debounce延缓input框发送ajax联想请求。那么这边我们就需要用throtte去实现无限滚动。(无限滚动的原理就是在滚动事件+分页请求+节流)
具体为什么不用debounce,需要体会的是debounce是在停止项某事件或者超过某个限时时才执行一次。滚动并不需要用户在停止scroll才去加载,而是应该在滚动的过程中定时去请求。所以用throtte。
throtte的实现是最简单的版本:
|
|
在实现过程中,还有这么几个问题:
楼主最开始的思路:方向检测+缓存。直接在滚动时发送请求(给定page初始值,根据上下滑动方向page++/page–),同时把每一页的数据存储下来。下次发送请求前,先根据页数判断是否已有缓存。上滑的话,不请求,满足需求。上滑一段时间后下滑,因为该页数已经访问过,数据已有,那么也不请求。满足需求。
所以,现在的关键问题在于:怎么检测这个scroll的上下顺序
查阅了资料,发现普遍是通过前后两次的scrollTop来检测的。楼主写了一个12345678function isScrollDown(initTop,cb){const curTop = document.documentElement.scrollTop;let isDown = false;if(curTop>initTop){isDown = true;cb(curTop);return isDown;}
12345678910111213141516171819202122232425262728
//调用,滚动检测fetchWhenScroll(){ const isDown = isScrollDown(this.initTop,(curTop)=>{ this.initTop = curTop; ); isDown? this.page++ : this.page--; //1,方向检测 this.fetchPage(this.page);},fetchPage(page){ if(responseDict[page]) return; //2,缓存判断 axios.get('https://cnodejs.org/api/v1/topics',{ params:{ page, ... } }) .then(response=>{ if(response.data){ const appendedList = this.getTransformedResponse(response.data); responseDict[page] = appendedList; //3,缓存数据 this.postList = [...this.postList,...appendedList]; } }) .catch(err=> console.log(err));}
scrollTop是文档的top=0处位置,到window的top=0位置的间距。具体的可以看上面scrollbar的示意图。
但是仔细一想,实际上是有问题的。当下滑时,会不停的page++,fetch serverlist。当文档实际上已经结束时。由于还在滚动,page会继续++。,所以要加一个if(response.data)的判断。如果没有数据,就啥也不干。
第二种思路,是看一篇无限滚动的文章看到的(Debouncing and Throttling Explained Through Examples)。主要原理是检测离底部的距离。当快接近底部时发送请求。
视窗底部距离文档底部的距离:
let height = \$(document).height() - \$(window).scrollTop() -$(window).height();应用场景:
- 实现回到顶部: scrollTop ===0
- 检测底部: scrollTop === documentHeight- windowHeight
具体的关于scroll,楼主上面的scrollbar里面也有介绍。可以瞄一眼。
|
|
这种方法的好处在于,避免方向的判断,上滑的时候 distanceToDocBottom实际上是变大的,那么就不需要进行请求。同时由于距离底部的距离限定好,那么从本次加载数据,到下次加载数据,实际上是把本次获得的数据滚动完以后再进行加载的。但是有一点问题是,貌似滑动到最下面的时候会停止,需要上滑一部分才会响应。而且当滚动很多页的时候,distanceToBottom会大于设定的gap。就不会发送请求。待解决。
除此之外,因为公式是jquery版本的。楼主试了很多兼容的原生版本,但是都不太对…就暗搓搓的去github上面搜了jquery这部分的源码…捂脸。
补充
|
|
- 优化(todo):
- 缓存dom节点。
- 用raf代替throtte,比较滑动的平滑效果。用debounce对比下效果。
===2016/11/23 更新
楼主的throtte是有点问题的,看了下underscore的函数说明,有两点:
- lastTime的初始值:
api的本意是一调用这个throtte才会设置lasttime,然后在此基础上去进行+wait.而楼主是在创建这个闭包的时候就把lasttime给定义了。也就是说如果
let test = throtte(console.log.bind(this,3),3000)。
在新建test后立刻test()执行。是不会运行的。因为达不到时间。
如果过一段时间test().那么才会执行。违背了立刻执行的本意。 2.原api中有leading,trailing的设置:
leading是指一调用test(),是否会立即执行(false表明不立即执行)。trailing是指,(trailing的前提是设置了settimeout,在0-wait内进入的函数都会被取消到最后再执行)。那么是否在最后真正执行,就是靠这个trailing。注意。leaing和trailing是不可以同时设置false的。因为这样的话介个函数永远都不会执行=。=,头尾都拒绝了呢。。。下面po下楼主现在的版本。- next函数中的this丢失,fix
|
|
css3常用
- 伪类
- :focus
- :checked
- :target