相对于父元素宽度的:
[max/min-]width、left、right、padding、margin 等;

相对于父元素高度的:
[max/min-]height、top、bottom 等;

相对于继承字号的:
font-size 等;

相对于自身字号的:
line-height 等;

相对于自身宽高的:
border-radius、background-size、transform: translate()、transform-origin、zoom、clip-path 等;

特殊算法的:
background-position(方向长度 / 该方向除背景图之外部分总长度 * 100)、
filter 系列函数等;

如果自身设置 position: absolute,“父元素”指:破坏文档流的div高度设为百分比是相对谁而言的? - Boringer 的回答
如果 position: fixed,“父元素”指视口。

作者:Boringer
链接:https://www.zhihu.com/question/36079531/answer/65809167
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

css3

position: sticky;
position: -webkit-sticky;

滚动定位: 当页面元素滚动到视觉范围之外时,元素改为fixed定位

ios滚动时事件处理

ios滚动时无触发scroll事件:可以修改为绑定touchmove事件,但是滑动后惯性滚动时还是不会触发事件
ios滚动时position从fixed切换为relative会有问题, 可以使用css3

mac同一程序不同窗口切换快捷键

commond + ~

webstrom format不工作

原因: 插件失效

shell

  • 获取日期时间 d=date '+%Y-%m-%d %H:%M:%S'
  • 使用expect实现自动交互功能
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # expect 示例1
    #! /usr/bin/expect
    expect << EOF
    spawn python upload.py -y
    expect "username:"
    send "myusename\r"
    expect "password:"
    send "mypassword\r"
    expect "New issue subject:"
    send "issuename\r"
    expect eof
    exit
1
2
3
4
5
6
7
8
9
# expect 示例2
spawn python upload.py -y
expect {
"username:" { send "myusename\r"; exp_continue}
"password:" { send "mypassword\r"; exp_continue }
"New issue subject:" {send "issuename\n"; exp_continue}
"please visit" {exit}
}

TCL (工具命令语言(Tool Command Language))

node错误处理

shell脚本 条件判断错误

[shell脚本报错:”[: =: unary operator expected”](http://blog.csdn.net/goodlixueyong/article/details/6564591)
在匹配字符串相等时,我用了类似这样的语句:

1
2
3
if [ $STATUS == "OK" ]; then
echo "OK"
fi

在运行时出现了 [: =: unary operator expected 的错误,就一直找不到原因,尝试了删除等号两侧的空格和括号里的空格都不管用,最后baidu了一下,才找到原因。把语句改成这样就不会出错了.

1
2
3
if [[ $STATUS = "OK" ]]; then
echo "OK"
fi

究其原因,是因为如果变量STATUS值为空,那么就成了 [ = “OK”] ,显然 [ 和 “OK” 不相等并且缺少了 [ 符号,所以报了这样的错误。当然不总是出错,如果变量STATUS值不为空,程序就正常了,所以这样的错误还是很隐蔽的。

或者用下面的方法也能避免这种错误:

1
2
3
if [ "$STATUS"x == "OK"x ]; then
echo "OK"
fi

当然,x也可以是其他字符。顺便提一点,shell中有没有双引号在很多情况下是一致的。

node同一个端口支持http和https(只能作为服务器,不能作为代理)

摘自:http://www.cnblogs.com/dojo-lzz/p/5479870.html
众所周知node是一个高性能的web服务器,使用它可以很简单的创建一个http或https的服务器。
比如一个很简单的http服务器:

1
2
3
4
5
6
7
8
9
var http = require('http');
var https = require('https');
var httpPort = 3345;
var server = http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('hello world!');
}).listen(httpPort);

https服务器需要生成证书,详情请看这篇文章:HTTPS 的原理和 NodeJS 的实现。这里我们直接看最终成果,附件证书。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var https = require('https');
var fs = require('fs');
var httpsPort = 3346;
var options = {
key: fs.readFileSync('./cakey.pem'),
cert: fs.readFileSync('./cacert.pem')
};
var sserver = https.createServer(options, function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('secured hello world');
}).listen(httpsPort);

从上文我们可以看出,node生成的每个服务器必须分配一个端口。那么如果我们在工作中遇到一个需求:让同一个端口或地址既支持http协议又支持https协议,这时候我们该怎么办,有的同学很可能想到用nginx做反向代理,这不失为一个解决方案,但这也同样意味着增加了产品的复杂度,用户并不想去折腾ngnix。
办法是有的,原理就要搬出OSI的七层模型:
a8ec8a13632762d04284e772a1ec08fa503dc641
HTTP与HTTPS都属于应用层协议,所以只要我们在底层协议中进行反向代理,就可以解决这个问题! 刚好node可以让我们很方便的创建一个tcp服务器!

所以我们的核心代码如下:

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
var net = require('net');
var http = require('http');
var https = require('https');
var fs = require('fs');
var httpPort = 3345;
var httpsPort = 3346;
var server = http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('hello world!');
}).listen(httpPort);
var options = {
key: fs.readFileSync('./cakey.pem'),
cert: fs.readFileSync('./cacert.pem')
};
var sserver = https.createServer(options, function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('secured hello world');
}).listen(httpsPort);
net.createServer(function(socket){
socket.once('data', function(buf){
console.log(buf[0]);
// https数据流的第一位是十六进制“16”,转换成十进制就是22
var address = buf[0] === 22 ? httpsPort : httpPort;
//创建一个指向https或http服务器的链接
var proxy = net.createConnection(address, function() {
proxy.write(buf);
//反向代理的过程,tcp接受的数据交给代理链接,代理链接服务器端返回数据交由socket返回给客户端
socket.pipe(proxy).pipe(socket);
});
proxy.on('error', function(err) {
console.log(err);
});
});
socket.on('error', function(err) {
console.log(err);
});
}).listen(3344);

