本文大部分转载自civerzhu的专栏https://segmentfault.com/blog/civerzhu
参考链接 https://developer.chrome.com/devtools/docs

console相关技巧

console.log

console.log()可以传入多个参数

console.log("test",123);

同时log的第一个参数是带有特别标示符的字符串的话控制台会有不同的效果

  • %s 输出字符串
  • %d/%i 输出数字
  • %f 输出浮点数
  • %o 输出Dom元素
  • %O 输出JS对象
  • %c 表示对输出的文字应用特殊的样式

console.log("%o",document.body.firstElementChild);
输出结果
<div class="...">...<div>

%c可以自定义输出样式

console.log("%cThis is a colorful text","color:blue; background:red");

可以看出%c应用的样式是CSS的语法,所以基本上CSS支持的样式语句都可以支持。当然,Chrome是有过滤一些CSS语法的,比如对元素定位的CSS语法就不支持(ps:貌似定位啥的也没用,除非是想捣乱的程序员,呵呵)

彩色的输出语句貌似看起来中看不中用,其实不然。大型的web开发项目,特别是多人分模块开发的时候,控制台一大堆console.log输出,你一下子找不到你自己的模块的输出语句。如果给你自己的模块输入语句应用了不同的颜色,相对来说比较好定位到输出的地方,这是提高效率的一个小技巧。

其他console Api

  • console.warn
  • console.info
  • console.error
  • console.trace
  • console.group

console.time

console.time用于显示代码执行的时间,要搭配console.timeEnd来使用。

console.time("getData use time")
for(){
    ...
}
console.timeEnd("getData use time")
输出
getData use time: 50.0000ms

其他

其他的console方法我将简单列举一下,就不一一详细说明了,详细可以参考Google的开发文档。

  • console.assert() 用于判断表达式,满足表达式时才输出语句;
  • console.debug() 用于输出输出debug的信息;
  • console.dir() 用于展开输出一个dom元素的JavaScript对象;
  • console.profile() 用于记录代码消耗CPU的信息;
  • console.timeStamp() 用于标记运行时的timeline信息;
  • console.count() 用于记录代码执行的次数;
  • console.memory 用于显示此刻使用的内存信息(这是一个属性而不是方法);
  • console.table() 用表格的形式来输出信息;
  • console.clear() 清空控制台的内容(当然你可以用快捷键ctrl+L);

另外,再来优惠大派送,介绍几个在Chrome控制台上比较有趣的命令。

  • $0 可以在控制台输出在Elements面板选中的页面元素;
  • $_ 表示上一次在控制台键入的命令,你也可以用快捷键“上方向键”来达到同样的效果;
  • $x 可以用xPath的语法来获取页面上的元素;

Element 面板的使用

使用Chrome开发工具中的elements面板估计是前端工程师修改一个页面内容最快的方法了。elements面板的左侧显示页面的HMTL元素,右侧显示选中元素的样式。使用方法也很简单,用左上角的“选择鼠标”在页面上选取元素,然后就可以查看该元素的HTML属性和CSS样式了。

查看hover方法

右键Html元素菜单上的“Force element state”这个操作,就是强制设置该元素的状态。状态分为四种,分别是active/hover/focus/visited。强制设置状态在某些情况下比较的有用,例如你想查看某些hover伪类的样式,又例如元素里有隐藏的元素,需要在鼠标hover的时候才出现,但你的鼠标移开的时候hover状态就消失了,强制显示hover状态比较方便你检查元素hover的情况。

在elements面板的样式区域也可以给元素强制设置状态(active/hover/focus/visited)。做法和原理跟上面说的一样。

html加断点

在调试的过程中可以给元素添加断点。很神奇吧?现在支持的断点的状态有:元素的子节点结构改变时、元素的属性改变时、元素被删除时。在大型项目中,这一断点比较有意思。大型项目中的HTML结构都比较宏大,而且脚本在改变HTML接口的时候你又难以跟踪元素HTML的状态。使用断点,这些都不是问题。右键菜单中即可把这一功能呼唤出来。

紧接上一篇,有两台服务器dev和product,需要在dev上写好的代码,覆盖到product上,但是只有部分代码改变了,所以有这个需求

解决方法

git fetch --all
git reset --hard origin/master

git fetch下载远程最新的,但不尝试,或重订任何东西。 然后,git resetmaster分支重置。

