CSS是一门很神奇的语言,不少和它不相干的功能却能起到很显著的效果,有些在js看起来实现都有必定的工做量,CSS一句属性就能垂手可得的解决,下面来看几个例子(主要和js事件相关)。css
原连接html
https://notes.codelabo.cn/art...jquery
原issuescss3
https://github.com/XboxYan/no...git
不少都是开脑洞想出来的,实现效果却意外的惊人
在js中对事件禁用并不复杂,可是却容易影响到业务逻辑github
function buy(){ if(XX){ return false; } //其余业务代码 }
固然,元素也要设置相应的样式,让它看起来不可点击。工具
css对事件禁用就比较简单了,主要有两种方式动画
1. disabledthis
原生表单元素是有默认的禁用属性的,好比spa
<button disabled onclick="alert(11)">按钮</button>
能够看出,禁用的默认样式为
button:disabled { color: graytext; }
因此,在这里你能够随意的修改禁用的样式
button:disabled { color: red; } button[disabled] {/**属性选择器也行**/ color: red; } button:hover { /**:hover支持**/ color: red; } button:active,button:focus{/**不支持,其实也好理解,会触发focus()事件,因此也禁用了**/ color:red }
通常状况下,使用这种方式是比较好的,自然的禁用属性,兼容性也不错
2. pointer-events:none
这个属性应该也不陌生,最多见的用法就是禁用一个按钮,并且不局限于表单元素,任意元素都可(好比不少人喜欢用的a标签)
button.disabled { pointer-events:none; user-select:none;/*去除选中效果*/ color: graytext; }
这个属性用处不少,不少js绞尽脑汁想要过滤掉的方法,直接就用一行属性解决,这里就不展开了,网上教程不少。
<iframe height="300" style="width: 100%;" scrolling="no" title="css 禁用事件" src="//codepen.io/xboxyan/embed/KLGXjR/?height=300&theme-id=34022&default-tab=html,result" frameborder="no" allowtransparency="true" allowfullscreen="true">
See the Pen css 禁用事件 by XboxYan
(@xboxyan) on CodePen.
</iframe>
原生js中并无长按事件,一般开发者通常会顺着思路,使用定时器来完成
下面是伪代码
el.onmousedown = function(){ this.timer && clearTimeout(this.timer); this.timer = settimeout(function(){ //业务代码 },350) } el.onmouseup = function(){ this.timer && clearTimeout(this.timer); }
固然,能够借助css来完成,并且效果更好,易于控制
这里为何说是“借助”呢,由于不能彻底有css来完成,只是利用了某些特性
css3中新增了过渡和动画属性,与之相对应的也预设了这些动画的回调事件,以下
事件 | 说明 |
---|---|
transitionstart |
在开始过渡时触发 |
transitionrun |
在进行过渡时触发 |
transitioncancel |
在取消过渡时触发 |
transitionend |
在完成过渡后触发 |
animationstart |
在 animation 开始时触发 |
animationiteration |
在 animation 完成一个周期时触发 |
animationend |
在 animation 完成时触发 |
animationcancel |
在 animation 取消时触发 |
有些事件存在兼容性问题,有兴趣的能够详细研究
有了这些事件,要作一个长按事件就很容易了,这里有两种种思路,你们能够脑洞一下
假设须要延时1s;
transitionend
或者animationend
transitionstart
或者animationstart
这里以第一种状况transitionend
(过渡比动画实现要容易多,代码也少,优先用过渡)来实现
button:hover:active{ opacity:.99;/**随便选取一个不影响页面的能够过渡的样式**/ transition:opacity 1s; }
相应的,js须要监听transitionend
事件,不须要借助定时器(我的有点鄙视定时器的思想^)
el.addEventListener('transitionend',function(){ //业务代码 })
是否是精简不少呢,须要改长按时间能够直接经过css来控制
这里封装了一下自定义事件,能够更好的在项目中使用(虽然代码自己就不多了)。
<iframe height="300" style="width: 100%;" scrolling="no" title="css 长按事件" src="//codepen.io/xboxyan/embed/KLxXNZ/?height=300&theme-id=34022&default-tab=css,result" frameborder="no" allowtransparency="true" allowfullscreen="true">
See the Pen css 长按事件 by XboxYan
(@xboxyan) on CodePen.
</iframe>
在jquery
中有一个once
(好像是这个)方法,表示绑定一次性事件,点击一次后就再也不生效。
原生js实现这个也不复杂,一般作法就是定义一个标识,点击后改变一下,下面是伪代码
el.onclick = function(){ if(!this.once){ //业务代码 this.once = true; } }
借助上面的思路,css也能够实现相似的效果,深究了一番,总结如下两个方法
1.animationend
animationend
是动画结束后触发,显然咱们能够在这里作文章
好比咱们能够在初始状态给一个暂停状态animation-play-state:paused
,而后在点击时运动animation-play-state:running
,结束后一直保持在最后状态animation-fill-mode: forwards
.button{ animation: once .01s paused forwards;/**给一个足够小的运动时间,确保可以在`:active`时运动完成**/ } .button:hover:active{ animation-play-state:running; } @keyframes once { to{ opacity:.8; } }
js只须要对animationend
进行监听
el.addEventListener('animationend',function(){ //业务代码 })
2.纯css实现
不知道在上面的例子中有没有发现,在动画结束时把元素禁用会怎么样?
@keyframes once { to{ opacity:.8; pointer-events:none; user-select:none; } }
<button class="button" onclick="fn()">按钮</button>
这样就能够在运动完直接禁用,好像很完美?
事实上,这里运动的时间很难把控,你们都知道,onclick
实际上是包含按下和抬起两个过程的,若是抬起的太慢,那么此时元素已经禁用了,触发不了事件;若是抬起太快,若是快速点击,因为还没运动完成,会触发屡次事件。
解决方式也很简单,用onmousedown
代替便可
<button class="button" onmousedown="fn()">按钮</button>
<iframe height="300" style="width: 100%;" scrolling="no" title="css 单次事件" src="//codepen.io/xboxyan/embed/ZNqrbX/?height=300&theme-id=34022&default-tab=css,result" frameborder="no" allowtransparency="true" allowfullscreen="true">
See the Pen css 单次事件 by XboxYan
(@xboxyan) on CodePen.
</iframe>
你们都知道window
有个onresize
事件,能够在窗口拉伸的时候触发,而后就能实时获取窗体的尺寸等等属性。
window.onresize = function(ev){ //业务代码 }
可是,普通的元素却没有这个监听,好比
div.onresize = function(ev){ //不生效... }
为何须要这个功能呢?
你们可能知道有这样一个属性,能够原生拉伸元素,改变尺寸
.box{ overflow: hidden;/**须要配合overflow才能生效**/ resize: both; }
只需一个属性,就能够实现元素的拉伸(虽然稍有瑕疵),不须要大量的js来计算。
视觉展现还好,可是若是须要实时知道元素的尺寸怎么办呢,js一般有两种思路
1. onmousemove事件
拉伸的时候很天然的想到是有鼠标按住而后拖拽完成,因此能够给元素添加onmouse-*
一系列事件,同时要注意鼠标抬起要取消监听
//大概是这样的逻辑 div.onmousedown = function(){ div.onmousemove = fn;//监听 div.onmouseup = function(){ div.onmousemove = null; } }
2. 定时器
借助setInterval
或者requestAnimFrame
来实现监听,一样是须要注意取消监听的时机
//大概是这样的逻辑 div.onmousedown = function(){ this.timer && clearInterval(this.timer) this.timer = setInterval(fn,300);//监听 div.onmouseup = function(){ this.timer && clearInterval(this.timer) } }
很显然,上面的方法都不是特别的温馨,不少状况下都会出现监听取消的问题,致使不停的触发,影响体验。
这时候,又轮到css出场了,不少时候js以为实现起来不畅的时候均可以用css的思惟来从新认识。
那么,如何借助css来监听这些呢?
能够从过渡和动画两个思路来考虑。
1. CSS过渡
首先,咱们能够知道的是,在经过resize: both
进行元素拉伸的时候,改变的是width
和height
,这一点能够从开发者工具直接看到
咱们须要经过transitionrun
或者transitionend
来监听width
和height
,因此须要给这两个属性加上过渡
.box{ transition:width .3s,ehight .3s;//分别给width和height设置过渡,其余属性不须要 }
这样就能够拿到监听了,不过这种方式有一个弊端,因为过渡须要时间,因此有一种不跟随,卡顿的感受。
因此咱们来看第二种方式
2. animationiteration
css
动画能够设置播放次数,若是设置成animation-iteration-count: infinite
就表示无限轮播,配合animationiteration
回调,不就能够实现监听了么
.box:active{ animation: resize .3s infinite forwards; } @keyframes resize{ to { opacity: .99;/**用一个可有可无的属性来触发动画**/ } }
js很简单,一个监听就能解决问题,也不须要什么取消监听什么,这些都已经在css完成了
el.addEventListener('animationiteration',function(){ //业务代码 })
这里是每一个动画完成一次就回调一次,因此咱们能够经过设置动画时长来控制监听的频率,好比上面是.3s
的触发频率。
下面写了一个demo,能够实现自定义onresize
事件
<iframe height="300" style="width: 100%;" scrolling="no" title="css resize事件" src="//codepen.io/xboxyan/embed/PvyeOL/?height=300&theme-id=34022&default-tab=css,result" frameborder="no" allowtransparency="true" allowfullscreen="true">
See the Pen css resize事件 by XboxYan
(@xboxyan) on CodePen.
</iframe>
以上经过借助css,实现了许多js都很棘手的问题,可能还会有更多的应用场景,欢迎小伙伴留言讨论~
若是有新的想法,会第一时间更新在 https://github.com/XboxYan/no... ,多多关注