fis3打包单文件vue

nodejs异步改造为同步模块fibers

nodejs输出单行日志

1
2
3
4
5
6
7
8
9
10
11
12
// 使用前最好判断一下这三个函数是否存在
process.stdout.clearLine();
process.stdout.cursorTo(0);
process.stdout.write(msg);
console.log(msg) == > process.stdout.write(msg + '\n')
// 输出区域的宽度和高度
process.stdout.on('resize', () => {
console.log('screen size has changed!');
console.log(`${process.stdout.columns}x${process.stdout.rows}`);
});

nodejs代理工具hoxy的使用介绍

Hoxy是一个用Node编写的完全免费、开源的Http代理软件,类似Charles和Fiddler。 它有一下功能:

  • 中断请求或者响应.
  • 查看和修改请求或响应的各个部分
  • 模拟慢速网络和延迟发送
  • 支持正向或者反向代理
  • 可以用本地文件代替远程请求
  • 请求或者响应主体支持格式: JSON, string, jQuery, buffer, 等.
  • 支持HTTP和HTTPS.

工作原理

Hoxy是客户端和服务器端之间的一个代理工具,可以在请求或者响应阶段做任何处理。配置代理后,客户端发送的请求将经历一下五个阶段

1
2
3
4
5
6
7
time ==>
-----------------------
server: 3
-------------/-\-------
hoxy: 2 4
-----------/-----\-----
client: 1 5

1.客户端发送请求.
2.Hoxy拦截并处理请求.
3.服务器端收到请求并发送响应数据.
4.Hoxy拦截响应并处理.
5.客户端收到请求.

下面通过几个例子来了解下hoxy的使用

1.打印所有请求并中断请求,发送 helloworld 给客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
"use strict";
let hoxy = require('hoxy');
// 创建一个代理服务器
let proxy = hoxy.createServer().listen(8080, function () {
console.log('start server at port:', 8080);
});
// 在请求阶段拦截并修改
proxy.intercept('request', function (req, resp, cycle) {
console.log('URL:', req.fullUrl());
resp.statusCode = 200;
resp.string = 'hello world!';
});

现在你可以直接打开浏览器直接访问http://localhost:8080,或者配置代理地址为"你的ip:8080",然后访问任意网页,即可看到"hello world!”
假如只是想查看请求内容,不做任何处理,只需要将resp相关行注释掉即可。
在请求阶段修改了响应内容之后,hoxy将不会再向服务器发送请求,直接使用修改后的内容发送给客户端。

2.修改请求或响应数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 省略前面创建代理服务器部分代码,以后示例同样
// 在请求阶段拦截并修改header
proxy.intercept({
phase: 'request',
hostname: 'test.com'
}, function (req, resp, cycle) {
console.log('URL:', req.fullUrl());
req.headers['host'] = 'test123.com';
});
// 在响应阶段拦截并修改响应数据
proxy.intercept({
phase: 'response',
fullUrl: /compconfig/, // 只修改匹配该正则的网址
as: 'json' // 将响应转化为json格式
}, function (req, resp, cycle) {
console.log('URL:', req.fullUrl());
if(resp.json.data){
resp.json.data['test'] = '123';
}
});