最近一直在忙实验室的事情,没有时间整理博客,有一些小的知识点直接用印象笔记记录了,之前使用svn进行服务器端开发的时候,觉得还是没有github好,远程git又不好操作,最近一个工作的朋友给我提了一下git也可以进行自动化部署,感觉很厉害,今天用 coding.net的webhook进行了自动化部署

coding.net

coding.net速度很快,操作很方便,功能很多,个人觉得,作为私有的git库很合适

基本操作和github类似

  1. 在服务器上生成用户公钥 ssh-keygen -t rsa -C "anzhengchao@gmail.com"
  2. 复制上面的/root/.ssh/id_rsa.pub的内容到个人设置页https://coding.net/user/setting/keys添加即可
  3. 生成部署公钥 sudo -Hu www ssh-keygen -t rsa # 请选择 "no passphrase",一直回车下去
  4. 复制用户公钥的内容并添加到Coding.net公钥:

选择项目 > 设置 > 部署公钥 > 新建 > 粘贴到下面框并确认

  1. 添加hook

选择项目 > 设置 > WebHook > 新建hook > 粘贴你的hook/index.php所在的网址。比如:http://example.com:3000/webhook, 令牌可选,但是建议写上。

  1. 在服务器端创建express,代码如下

之后需要在现有的或者新建的项目下面做如下操作

git init
git commit -m "first commit"
git remote add origin git@coding.net:zhanfang/xxx
git push -u origin master

在提交的过程中可能原本有文件存在,会发生冲突
解决办法:

  1. 强推,即利用强覆盖方式用你本地的代码替代git仓库内的内容

    git push -f

  2. 先把git的东西fetch到你本地然后merge后再push

    git pull

又会出现另外一个问题

[branch "master"] 
remote = <nickname> 
merge = <remote-ref> 
[remote "<nickname>"] 
url = <url> 
fetch = <refspec>

这等于告诉git2件事:

  1. 当你处于master branch, 默认的remote就是origin。
  2. 当你在master branch上使用git pull时,没有指定remote和branch,那么git就会采用默认的remote(也就是origin)来merge在master branch上所有的改变
    如果不想或者不会编辑config文件的话,可以在bush上输入如下命令行:

    git config branch.master.remote origin
    git config branch.master.merge refs/heads/master

大功告成

完成这些后,试着修改一次,然后push
之后应该服务器会自动进行pull操作

注意

git config --global user.name "overtrue" 
git config --global user.email "anzhengchao@gmail.com" # 邮箱请与conding上一致

由于网络用户是www,所以要需要部署密钥,生成方法如下:

//默认路径/alidata/www/.ssh/
sudo -u www ssh-keygen -t rsa

只有这样才能通过网络git pull

express代码

var express = require('express');
var process = require('child_process');
var bodyParser = require('body-parser');
var multer = require('multer');
var app = express();

app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(multer()); // for parsing multipart/form-data


app.post('/webhook', function(req,res){
  //console.log('print', req.body);
  console.info(req.body["token"]);
  if('xxx' === req.body['token'] ){

    console.info(process);
    process.exec('git pull', {'cwd':'/alidata/www/xxx'},
      function (error, stdout, stderr) {
        console.log('stdout========================\n' + stdout);
        console.log('stderr========================\n' + stderr);
        if (error !== null) {
          res.send('<pre>fail!!!\n' + stdout + error + '</pre>');
        } else {
          res.send('<pre>done!!!\n' + stdout + '</pre>');
        }
      });
  } else {
    console.log(' failed token ')
    res.send('<pre>token不正确?</pre>');
  }
});

app.set('port', 3000);

var server = app.listen( 3000, function() {
  console.log('Listening on port %d', server.address().port);
})

最近要开始苦逼的网站优化之路了,因为主页是php动态页面,加载速度较慢,所以决定生成静态页面,实现方法是利用php的file_put_contents获取页面,然后存放到index.html中

代码

1
2
3
4
5
6
7
<?php
ini_set("user_agent","Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2) Gecko/20100301 Ubuntu/9.10 (karmic) Firefox/3.6");
$index_file = ROOT_PATH . 'index.html';
$source_url = $site_url."/index.php";
file_put_contents($index_file, file_get_contents($source_url), LOCK_EX);
?>

Tips

  • 上面的代码并不完整,但大概意思已经展现了
  • 由于file_get_contents总是获取到手机端页面,所以需要加上第一行的ini_set伪装为PC端请求
  • curl更加强大,有兴趣的可以尝试一下

