最近在阅读《高效前端:Web高效编程与优化实践》这本书,书中介绍了前端高效编程的优化实践和前端基础。本文将结合个人的理解介绍部分高效编程的例子。
能用HTML/CSS解决的问题就不要用JS
自定义radio/checkbox的样式
表单中原生的radio/checkbox的样式各个浏览器都不太一致。要想统一样式,一种做法是自己div/span
去画,然后去监听单击事件。这种做法就是逻辑控制完全要自己写,还有原生事件change
也无法使用。
这里可以通过CSS提供伪类checked
来实现自定义样式。原理是把一个checkbox
和一个用来自定义样式的span
写在一个label
里面,checkbox
始终隐藏。
<style>
input[type=checkbox]{
display: none;
}
/*未选中的checkbox的样式*/
.checkbox{ /* 实现略 */ }
input[type=checkbox]:checked + .checkbox{ /* 实现略 */ }
</style>
<label for="apple">
<input type="checkbox" id="apple">
<span class="checkbox"></span>
</label>
需要根据个数显示不同样式
有1~3个items要显示在同一行, 但是item的个数不一定,就一个的话item占宽100%,两个时各占50%,三个时各占33%。显然你可以用js来计算,但是这样有点繁琐。
我们可以通过CSS3的first-child
和nth-last-child
来实现个数的区分
<style>
li {
width: 100%
}
li:first-child:nth-last-child(2),
li:first-child:nth-last-child(2) ~ li{
width: 50%
}
li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li{
width: 33%
}
</style>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
用CSS画一个三角形
这个技巧应该是比较常见,通过把宽高设置为0,同时只设置一个边的border来画三角形。下面提供一些其他三角形画法:
// 斜边在左边的三角形
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
border-left: 50px solid #000;
// 直角三角形
border-left: 60px solid transparent;
border-right: 0 solid transparent;
border-bottom: 40px solid #000;
// 等边三角形
border-left: 28px solid transparent;
border-right: 28px solid transparent;
border-bottom: 40px solid #000;
减少前端代码耦合
JS/CSS/HTML的耦合
不推荐直接在JS里面更改样式属性, 应该通过增删类来控制样式,除了scroll和mousemove
策略模式
// common
function popCallback(popType){
switch(popType){
case: "favHouse":
favHouse();
break;
case: "saveSearch":
saveSearch();
break;
}
}
// strategy
var popCallback = {
favHouse: function(){ /*do sth.*/ },
saveSearch: function(){ /*do sth.*/ }
}
if(typeof popCallback[popType] === "function"){
popCallback[popType]();
}
JS书写优化
按强类型风格写代码
这边其实也可以在项目中静态类型检查器(Flow、TypeScript)来优化代码。书中有介绍几点还不错建议:
- 定义变量的时候要指明类型
var num = 0,
str = '',
obj = null;
- 不要随意改变变量的类型
// bad
var num = 5;
num = "-" + num;
// good
var num = 5;
var sign = "-" + num;
- 函数的返回类型应该是确定的
// bad
function getPrice(count){
if(count < 0) return "";
else return count * 100;
}
// good
function getPrice(count){
if(count < 0) return -1;
else return count * 100;
}
减少作用域查找
全局作用域比较复杂,所以查找属性比较慢。局部作用的查找是很快的
// bad
var url = "";
if(window.location.protocal === "https:"){
url = "wss://xxx.com" + window.location.pathname + window.location.search;
}
// good 缓存成局部变量
var url = "";
var location = window.location;
if(location.protocal === "https:"){
url = "wss://xxx.com" + location.pathname + location.search;
}
避免==的使用
我们的代码中应该避免==
的使用,应该使用===
,这样可以避免js类型转换带来的一些意外的结果。
==
建议的使用场景是判断变量是否为空的时候,即if(obj == null)
使用ES6简化代码
- 使用箭头函数取代小函数
var nums = [4, 8, 1, 9, 0];
nums.sort((a, b) => b - a);
- 字符串拼接
var tpl =
` <div>
<span>1</span>
</div>
`;
var url = `/list?page=${page}&type=${type}`;
- 块级作用域变量
var tasks = [];
for(let i = 0; i <= 4; i++){
tasks.push(function(){
console.log("i is " + i);
});
}
for(var j = 0; j < tasks.length; j++){
tasks[j]();
}
增强用户的体验
加Loding效果
常见的Loading都有图片加载、AJAX请求、上传文件进度条。还有一个最近流行的骨架屏(skeleton loading)
样式、文案
这部分可以去看下一些UI库的基本理念和设计原则,如antd-design
用好Chrome Devtools
Chrome Devtools调试建议可以看下F12里面的官方文档。
打印
console.table
打印对象数组console.dir
能递归打印对象的所有属性,打印一个DOM结点
检查没有用的CSS/JS
devtools的Coverage标签栏,没有用到的用红色表示, 用到的用绿色表示
研究重绘
devtools有一个Renders可以用来研究重绘
总结
书中的优化实践点还是很多的,我这边就介绍部分相对比较常用的。其实优化实践给出了比较好的方案,但是实际还是要结合具体情况来选择方案的。