3.修改响应速度

1
2
3
4
5
6
7
8
9
10
// 限制上传速度为10,000字节/秒
proxy.intercept('request', function(req, resp, cycle) {
req.slow({rate:10000}); // bytes per second
});
// 模拟每个请求延迟500到1000ms
proxy.intercept('request', function(req, resp, cycle) {
req.slow({latency:randint(500, 1000)});
});

4.发送本地文件

1
2
3
4
5
6
7
8
9
// 拦截compconfig并发送本地文件
proxy.intercept({
phase: 'request',
fullUrl: /compconfig/,
}, function (req, resp, cycle) {
console.log('URL:', req.fullUrl());
resp.statusCode = 200;
return cycle.server("./mock/compconfig.json"); // 注意一定要将该对象(是个promise)返回,否则发送文件将不会生效
});

5.https代理服务器

关于https和ssl证书,可以参考

在这里我们使用openssl工具创建证书

1
2
3
4
# 创建密匙
openssl genrsa -out ./ca/my-private-root-ca.key.pem 2048
# 创建证书,我们将用这个证书为所有通过该代理的网站制作签名证书
openssl req -x509 -new -nodes -key ./ca/my-private-root-ca.key.pem -days 1024 -out ./ca/my-private-root-ca.crt.pem -subj "/C=US/ST=Utah/L=Provo/O=ACME Signing Authority Inc/CN=example.com"

创建https代理服务器

1
2
3
4
5
6
hoxy.createServer({
certAuthority: {
key: fs.readFileSync('./ca/my-private-root-ca.key.pem'),
cert: fs.readFileSync('./ca/my-private-root-ca.crt.pem')
}
}).listen(8080);

配置好代理访问https://www.baidu.com,将提示改网站证书不可信。
这里需要我们先信任刚刚制作的证书“my-private-root-ca.crt.pem”,之后就可以正常访问了。。
可以结合示例4,匹配某一个地址就发送证书给浏览器,就可以像fiddle或charles一样监控手机的https请求了。

6.使用时遇到的问题

  1. setheader失败程序退出。node4.2.6之后的版本setheader采用更严格的匹配模式比如setheader[‘host :www.baidu.com’],多个空格将不能正常执行。。
    这时需要将node降为4.2.6版本或以下(可以使用node版本管理工具nvm或者n)
  2. 出现错误时程序容易崩溃,比如链接失效等。可以使用domain或者process或者其他方式捕获异常后重启
    例如:node异常捕获domain
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    const domain = require('domain');
    const fs = require('fs');
    const d = domain.create();
    d.on('error', (er) => {
    console.error('Caught error!', er);
    });
    d.run(() => {
    process.nextTick(() => {
    setTimeout(() => { // simulating some various async stuff
    fs.open('non-existent file', 'r', (er, fd) => {
    if (er) throw er;
    // proceed...
    });
    }, 100);
    });
    });

使用fis3打包单文件vue组件

在项目开发过程中,我们常把页面拆分成一个个小组件,每个组件由css、模板、js组成。
一般情况下,三个部分我们分别写在不同的文件中,但是假如页面有很多小组件,每个组件都拆分成三个文件,最终就会产生大量的小文件,不便于管理。
这时我们通过将组件的三个部门写在同一个文件来避免多个小文件,并且每个组件一个文件也更加直观。
参考webpack和browserify打包单文件组件fis3-parser-vue

详细说明

1.首先新建一个项目,文件目录如下

1
2
3
4
5
6
7
+-- index.html
+-- weight
|-- app.vue
+-- js
|-- base
|-- vue.js
|-- mod.js

文件weight/app.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// weight/app.vue
<style>
h1 {
color: #f00;
}
</style>
<template>
<h1>{{msg}}</h1>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>

文件index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<app></app>
<script src="js/base/mod.js"></script>
<script src="js/base/vueify-insert-css.js"></script>
<script src="js/base/vue.js"></script>
<script>
var App = require('weight/app.vue');
new Vue({
el: 'body',
components: {
app: App
}
});
</script>

2.安装打包工具

1
2
3
4
5
6
7
8
9
10
11
12
13
### 全局安装fis3
npm install fis3 -g -d
npm install fis3-hook-module -g -d
npm install fis3-hook-relative -g -d
npm install fis3-postpackager-loader -g -d
### es6相关模块(根据需要选择安装)
npm install babel-plugin-transform-runtime
npm install babel-preset-es2015
npm install fis-parser-babel2
### vue
npm install fis3-parser-vue