转载自 http://segmentfault.com/a/1190000002489109

map标签

定义一个客户端图像映射。图像映射(image-map)指带有可点击区域的一幅图像。

  • area元素永远嵌套在map元素内部。area元素可定义图像映射中的区域。
  • img标签中的usemap属性可引用的map标签中的id或name属性(取决于浏览器),所以我们应同时向map标签添加id和name属性。

示例

例如我们想在下面一张图实现九个热点区域,不切图,就使用map标签。
Alt
首先用 ps 得到几个坐标:
Alt

然后代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<img src="cat.jpg" alt="" usemap="#catmap" >
<map name="catmap">
<area shape="rect" coords="0,0,148,139" href ="http://www.baidu.com" target ="_blank" alt="">
<area shape="rect" coords="148,139,295,0" href ="http://www.sina.com" target ="_blank" alt="">
<area shape="rect" coords="295,0,439,140" href ="http://www.qq.com" target ="_blank" alt="">
<area shape="rect" coords="148,139,0,340" href ="http://www.163.com" target ="_blank" alt="">
<area shape="rect" coords="148,139,296,340" href ="http://www.soso.com" target ="_blank" alt="">
<area shape="rect" coords="296,340,439,140" href ="http://sf.gg" target ="_blank" alt="">
<area shape="rect" coords="0,340,148,493" href="http://www.zhihu.com" target ="_blank" alt="">
<area shape="rect" coords="148,493,296,340" href="http://z.cn" target ="_blank" alt="">
<area shape="rect" coords="296,340,436,490" href="http://jd.com" target ="_blank" alt="">
</map>
</body>
</html>

关于area

  • area 可以是圆形(circ),多边形(poly),矩形(rect),不同形状要选取不同的坐标(coords).
  • 圆形:shape=”circle”,coords=”x,y,z”
    x,y为圆心坐标(x,y),z为圆的半径
  • 多边形:shape=”polygon”,coords=”x1,y1,x2,y2,x3,y3,…”
    每一对x,y坐标都定义了多边形的一个顶点(0,0) 是图像左上角的坐标)。定义三角形至少需要三组坐标;高纬多边形则需要更多数量的顶点。
  • 矩形:shape=”rectangle”,coords=”x1,y1,x2,y2”
    第一个坐标是矩形的一个角的顶点坐标,另一对坐标是对角的顶点坐标,”0,0” 是图像左上角的坐标。请注意,定义矩形实际上是定义带有四个顶点的多边形的一种简化方法。(就是说,知道对角的两个点的坐标就行了。)

最近在做‘悠客生鲜’手机端,想用flex做一下,却发现原来还有兼容性问题
主要是ios9以下,不能直接使用flex,ios9没问题

display:flex的兼容性

1
2
3
4
5
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */

flex兼容性

-webkit-flex: 1;
-moz-box-flex: 1;
-webkit-box-flex: 1;
-o-box-flex: 1;
-ms-flex: 1;
flex: 1;

其他

-webkit-flex-direction: column;
flex-direction: column;


-webkit-justify-content: space-between;
justify-content: space-between;


-webkit-align-self: flex-end;
align-self: flex-end;

bug

慎用flex,兼容性问题太大了,学习用还可以,别用在生产环境
2.3-4.3的Android浏览器还是不支持flex的

部分转载 http://cube.qq.com/?p=328
http://www.cnblogs.com/webflash/archive/2009/08/23/1552462.html

事件流

事件流是描述从页面中接受事件的顺序,ie实现的是事件冒泡流,而Netscape实现的是事件捕获流
而现代的Dom事件流包括了三个阶段:事件捕获、处于目标阶段和时间冒泡阶段,如下图所示
Alt text;

ie9 opera firefox chrome safari 都支持dom流,而ie8之前不支持

Dom0 Dom2 Dom3

DOM0

直接通过 onclick写在html里面的事件, 比如:

<input onclick="alert(1)" />

使用Dom0级方法指定的事件处理程序被认为是元素的方法
即程序中的this引用的是当前元素

var btn = document.getElementById("myBtn");
btn.onclick = function(){
    alert(this.id); //"myBtn"
}

删除Dom0的事件处理程序

btn.onclick = null;

DOM2

是通过addEventListener绑定的事件, 还有IE下的DOM2事件通过attachEvent绑定;

