title: 奇巧淫技
date: 2014-12-22 12:39:04
categories: [技术]
tags: [CSS, javascript]

comments: true

[TOC]

杂技

<– more –>

加快页面打开速度——优化首屏加载

  1. 减少渲染阻塞

放在head标签中的css和js资源都会阻塞渲染。

  1. 避免head标签JS堵塞
    两种方法,defer延迟加载和加将脚本放在body后执行。两者区别在于defer加载是并行加载资源的,就是说defer资源正常顺序加载,但是延后执行。由于在同一时间浏览器对同一域名下的资源请求,最多只能建立有限个TCP请求(Chrome是6个),所以需要权衡两种方式,如果交互大于展示使用defer,反之则反。
  2. 减少head标签里的CSS资源
    CSS资源必须放在head中,如果放在body中,会引发dom重排和显示闪烁。所以一定要减小CSS体积。1、减少在样式文件中使用base64;2、把CSS写成内联的——谷歌和淘宝PC端就是这么做的——减少请求——每次http请求的花销都很大——DNS查找、tcp链接、建立http链接。
  1. 优化图片
  1. 使用响应式图片

    1
    2
    3
    4
    5
    6
    7
      <img srcset="photo_w350.jpg 1x, photo_w640.jpg 2x" src="photo_w350.jpg" alt="">
      /*或*/
      <picture>
        <source srcset="banner_w1000.jpg" media="(min-width: 801px)">
        <source srcset="banner_w800.jpg" media="(max-width: 800px)">
        <img src="banner_w800.jpg" alt="">
    </picture>
  2. 延迟加载图片
    主要懒惰加载图片

  1. 压缩和缓存
  1. gzip压缩
    在http服务器如nginx中开启gzip压缩
  2. Cache-Control
    1. last-modified:第一次请求后返回(如果开启,此处是一个绝对时间),如果在有效期内则返回304,这里只是避免了资源重新传输;
    2. Cache-Control:设置获取时长(相对时间),比如max-age:3600代表一小时后过期。max-age优先级高于last-modified,如果在有效期内不发请求。
    3. Etag:使用模板渲染则last-modified失效,max-age只是粗略设定时长。如果开启Etag,则第一次请求资源会返回Etag,再次使用是请求头If-None-Match中携带资源Etag信息,如果匹配则返回304。Etag非常低的重合风险——代表文件以及修改但是却返回304,所以对于非常敏感的实时信息要谨慎使用Etag。
  1. 其他方案

DNS预读取

1
  <link rel="dns-prefection" href="https://www.google-analytics.com">

提取解析DNS,并行,不阻塞页面渲染。

html优化
减少tab空格及体积较大的svg等。
代码优化
html嵌套忌过深,css选择器匹配,js闭包等。

参考

http://blog.csdn.net/BaiHuaXiu123/article/details/68925120

JS创建多线程

http://www.ruanyifeng.com/blog/2014/10/event-loop.html

关于回调判断

保证回调存在且必须是函数引用或者函数表达式

1
(callback && typeof(callback) === "function") && callback()

异步与回调

先来个segmentfault上有人做的比喻:

你有事去隔壁寝室找同学,发现人不在,你怎么办呢?
方法1,每隔几分钟再去趟隔壁寝室,看人在不
方法2,拜托与他同寝室的人,看到他回来时叫一下你

前者是轮询,后者是回调。

那你说,我直接在隔壁寝室等到同学回来可以吗?

可以啊,只不过这样原本你可以省下时间做其他事,现在必须浪费在等待上了。把原来的非阻塞的异步调用变成了阻塞的同步调用。

JavaScript的回调是在异步调用场景下使用的,使用回调性能好于轮询。

查看

异步回调,异步与回调没有直接关系,回调只是异步一种实现方式——回调不一定都是异步的,还有同步回调

一个简单的原生AJAX实现