3.编写fis-conf.js

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
// fis-conf.js
// 开启模块化包装amd,cmd
fis.hook('module', {mode: 'auto'});
// 使用相对路径。
fis.hook('relative');
fis.match('**', {relative: true});
fis
// 打包vue文件
.match(/\.vue$/i, {
rExt: '.js',
isMod: true,
isJsLike: true,
isComponent: true,
parser: fis.plugin('vue')
})
// 普通js不增加module名称
.match("*.js", {
isMod: false,
isES6: false,
isComponent: false,
useHash: false,
// 设置js文件为babel解析,支持es6的写法。
parser: fis.plugin('babel2')
})
.match('::package', {
// npm install [-g] fis3-postpackager-loader
// 分析 __RESOURCE_MAP__ 结构,来解决资源加载问题
// allInOne: true, //js&css打包成一个文件
sourceMap: true, //是否生成依赖map文件
// useInlineMap: true //是否将sourcemap作为内嵌脚本输出
postpackager: fis.plugin('loader', {})
})

4.编译

执行 fis3 release -d output,即可看到文件output/weight/app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// weight/app.js
define('weight/app.vue', function(require, exports, module) {
var __vueify_style__ = require("vueify-insert-css").insert("\nh1 {\n color: #f00;\n}\n")
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = {
data: function data() {
return {
msg: 'Hello world!'
};
}
};
if (module.exports.__esModule) module.exports = module.exports.default
;(typeof module.exports === "function"? module.exports.options: module.exports).template = "\n<h1>{{msg}}</h1>\n"
});

但是”vueify-insert-css”是什么鬼?
通过浏览器打开查看,会提示”mod.js:65 Uncaught Error: Cannot find module vueify-insert-css

5.修复

在项目中搜索 vueify-insert-css,会发现fis3-parser-vue中使用了模块vueify-insert-css,打开项目,就一个文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var inserted = exports.cache = {}
exports.insert = function (css) {
if (inserted[css]) return
inserted[css] = true
var elem = document.createElement('style')
elem.setAttribute('type', 'text/css')
if ('textContent' in elem) {
elem.textContent = css
} else {
elem.styleSheet.cssText = css
}
document.getElementsByTagName('head')[0].appendChild(elem)
return elem
}

稍微改造一下就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// js/base/vueify-insert-css.js
define('vueify-insert-css', function (require, exports, module) {
var inserted = exports.cache = {}
exports.insert = function (css) {
if (inserted[css]) return
inserted[css] = true
var elem = document.createElement('style')
elem.setAttribute('type', 'text/css')
if ('textContent' in elem) {
elem.textContent = css
} else {
elem.styleSheet.cssText = css
}
document.getElementsByTagName('head')[0].appendChild(elem)
return elem
}
});

放在js/base目录,html中直接引入,重新打包,ok

6.存在问题

  • fis3-parser-vue组件对less的支持有问题,单文件中暂时无法使用less语法。sass没有试过,感兴趣的同学可以动手试试看
  • 部分编辑器可能不支持单文件vue语法高亮,使用html格式即可

npm run执行的代码和直接输入命令执行代码有什么区别?

使用npm run的方便之处在于,npm会自动把node_modules/.bin加入$PATH,这样你可以直接运行依赖程序和开发依赖程序,不用全局安装了。只要npm上的包提供命令行接口,你就可以直接使用它们,方便吧?当然,你总是可以自己写一个简单的小程序。

https

console中Command+Click即可打开连接

nodejs错误

Header name must be a valid HTTP Token
header字段不合法,降级node版本为4.2.6即可

node版代理软件hoxy的学习使用

node异常捕获domain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const domain = require('domain');
const fs = require('fs');
const d = domain.create();
d.on('error', (er) => {
console.error('Caught error!', er);
});
d.run(() => {
process.nextTick(() => {
setTimeout(() => { // simulating some various async stuff
fs.open('non-existent file', 'r', (er, fd) => {
if (er) throw er;
// proceed...
});
}, 100);
});
});

svn,cooder

1
2
svn checkout https://muzhilong@svn.baidu.com/......
upload.py -r user

Fiddle安装后上不了网

  • 关闭设置: tools -> connections -> act as system proxy on startup

charles https代理问题:破解后本地证书无法安装

node版代理软件hoxy