var btn = document.getElementById("myBtn");
btn.addEventListener = ('click',function(){
    alert(this.id); //"myBtn"
},false);

如果该方法传入的最后一个参数值为true,表示事件处理程序被注册在捕获阶段,如果为false表示件处理程序被注册在冒泡阶段。

DOM3

是一些新的事件, 区别DOM3和DOM2的方法我感觉是DOM3事件有分大小写的,DOM2没有;

事件流的作用

允许多个操作被集中处理(把事件处理器添加到一个父级元素上,避免把事件处理器添加到多个子级元素上),它还可以让你在对象层的不同级别捕获事件。

<div onclick="eventHandle(event)" id="outSide" style="width:100px; height:100px; background:#000; padding:50px">
    <div id="inSide" style="width:100px; height:100px; background:#CCC"></div>
</div>
<script type="text/javascript">
//本例子只在外面盒子定义了处理方法,而这个方法一样可以捕获到子元素点击行为并处理它。假设有成千上万子元素要处理,难道我们要为每个元素加“onclick="eventHandle(event)"”?显然没有这种集中处理的方法来的简单,同时它的性能也是更高的。
function eventHandle(e)
{
    var e=e||window.event;
    var obj=e.target||e.srcElement;
    alert(obj.id+' was click')
}
</script>

让不同的对象同时捕获同一事件,并调用自己的专属处理程序做自己的事情

<div onclick="outSideWork()" id="outSide" style="width:100px; height:100px; background:#000; padding:50px">
    <div onclick="inSideWork()" id="inSide" style="width:100px; height:100px; background:#CCC"></div>
</div>
<script type="text/javascript">
function outSideWork()
{
    alert('My name is outSide,I was working...');
}

function inSideWork()
{
    alert('My name is inSide,I was working...');
}

//因为下面程序自动激活单击事件,有些浏览器不允许,所以请单击灰色盒子,从这里开始下命令,这样因为冒泡的原因,黑色大盒子也会收到单击事件,并调用了自己的处理程序。如果还有更多盒子嵌套,一样道理。
</script>

事件处理顺序

在W3C事件模型中,任何事件会首先被捕获直至到达目标元素然后再冒泡回去。事件流包括3个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。Web开发者可以选择将事件处理程序注册在捕获或者冒泡阶段。这可以通过addEventListener()方法来实现。(element2是element1的子元素)

element1.addEventListener(“click”, doSomething2, true);
element2.addEventListener(“click”, doSomething, false);

如果用户点击元素2会发生如下事情:

  • 点击事件开始于捕获阶段。它会先查询是否有元素2的任何祖先元素在捕获阶段绑定了onclick事件。
  • 它发现祖先元素1在捕获阶段绑定了onclick事件,于是element1.doSomething2()首先被执行。
  • 事件一直查询到目标元素element2都没有再发现别的在捕获阶段绑定的onclick事件,事件转到它的冒泡阶段并执行doSomething()(注册在element2上的在冒泡阶段执行的事件处理程序)。
  • 事件再次向上查询并检查是否有任何祖先元素在冒泡阶段绑定了onclick事件,并没有查询到,所以什么都没有发生。

再看相反的例子:

element1.addEventListener(“click”, doSomething2, false);
element2.addEventListener(“click”, doSomething, false);

现在如果用户点击元素2,下面的事情会按顺序发生:

  • 点击事件发生于捕获阶段。事件查询元素2是否有任何祖先元素在捕获阶段绑定了onclick事件并且没有查找到这样的元素。
  • 事件查询到目标元素element2自己。事件转为冒泡阶段并执行doSomething()。
  • 事件再次向上查询并检查目标元素是否有任何祖先元素在冒泡阶段绑定了onclick事件。
  • 它找到了满足条件的元素1,然后执行doSomething2()。

始终都会发生

首先需要理解的是事件捕获或者冒泡始终都会发生。如果你为整个document定义一个onclick事件处理程序:

document.onclick = function(){
  alert("clicked");
};

在文档中任何元素上的任何点击事件最终都会冒泡到document,并且触发上面注册的事件处理程序,从而弹出一个警告框。只有当之前的事件处理程序阻止冒泡时,才不会冒泡到document上。

如果你的文档结构非常复杂,你可以通过阻止冒泡来节约系统资源。毕竟,浏览器必须查询事件目标的每一个祖先元素是否有绑定相同的事件,即使一个也没有找到,这个查询的过程仍然需要花费时间。

