CSS
1、-webkit-overflow-scrolling : touch;
IOS下用这个属性可以实现流畅滑动,但要注意和这几个属性一起用(Android上还是略卡)
.container{
-webkit-overflow-scrolling : touch;
overflow-y:auto;
height:固定高度
}
如果.container有同级元素,且该元素用fixed定位,那么.container也必须使用定位属性,且设置z-index值,否则该属性可能不会生效。
注:Android下要实现类似流畅滑动,可尝试使用iScroll.js,地址在这
2、实用css
-webkit-tap-highlight-color: rgba(0,0,0,0); //去除点击阴影,IOS私有
user-select:none; //禁止用户选择文本
-webkit-touch-callout: none //禁止图片长按弹出菜单,img和a标签都要加
pointer-events: none; //禁止一切鼠标事件
-webkit-appearance: none; //消除输入框和按钮的原生外观
// 实现谷歌浏览器支持<12px字体,比如显示7px,可采用如下方案
.test_tag{
font-size:12px;
-webkit-transform-origin-x: 0;
-webkit-transform: scale(0.5833333333333334); // 7/12=0.5833
}
3、高请显示图片问题 image-set,最好用SVG来做
image-set解决苹果的高请显示图片问题,不支持image-set的浏览器下,他们解析background-image中的背景图像;支持image-set:
如果你的浏览器支持image-set,而是普通屏下,此时浏览器选择image-set中1x背景图像
如果你的设备是高清屏幕下(ppi大于320时)时浏览器会选择image-set中@2x背景图像。
仅支持background-image属性,而不能使用在'<img>'标签中,老的安卓4.4以下的不支持
优点:image-set不需要告诉浏览器使用什么图像,而是直接提供了图像让浏览器选择
```javascript
selector{
background-image:url(no-image-set.png);
background:image-set(url(foo-lowres.png) 1x,url(foo-highres.png) 2x) center;
}
4、1px 边框方案
@mixin border-1px ($color) {
position:relative;
&::after{
diplay:block;
position:absolute;
content:"";
left:0;
bottom:0;
width:100%;
border-top:1px solid $color;
}
@media(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5){
&::after{
-webkit-transform:scaleY(0.7);
transform:scaleY(0.7);
}
}
@media(-webkit-min-device-pixel-ratio:2),(min-device-pixel-ratio:2){
&::after{
-webkit-transform:scaleY(0.5);
transform:scaleY(0.5);
}
}
@media(-webkit-min-device-pixel-ratio:3),(min-device-pixel-ratio:3){
&::after{
-webkit-transform:scaleY(0.33);
transform:scaleY(0.33);
}
}
}
5、移动端垂直居中问题(带四周边框)
为了兼容IOS和Android,可设置line-height比height少1-2个像素,flex都不好使的
6、做弹窗时,会涉及到z-index问题,最好将弹窗的div层级与主内容并列
7、伪类与伪元素的区别:有没有创建一个文档树之外的元素
8、~ 与 + 选择器的区别: + 是选中紧挨其后的兄弟元素,~是选中其后的兄弟元素,不一定紧挨
9、页面出现垂直方向滚动条时抖动问题
原理是:vw取的是window.innerWidth,包含滚动条;100%不包含滚动条
.wrap-outer {
margin-left: calc(100vw - 100%);
}
10、父元素设置了左右padding,子元素想突破这个padding,怎么做?
.parent{
overflow-x:hidden; //消除水平方向由于滚动条导致的微小偏移
}
.child{
position:relative;
width:100vw;
left: calc((100% - 100vw) / 2);
}
JS
1、事件代理是个好的事件处理技巧,但是要特别注意代理元素的选取,一般选取body,如果出现这种层级结构body>main>button,且main设置了opacity:1,那么想在body上代理button的点击事件是做不到的,因为body被main挡住了(PC端不会,但移动端会),解决方式是将代理设到main元素上,其实这个问题的根源在于opacity会挡住比他层级底的元素,使得事件冒泡无法进行。此外不要重复执行绑定操作,否则会被绑定多次(场景:A页面跳到B页面,在B页面做了修改A页面数据的操作,修改完返回到A页面,A页面需要重新拉数据渲染页面。这时应该只执行页面渲染操作,不能再执行事件绑定操作),浏览器对匿名函数的绑定会重复绑定,对命名函数的绑定不会多次绑定。
2、monitorEvents(dom,eventName),可以模拟某元素上所有事件
3、webpack设置代理问题:
不能把backend放在backend2前面,根源在于不能使用正则匹配,导致/backend2会被/backend代理。
4、正则
要写一个复杂的正则,不一定要写成一个完整的形式;还可以通过分步的形式来实现,比如
var hasNumberReg = /[0-9]/g,
hasLetterReg = /[a-zA-Z]/g,
hasSpecialReg = /[~!@#¥\$%\^&\*\(\)-_+=:;'",\.\<\>\/\|\\?\[\]{}]/g;
// 必须包含字母数字和特殊符号的密码,可以这样分步写
hasNumberReg.test(value) && hasLetterReg.test(value)&&hasSpecialReg.test(value)
5、REM布局
设置html的font-size时机要很早才不会有闪烁的感觉,直接在head里内联以下脚本即可,rem布局可能会产生小数像素问题,这会导致使用background-img时被裁掉一点,解决方案是设置background-img时注意留点空白,也就1px的事情,具体参看这里
<script>
(function(doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
docEl.style.fontSize = clientWidth / 7.5 + 'px';
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
recalc();
})(document, window);
</script>
6、对于scroll事件或mousewheel事件,使用passive模式的监听器,可使滑动更顺畅。如何不择手段提升scroll事件的性能
window.addEventListeners('scroll',handler,{passive:true})
7、DOMContentLoaded(蓝线),Loaded(红线),First Paint(绿线)
First Paint 一般位于二者之间,但最好在DOMContentLoaded之前
对于defer的js文件会在DOMContentLoaded之前执行。js执行期间与页面渲染是一个竞态,若js操作了dom,以往的渲染会被取消。这个问题在首屏的骨架屏需要注意
8、函数节流throttle和防抖debounce
节流:保证m时间内必定执行一次,如图片懒加载,不希望滑动停止时才开始加载,而是在滑动过程中就要开始加载
防抖:m时间内触发多次只执行一次,如scroll,resize等事件的触发
// 简单的节流函数
function throttle(func, wait, mustRun) {
var timeout,
startTime = new Date();
return function() {
var context = this,
args = arguments,
curTime = new Date();
clearTimeout(timeout);
// 如果达到了规定的触发时间间隔,触发 handler
if(curTime - startTime >= mustRun){
func.apply(context,args);
startTime = curTime;
// 没达到触发间隔,重新设定定时器
}else{
timeout = setTimeout(func, wait);
}
};
};
// 简单的防抖动函数
function debounce(func, wait) {
// 定时器变量
var timeout;
return function() {
// 每次触发 scroll handler 时先清除定时器
clearTimeout(timeout);
// 指定 xx ms 后触发真正想进行的操作 handler
timeout = setTimeout(func, wait);
};
};
9、webworker使用方式
// in html
<script type="text/javascript">
// we will use this function in-line in this page
function isPrime(number)
{
if (number === 0 || number === 1) {
return true;
}
var i;
for (i = 2; i <= Math.sqrt(number); i++) {
if (number % i === 0) {
return false;
}
}
return true;
}
// a large number, so that the computation time is sensible
var number = "1000001111111111";
// including the worker's code
var w = new Worker('webworkers.js');
// the callback for the worker to call
w.onmessage = function(e) {
if (e.data) {
alert(number + ' is prime. Now I\'ll try calculating without a web worker.');
var result = isPrime(number);
if (result) {
alert('I am sure, it is prime. ');
}
} else {
alert(number + ' is not prime.');
}
};
// sending a message to the worker in order to start it
w.postMessage(number);
</script>
<p style="height: 200px; width: 400px; overflow: scroll;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce blandit tristique risus, a rhoncus nisl posuere sed. Praesent vel lorem.
</p>
// in webworkers.js
function isPrime(number)
{
if (number === 0 || number === 1) {
return true;
}
var i;
for (i = 2; i <= Math.sqrt(number); i++) {
if (number % i === 0) {
return false;
}
}
return true;
}
// this is the point of entry for the workers
onmessage = function(e) {
// you can support different messages by checking the e.data value
number = e.data;
result = isPrime(number);
// calling back the main thread
postMessage(result);
};
10、requestAnimationFrame提升滚动动画
const newScrollTop = this.getPosition(this.panes[index].$refs.content).top - this.distance
function scrollStep() {
document.documentElement.scrollTop += 5
if (document.documentElement.scrollTop < newScrollTop) {
window.requestAnimationFrame(scrollStep)
}
}
window.requestAnimationFrame(scrollStep)
可以将requestAnimationFrame看做一个钩子,刚好卡在浏览器重绘前向我们的操作伸出橄榄枝。实际上它更像定时器,每秒60次执行回调——符合屏幕的刷新频率,遇到耗时长的操作,这个数字会降到30来保证稳定的帧数。
HTML
1、IOS下input问题
- 输入框被弹起的系统键盘挡住
当输入框在底部时,往往会使用固定定位fixed,当输入框获得焦点时,系统键盘会弹起,有时键盘会挡住输入框。
解决办法:当输入框获得焦点时,用setInterval定时器不断调整input上方元素的scrollTop
当输入框失去焦点时,取消该setInterval定时器 - 输入框弹起后,点返回按钮键盘没有收起
解决方法:路由切换时,使用document.activeElement.blur()手动触发blur事件 - input几个常用事件
change:开始输入时触发
input:每次输入新值都会触发,对于根据input是否有内容来实时设置button样式很有用
关于手机端IOS系统微信中虚拟键盘遮挡input输入框问题的解决方案
IOS fixed input focus bug
2、使用content做一个三个点加载动画
本技巧来源于这里
<a href="javascript:" class="grebtn">订单提交中<dot>...</dot></a>
dot {
display: inline-block;
height: 1em; line-height: 1;
vertical-align: -.25em;
overflow: hidden;
}
dot::before {
display: block;
content: '...\A..\A.';
white-space: pre-wrap;
animation: dot 3s infinite step-start both;
}
@keyframes dot {
33% { transform: translateY(-2em); }
66% { transform: translateY(-1em); }
}
原理:1 \A可以换行;2 before元素可以覆盖其寄生元素;3 用动画调整每次显示的content;4 不支持animation时只显示三个点(优雅降级&渐进增强)
3、PC端分享到微博、QQ空间、微信的做法
- 分享到微博
function shareToXl(title,url,picurl){
var sharesinastring='http://v.t.sina.com.cn/share/share.php?title='+title+'&url='+url+'&content=utf-8&sourceUrl='+url+'&pic='+picurl;
window.open(sharesinastring,'newWindowName','height=400,width=400,top=100,left=100');
}
- 分享到QQ空间
function shareToQq(title,url,picurl){
var shareqqzonestring='http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?summary='+title+'&url='+url+'&pics='+picurl;
window.open(shareqqzonestring,'newwindow','height=400,width=400,top=100,left=100');
}
- 分享到微信
将要分享的网页链接URL转成二维码,让用户扫二维码进入微信WebView进行分享
移动端开发踩过的一些坑](https://www.zhihu.com/people/qiangdada520)
](https://zhuanlan.zhihu.com/p/30419351?utm_source=com.jianshu.haruki&utm_medium=social)