1
2
3
4
5
6
7
8
var xhr = new XMLHttpRequest();
    xhr.open('POST', url, true);   //第三个参数决定是否采用异步的方式
    xhr.send(data);
    xhr.onreadystatechange = function(){
        if(xhr.readystate === 4 && xhr.status === 200){
                ///xxxx
        }
    }

http

0. vpn

104.224.165.250 443 weixy79@xu…

weixy79@ mysql密码 参考文件
登陆网址

1. 文章阅读列表

  • 7.11Chrome 35个开发者工具的小技巧

2. 关于定位

  1. 可以理解fixed和absolute是相同的,只是相对定位父元素不同
  2. 两者都是脱离了文档流,也就是说后面正常文档流的元素的位置不受fixed和absolute的影响,前者是相对于视窗定位,后者是相对于非static的父元素定位
  3. relative相对定位没有脱离文档流,后面的元素相对于其正常文档流定位参考,其参考位置是相对于其初始位置定位,其初始位置不会被占用
  4. 需要注意的一点是relative定位后的元素被作为参考定位元素时,被参考的依旧是其正常文档流的位置来定位
  5. 还需要注意的一点是absolute定位后一定要设置leftright属性,负责其显示位置跟relative是一样的,
  6. 还还要注意的一点是absolute定位是根据祖先元素的border定位的,改变祖先元素的margin会让包含其子元素和自身同时位移,改变padding并不会改变其位置
  7. 如果要使用absolute,最好在其外层父元素(非亲父层)使用relative
    参考

3. z-index

1.父子关系是无法用z-index来设定上下关系的,一定是子级在上父级在下

  1. 使用static 定位或无position定位的元素z-index属性是无效的

4. box-sizing

box-sizing除了是为了数学计算方便外,更重要的是为防止在操作paddingborder时不至于影响到父元素和相邻元素,box-sizing有两个属性:border-boxcontent-box;

content-box

  • 默认值,标准盒模型。 width 与 height 只包括内容的宽和高, 不包括边框(border),内边距(padding),外边距(margin)。注意: 内边距, 边框 & 外边距 都在这个盒子的外部。 比如. 如果 .box {width: 350px}; 而且 {border: 10px solid black;} 那么在浏览器中的渲染的实际宽度将是370px;
  • 尺寸计算公式:width = 内容的宽度,height = 内容的高度。宽度和高度都不包含内容的边框(border)和内边距(padding)。

border-box

  • width 与 height 包括内边距(padding)与边框(border),不包括外边距(margin)。这是IE 怪异模式(Quirks mode)使用的 盒模型 。注意:这个时候内边距和边框将会包括在盒子中。比如 .box {width: 350px; border: 10px solid black;} 浏览器渲染出的宽度将是350px. 如果计算后的最内部的内容宽度为负值,都会被计算成0,内容还在,所以不可能通过border-box来隐藏元素。
  • 尺寸计算公式:width = border + padding + 内容的宽度,height = border + padding + 内容的高度。

5. 高度塌陷

6. viewport

  • 测量viewport里面html的宽度:
  1. document.documentElement.offsetWidth
  2. document.documentElement.clientWidth
  • 整个 html 的宽度
  1. document.documentElement.scrollWidth
  • 整个 HTML 的高度
  1. document.documentElement.offsetHeight
  • viewport 内的 HTML 的高度
  1. document.documentElement.clientHeight

6. boxe-shadow

1
2
3
4
5
6
E {box-shadow: <length> <length> <length>?<length>?||<color>}
也就是:
E {box-shadow:inset x-offset y-offset blur-radius spread-radius color}
换句说:
对象选择器 {box-shadow:投影方式 X轴偏移量 Y轴偏移量 阴影模糊半径 阴影扩展半径 阴影颜色}
box-shadowtext-shadow一样可以使用一个或多个投影,如果使用多个投影时必须需要用逗号“,”分开。

7. 媒体查询

1
2
3
4
/*只在pc上起效*/
@media only screen and (orientation: landscape) and (min-width: 1366px) {
   ...
}