要想阻止冒泡,在Microsoft模型中,你需要将事件的cancelBubble属性设置为true。在W3C模型中,你需要调用事件的stopPropagation()方法。

阻止冒泡

如果想解决浏览器兼容问题,你可以像下面这样写:

function doSomething(e){
  if(!e){
    var e = window.event;
  }
  e.cancelBubble = true;
  if(e.stopPropagation){
    e.stopPropagation();
  }
}

在不支持cancelBubble属性的浏览器中设置它的值并不会报错。浏览器会忽略它并创建这个属性。当然,它并不能真正地阻止冒泡,但是给它分配值的操作本身是安全的

currentTarget

就像我们之前看到的,一个事件拥有一个target或者srcElement属性,它包含一个对事件所发生的元素的引用。在我们的例子中是element2,因为用户点击的是它。

理解在捕获和冒泡过程中这个target是不会改变的是非常重要的:它始终是对element2的引用。

但是假设我们像下面这样注册这些事件处理程序:

element1.onclick = doSomething;
element2.onclick = doSomething;

如果用户点击element2,doSomething()会执行两次。但是你怎样知道哪一个HTML元素正在处理这个事件?target/srcElement并不能给出正确答案,因为它们始终是对element2的引用。

为了解决这个问题,W3C添加了currentTarget属性。它包含对正在处理事件的HTML元素的引用。不幸的是Microsoft模型并不支持类似的属性。

你也可以使用this关键字。在上面的例子中它引用正在处理事件的HTML元素,就像currentTarget属性。

注意要点

  • 不是所有的事件都能冒泡。以下事件不冒泡:blur、focus、load、unload。

  • 事件捕获方式在不同浏览器,甚至同种浏览器的不同版本中是有所区别的。如Netscape4.0采用捕获型事件解决方案,其它多数浏览器则支持冒泡型事件解决方案,另外DOM事件流还支持文本节点事件冒泡。

  • 事件捕获到达顶层的目标在不同浏览器或不同浏览器版本也是有区别的。在IE6中HTML是接收事件冒泡的,另外大部分浏览器将冒泡延续到window对象,即……body→documen→window。

  • 阻止冒泡并不能阻止对象默认行为。比如submit按钮被点击后会提交表单数据,这种行为无须我们写程序定制。

实例

实践是检验真理的唯一标准,对于jquery,必须写在内部
实际用的过程,可能一个父元素有一个事件,子元素有另一个事件,为了保证点击子元素的时候,父元素不被触发,必须阻止冒泡

1
2
3
4
5
<ul>ul (祖父)
<li onclick=click2()>li (直接父)
<span onclick=click1()>span</span>
</li>
</ul>
1
2
3
4
5
6
7
8
9
10
$(function($) {
$("span").click(function() {
alert
event.stopPropagation();
});
});
function click2(){
alert("li");
}

webpack.config.js

  • 输出文件夹名必须为build(原因不明)
  • index.html 放到build文件夹下(否则不能自动刷新)
  • package.json script修改为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
'use strict';
var path = require('path');
module.exports = {
entry: [
path.resolve(__dirname, 'src/entry.js')
],
output: {
path: path.join(__dirname, 'build'),
filename: "bundle.js"
},
externals: {
'react': 'React'
},
module: {
loaders: [
{ test: /\.js$/, loader: "jsx!babel", include: /src/},
{ test: /\.css$/, loader: "style!css"},
{ test: /\.scss$/, loader: "style!css!sass"},
{ test: /\.svg$/, loader: "url?limit=8192"}
]
}
};

package.json

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
{
"name": "myTodo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
"dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build"
},
"author": "",
"license": "ISC",
"dependencies": {
"react": "^0.13.3",
"sass": "^0.5.0"
},
"devDependencies": {
"babel-core": "^5.5.8",
"babel-loader": "^5.1.4",
"css-loader": "^0.14.5",
"file-loader": "^0.8.4",
"jsx-loader": "^0.13.2",
"node-libs-browser": "^0.5.2",
"node-sass": "^3.2.0",
"sass-loader": "^1.0.2",
"style-loader": "^0.12.3",
"url-loader": "^0.5.6",
"webpack": "^1.9.11"
}
}

要点

  • 输出文件夹名必须为build(原因不明)
  • index.html 放到build文件夹下(否则不能自动刷新)
  • package.json script修改为重点

看100遍不如自己写一遍,最近参考网上一个Todo例子写了一个Todo应用,顺便适配了移动端,发现了一系列问题 我自己的例子demo http://115.28.147.237:2223/demo1/

参考 http://h5shop.org/article/50/

props

每一个组件都有可变与不可变的属性,props就是不可变的属性,当props改变时,组件的绘制方法不会被调用。

states

当setState时会重新渲染render

states就是组件的可变属性,states的改变会触发组件的render函数,react与其他mvvm框架的最大的不同点就是,react组件可以想象成一个状态机,状态的改变会重绘UI,然后根据 dom diff 算法来绘制UI,而其他的mvvm框架则是对js对象的dirty

我们在设计React组件时如何灵活的运用props与state是一个非常关键的要点。

refs

refs这个点主要用在上级组件调用下级组件的场景,这个场景非常多见。

React.findDOMNode(this.refs.deleteBtn).style.visibility = "visible";

componentDidMount

组件UI渲染完毕后调用,常用在这种业务场景:调用ajax获得数据后,渲染UI。

各种坑

触摸事件

React中的触摸事件仅用三种,touchstart, touchend, touchmove,可是这种会有问题,有时候我需要滚动页面的时候,很容易触发某一个元素的touchend事件,为此笔者找了一个React第三方组件,React-tappable

还无意中发现一个Android与iOS的不同之处

input在disable且readonly之后,onClick会在iOS上触发不起来,onTouchEnd又会在Android上把键盘弹出来,这边笔者做了个Hack,iOS下用onTouchEnd,Android下用onClick,就正常了。

最近想学习一下移动端开发,学习了一下flex,这个东西简直厉害的不行呀,主要是参考阮一峰的文章

容器的属性

  • flex-direction:flex的方向(row | row-reverse | column | column-reverse) ,这个对于很多布局是很有用的
  • flex-wrap:换行(nowrap | wrap | wrap-reverse),默认不换行
  • flex-flow:是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap
  • justify-content:属性定义了项目在主轴上的对齐方式(flex-start | flex-end | center | space-between | space-around)
  • align-items:定义项目在交叉轴上如何对齐,即纵轴上的对齐方式
  • align-content:定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用

项目的属性

  • order:定义项目的排列顺序。数值越小,排列越靠前,默认为0(可以为负数)
  • flex-grow:属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
  • flex-shrink:属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
  • flex-basis:定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小
  • flexnone | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
  • align-self:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性

flex实例

  • 骰子的布局
  • 网格布局
  • 圣杯布局
  • 输入框的布局
  • 悬挂式布局

上面几个布局我已经自己动手写过,之后传到github吧

真是受够了hexo一直出问题,今天都想自己写一个md个人博客,忍了忍又把hexo优化了一下
还有之前帮老师做的公众账号,一直用forever出问题,今天试着用pm2重新弄了一下,效果不错

hexo优化

  1. 删除了之前的 InstantClick
  2. 通过查看加载时间,发现一个<link font.google... />什么的加载时间非常慢,快有1分钟了,简直不能忍,查看了一下,源代码,大概意思是如果字体zh-hans加载不成功的时候会加载这个字体,果断删掉这段代码

pm2

主要特性:

内建负载均衡(使用Node cluster 集群模块)
后台运行
0秒停机重载,我理解大概意思是维护升级的时候不需要停机.
具有Ubuntu和CentOS 的启动脚本
停止不稳定的进程(避免无限循环)
控制台检测
提供 HTTP API
远程控制和实时的接口API ( Nodejs 模块,允许和PM2进程管理器交互 )

测试过Nodejs v0.11 v0.10 v0.8版本,兼容CoffeeScript,基于Linux 和MacOS.

安装

npm install -g pm2

用法

$ npm install pm2 -g     # 命令行安装 pm2 
$ pm2 start app.js -i 4 #后台运行pm2,启动4个app.js 
                                # 也可以把'max' 参数传递给 start
                                # 正确的进程数目依赖于Cpu的核心数目