8. DOM操作

Javascript
Dom

jQuery

jQuery

9. 组织掉touchmove事件

页面高度超过设备可见高度时,阻止掉touchmove事件。

1
2
3
document.body.addEventListener('touchmove'function (event{
    event.preventDefault();
}, false);

10. 块级元素和行内元素的区别

块级元素:

1.会另起一行,
2.可以设置width,height,margin,padding,border属性
3.默认宽度是容器的100%

行内元素:

1.和其他元素在同一行内
2.高度和宽度就是内容的高度和宽度
3.可以设置margin-left和margin-right属性,无法设置margin-top和margin-bottom属性
4.border和padding可以设置,但是border-top和padding-top到页面顶部后就不再增加

11. 多行文本溢出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
p {
    position:relative;
    line-height:1.5em;
    /* 高度为需要显示的行数*行高,比如这里我们显示两行,则为3 */
    height:3em;
    overflow:hidden;
}
p:after {
    content:"...";
    position:absolute;
    bottom:0;
    right:0;
    padding: 0 5px;
    background-color: #fff;
}
<p>文本溢出我们经常用到的应该就是text-overflow:ellipsis了,相信大家也很熟悉,但是对于多行文本的溢出处理确接触的不是很多,最近在公司群里面有同事问到,并且自己也遇到过这个问题,所以专门研究过这个问题。文本溢出我们经常用到的应该就是text-overflow:ellipsis了,相信大家也很熟悉,但是对于多行文本的溢出处理确接触的不是很多,最近在公司群里面有同事问到,并且自己也遇到过这个问题,所以专门研究过这个问题。</p>

12. 匿名函数调用

匿名函数调用

13. 清除浮动

清楚浮动

15. 少写if-else

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 方法1 hash 表
if (key == "Apple") {
    val = "Jobs";
else if (key == "microsoft"){
    val = "Gates";
else if (key == "Google"){
    val = "Larry";
}
// 替代方法
var ceos = {"Apple":"Jobs""microsoft":"Gates""Google":"Larry"};
val = ceos[key];
///////////////////////////////////////////////////
// 方法2 重构,用 OO 里面的继承或者组合
function getName(type{
    if (type === 'monkey') {
        return 'monkey name';
    } else if (type === 'cat') {
        return 'cat name';
    } else {
        return 'dog name';
    }
}
// 替代方法
function getName(type{
    var data = {
        monkey'monkey name',
        cat'cat name',
        dog'dog name'
    }
 
    return data[type] ? data[type] : data['dog'];
}
// else
unction getName(type) {
        var data = {
            monkeyfunction ({
                console.log('monkey name111');
            },
            catfunction ({
                console.log('monkey name111');
            },
            dogfunction ({
                console.log('monkey name111');
            },
        };
        return data[type] ? data[type] : data['dog'];
    }
// else
function getName(type{
        return ({
            monkeyfunction ({
                console.log('monkey name1111');
            },
            catfunction ({
                console.log('monkey name2222');
            },
            dogfunction ({
                console.log('monkey name3333');
            }
        }[type] || ['dog'])();
    }

16. 判断终端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//判断访问终端
    var browser={
        versions:function(){
            var u = navigator.userAgent, app = navigator.appVersion;
            return {
                trident: u.indexOf('Trident') > -1//IE内核
                presto: u.indexOf('Presto') > -1//opera内核
                webKit: u.indexOf('AppleWebKit') > -1//苹果、谷歌内核
                gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,//火狐内核
                mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
                ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
                android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1//android终端或者uc浏览器
                iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器
                iPad: u.indexOf('iPad') > -1//是否iPad
                webApp: u.indexOf('Safari') == -1//是否web应该程序,没有头部与底部
                weixin: u.indexOf('MicroMessenger') > -1//是否微信 (2015-01-22新增)
                ali: u.indexOf('AliApp') > -1              //阿里服务窗
            };
        }(),
        language:(navigator.browserLanguage || navigator.language).toLowerCase()
    }

17. 立即执行函数

立即执行

1
2
3
4
5
6
7
8
// 使用了`()`表示调用的意思
(function(){
    console.log("test");
})();
 
(function(){
    console.log("test");
}());

18. DPI/PPI/dp/sp/px/pt

参考1 or 2

19. 览器渲染原理

浏览器渲染原理

20. Viewport Meta

Viewport Meta

8. ionic 指令图

ionic指令

ES6

1. let
1
2
3
4
5
var a = 123//
var let = 123//局部变量,同作用域中不可重复声明
for (let i=0; i<arr.length; i++) {
...
}
2. const
1
2
const PI = 2.1415926//定义常量,不可重复声明,只在变量作用域内有效
const foo = Object.freeze({}); //对象冻结,使用Object.freeze
3. 数组解析赋值
1
2
3
4
let [x, y, z] = ['a']; //x ="a",  y,z = undefined
 
[x, y = 'b'] = ['a']; // 定义默认值 x='a', y='b'
[x, y = 'b'] = ['a'undefined]; // x='a', y='b'
4. 对象解构赋值

参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var { foo, bar } = { foo"aaa"bar"bbb" };
 
let obj = { first'hello'last'world' };
let { first: f, last: l } = obj; //f = 'hello' , l = 'last'
//对象的解构赋值是下面形式的简写
var { foo: foo, bar: bar } = { foo"aaa"bar"bbb" };
 
//解构支持嵌套
var obj = {
  p: [
    "Hello",
    { y"World" }
  ]
};
 
var { p: [x, { y }] } = obj;//var { p: [x, { y: wod}] } = obj;
//这时p是模式,不是变量,因此不会被赋值
 
//从函数返回多个值,快速提取json的值等
// 返回一个数组
function example({
  return [123];
}
var [a, b, c] = example();
 
// 返回一个对象
function example({
  return {
    foo1,
    bar2
  };
}
var { foo, bar } = example();

模板字符串
1
2
3
4
5
6
7
8
9
10
var str = `a \n b`;
 
var name = "Bob", time = "today";
var str  = `Hello ${name}, how are you ${time}?`//str = "Hello Bob, how are you today?"
 
//也可以调用函数
function fn({
  return "Hello World";
}
`foo ${fn()} bar`
箭头函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//箭头函数goes to
function countdown(n{
  while (n --> 0)  // "n goes to zero"
    alert(n);
}
//使用-->表示从n到0,此处的-->等价于 (n--)>0 即 -- and >
 
var f = v => v;
//等价于
var f = function(v{
  return v;
};
 
const isEven = n => n % 2 == 0;
const square = n => n * n;
 
// 正常函数写法
[1,2,3].map(function (x{
  return x * x;
});
 
// 箭头函数写法
[1,2,3].map(x => x * x);

环境安装

1
2
3
4
5
6
nvm .exe \\安装,nodejs包管理工具
nvm list 查看可用版本
nvm install 版本号\\安装相应版本
nvm user 版本号 \\使用相应版本
node -v\\查看版本号
进入相应的从在.json目录下npm install

chrome开发技巧

  • inspect() / copy() / values() 和 Ctrl + L
    在 console 面板使用 inspect(elem) 跳转到 elements 面板的指定元素节点
    在 console 面板使用 copy(values) 将数据复制到剪贴板
    在 console 面板使用 values(object) 获取对象的所有属性值,返回数组
    使用 Ctrl + L 清空当前的 console 面板

  • JS 文件打开和文件内的快速跳转
    在 Sources 面板使用 CMD + O 快捷键打开搜索框
    搜索框下会提示当前页面的涉及的 JS 文件,输入文件名即可打开
    如果输入:5:9,则表示跳转到文件的第五行第九个字符
    在 Sources 面板使用使用 Alt + - 和 Alt + = 可以在上一个鼠标位置和下一个鼠标位置之间跳转

经不住似水流年  逃不过此间少年
0%