$ pm2 start app.js --name my-api # 命名进程
$ pm2 list               # 显示所有进程状态
$ pm2 monit              # 监视所有进程
$ pm2 logs               #  显示所有进程日志
$ pm2 stop all           # 停止所有进程
$ pm2 restart all        # 重启所有进程
$ pm2 reload all         # 0秒停机重载进程 (用于 NETWORKED 进程)
$ pm2 stop 0             # 停止指定的进程
$ pm2 restart 0          # 重启指定的进程
$ pm2 startup            # 产生 init 脚本 保持进程活着
$ pm2 web                # 运行健壮的 computer API endpoint (http://localhost:9615)
$ pm2 delete 0           # 杀死指定的进程
$ pm2 delete all         # 杀死全部进程

运行进程的不同方式:

$ pm2 start app.js -i max  # 根据有效CPU数目启动最大进程数目
$ pm2 start app.js -i 3      # 启动3个进程
$ pm2 start app.js -x        #用fork模式启动 app.js 而不是使用 cluster
$ pm2 start app.js -x -- -a 23   # 用fork模式启动 app.js 并且传递参数 (-a 23)
$ pm2 start app.js --name serverone  # 启动一个进程并把它命名为 serverone
$ pm2 stop serverone       # 停止 serverone 进程
$ pm2 start app.json        # 启动进程, 在 app.json里设置选项
$ pm2 start app.js -i max -- -a 23                   #在--之后给 app.js 传递参数
$ pm2 start app.js -i max -e err.log -o out.log  # 启动 并 生成一个配置文件

你也可以执行用其他语言编写的app ( fork 模式):

$ pm2 start my-bash-script.sh    -x --interpreter bash
$ pm2 start my-python-script.py -x --interpreter python

0秒停机重载:
这项功能允许你重新载入代码而不用失去请求连接。
注意:
仅能用于web应用
运行于Node 0.11.x版本
运行于 cluster 模式(默认模式)

$ pm2 reload all

Tips

最后我对比了一下我写的两个公众号,发现nodejs写的回复速度比php写的快,之后具体比一比

列出一些常用的特殊字符

特殊字符

  • \: 做为转意,即通常在”\”后面的字符不按原来意义解释,如/b/匹配字符”b”,当b前面加了反斜杆后/\b/,转意为匹配一个单词的边界。 -或-
    对正则表达式功能字符的还原,如”“匹配它前面元字符0次或多次,/a/将匹配a,aa,aaa,加了”\”后,/a\*/将只匹配”a*”。
  • ^ 匹配一个输入或一行的开头,/^a/匹配”an A”,而不匹配”An a”
  • $ 匹配一个输入或一行的结尾,/a$/匹配”An a”,而不匹配”an A”
    • 贪婪量词 匹配前面元字符 0次或多次 ,/ba*/将匹配b,ba,baa,baaa
    • 匹配前面元字符1次或多次,/b(a+)/将匹配ba,baa,baaa
  • ? 匹配前面元字符0次或1次,/ba*/将匹配b,ba
  • (x) 匹配x保存x在名为$1…$9的变量中
  • x|y 匹配x或y
  • {n} 精确匹配n次
  • {n,} 匹配n次以上
  • {n,m} 匹配n-m次
  • [xyz] 字符集(character set),匹配这个集合中的任一一个字符(或元字符)
  • [^xyz] 不匹配这个集合中的任何一个字符
  • [\b] 匹配一个退格符
  • \b 匹配一个单词的边界
  • \B 匹配一个单词的非边界
  • \cX 这儿,X是一个控制符,/\cM/匹配Ctrl-M
  • \d 匹配一个字数字符,/\d/ = /[0-9]/
  • \D 匹配一个非字数字符,/\D/ = /[^0-9]/
  • \n 匹配一个换行符
  • \r 匹配一个回车符
  • \s 匹配一个空白字符,包括\n,\r,\f,\t,\v等
  • \S 匹配一个非空白字符,等于/[^\n\f\r\t\v]/
  • \t 匹配一个制表符
  • \v 匹配一个重直制表符
  • \w 匹配一个可以组成单词的字符(alphanumeric,这是我的意译,含数字),包括下划线,如[\w]匹配”$5.98”中的5,等于[a-zA-Z0-9]
  • \W 匹配一个不可以组成单词的字符,如[\W]匹配”$5.98”中的$,等于[^a-zA-Z0-9]。

常用正则表达式

去除字符串前后空格的五种方法

trim1

使用两个子表达式。一个去除头部空白,一个去除尾部,好的跨浏览器解决方案

if(!String.prototype.trim){
    String.prototype.trim = function(){
        return this.replace(/^\s+/,"").replace(/\s+$/,"");
    }
}

####trim2

该方法处理长字符串,比第一种方法慢,因为有两个分支选项

String.prototype.trim=function() {
    return this.replace(/^\s+|\s+$/g,'');
}

trim3

效率低,不建议使用

String.prototype.trim = function(){
    return this.replace(/^\s*([\s\S]*?)\s*$/,"$1");
}

trim4

贪婪量词

String.prototype.trim = function(){
    return this.replace(/^\s*([\s\S]*\S)?\s*$/,"$1");
}

trim5

最慢

String.prototype.trim = function(){
    return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1");
}  

苦逼的周末还要把之前 三五成群 的东西完善了,大家可以去关注这个公众号
因为微信公众平台还是需要过滤一些文字的,需要用到php敏感词过滤
其实代码很简单的,直接贴出来就好,以后可以直接用

代码

function filter($str){
    if (is_file("filterwords.txt")){   //判断给定文件名是否为一个正常的文件
        $filter_word = file("filterwords.txt");  //把整个文件读入一个数组中
        for($i=0;$i<count($filter_word);$i++){   //应用For循环语句对敏感词进行判断
            if(preg_match("/".trim($filter_word[$i])."/i",$str)){  //应用正则表达式,判断传递的留言信息中是否含有敏感词
                $words = trim($filter_word[$i]);
                return str_replace($words,"**",$str);
            }
        }
    }
    return $str;
}

注意转成utf-8

之前转载过一篇阮一峰写的js优化方面的博客,讲的特别好,大家可以去看看,最近在看《高性能javascript》,简单的做了一些笔记

准备总结一点东西,但是回头看书的时候又觉得这本书总结的已经很好了,推荐大家买一本《高性能javascript》,自己拿来看看吧

前一篇文章提到前端框架React.js在IOS手机上onClick属性失效
其实理论上触屏设备都应该出问题,可能是由于android还是支持click,但click并不好,有300ms的延时,最好还是用touch方法

知乎上有两种办法

  • 在组件中的componentDidMount方法中,为该div绑定事件,在回调函数中写入想要实现的逻辑。选取dom的方法,可以用原生js或jquery,也可以用react中的ref实现。

  • 为“按钮”这个div 的样式 加入cursor:pointer这一条属性,在ios设备上就正常了。(这个我试过,可行)

这两种方法都不完美,前者写的不够优雅,好的react项目中是基本不对dom进行操作的;后者虽然只加了一行代码,但对日后维护增加了不确定性,特别是对于移动端的页面,cursor属性在不明真相的人看起来会觉得你写的莫名其妙,很可能误删,造成不必要的麻烦。

最好的办法–touch

React event列表

触摸事件

为了使触摸事件生效,在渲染所有组件之前调用

React.initializeTouchEvents(true)。

事件名:

onTouchCancel onTouchEnd onTouchMove onTouchStart

属性:

boolean altKey
DOMTouchList changedTouches
boolean ctrlKey
function getModifierState(key)
boolean metaKey
boolean shiftKey
DOMTouchList targetTouches
DOMTouchList touches

一个参考代码

var IndexPage = (function(A){
    var Person = React.createClass({
        handleClick: function () {
            window.location.href = "#" + this.props.id ;
        },
        render: function () {
            var link = "tel:" + this.props.tel;
            return (
                <A.ListItem className="Person" onClick={this.handleClick} onTouchStart={this.handleClick}>
                    <A.Icon icon="user" className="person-icon" />
                    {this.props.name}
                    <A.Badge amStyle="success" radius className="person-phone">
                        <a href={link}>
                            <A.Icon icon="phone" />
                        </a>
                    </A.Badge>
                </A.ListItem>
            );
        }
    });

    return React.createClass({
        initializeTouchEvents: function () {
            return (true);
        },
        getInitialState: function () {
            return {
                persons: []
            };
        },
        componentDidMount: function () {
            $.getJSON('/js/data.json').then(function (data) {
                if(this.isMounted()){
                    this.setState({
                        persons:data
                    });
                }
            }.bind(this));
        },
        render: function () {
            var items = this.state.persons.map(function (t) {
                return <Person {...t} />;
            });
            return (
                <div>
                    <A.Header title="通讯录3"/>
                    <A.List className="person-list">
                        {items}
                    </A.List>
                </div>
            );
        }
    });
})(AMUIReact);