Git vs Svn 谁更好?

起因

昨天同事过来问我,git一般是如何提交代码的。我吧啦吧啦说了一堆,同事一句,好像和svn差不多呀。我瞬间失语,我说我感觉git比svn好,同事问我,哪里比svn好?我说不出来。同事说等我想出来再和他说好了,我说好的。

随即,我就谷歌「git vs svn」,看看网上别人如何说的。在stackoverfiow上找到一个答案,说的很好,特来翻译给大家看看。

Node v5.0.0(Stable)

对Node.js v5说你好!我们确实在最近发布了Node.js v4.0.0,然而,这次新版本的发布并不意味着v4的远去。事实上,v4将会比v5存活更长时间。

根据我们最新的LTS(Long-term Support,长期维护版本)计划,Node.js v4 阿尔贡(Argon)将会持续支持30个月,在2018年5月停止维护。然而,此次发布的node.js版本,将仅仅只会支持8个月,与此同时,新的主版本v6,将会在2016年8月发布。Node.js v6将会像v4的时间轴一样,最终会进入新的LTS版本(长期支持版本)。这样一来,我们将会每隔6月有一个~稳定~版本,并且,第二个版本将会进入长期支持版本。如果你刚刚知道LTS,那么这里将会有关于LTS是如何工作的,以此来确保你可以对选择Node.js版本做出正确的决定。

对于选择Node.js版本的一般规则如下:

  • 如果你需要稳定并且处于复杂的生产环境,那么升级或停留在Node.js v4.2.x版本。例如你是一个中型或大型企业。
  • 如果你有能力在不会影响你的环境的情况下,快速、轻松的升级到最近版本,并且,愿意在最新特性出现的时候去尝试它,那么可以升级到Node.js v5。

下面的发布说明是确保可以跳跃到v5版本的主要不兼容变化。请注意,因为此次Node.js新版本采用新版本的V8引擎,你所有的基于本地的插件都需要重新编译,不然你将会收到运行错误当你尝试去加载它们的时候。使用npm rebuild,或者简单的删除node_modules文件夹再重新获取。

###主要改动

  • buffer:(不兼容)从Buffer对象中移除rawraws编码格式,它们已经被遗弃了很长时间#2859
  • console:(不兼容)console.time()的返回值现在会精确到小数点后三位。#3166
  • fs:
    • fs.readFile*(),fs.writeFile*()fs.appendFile*()现在也可以接受一个文件描述符作为它们的第一个参数#3163
    • (不兼容)在fs.readFile()中,如果一个编码格式被指定了,内部方法toString()在错误时不再会抛出(thrown)错误,但是将会通过回调(callback)表示。3485
    • (不兼容)在fs.read()中,如果内部方法toString()失败报错时,同样不会抛出错误,而是通过回调来表示。像这样fs.read(fd,length,position,encoding,callback)
  • http:
    • 修正http请求的流中会阻塞的问题。3342
    • (不兼容)在解析HTTP时,将不再复制一下头信息:Retry-After,ETag,Last-Modified,Server,Age,Expire

去掉oh_my_zsh主题自带的git检查

oh_my_zsh是一个非常好用和好看的命令行配置,它包含自动补全目录下git自动检查主题插件等功能,给在命令行下工作的人提供了非常好的便利。

前阵子配置vagrant虚拟机,为了打个环境给同事使用。考虑到有些命令需要在虚拟机里面完成,所以还是安装了一个oh_my_zsh

但是问题来了,在oh_my_zsh的默认主题中,当进入一个是git仓库的文件夹时,会自动读取.git里面的内容,了解当前的仓库状态,比如当前分支。可是在虚拟机里读取文件的速度要慢一些,这就会导致每一条命令都会检查一下当前仓库状态的这个行为会使得命令行开始输入的状态变的很慢。

一开始我以为是插件的原因,去掉git插件,sourse ~/.zshrc重载配置之后,还是如此,后来发现是主题的缘故。

我通常是比较懒的,既然默认主题有这个问题,那就找一个别的主题好了。

可是在oh_my_zshgithub上的theme列表中,每个主题都是含有这个功能的,所以只有自己修改主题了。

1
2
3
4
5
6
7
8
// 进入用户主目录
cd ~

// 进入oh_my_zsh的主题目录,这里保存着所有可以在其github上的主题库,我们只要改名字就可以引入对应的主题
cd .oh-my-zsh/themes

// 编辑默认主题文件
vim robbyrussell.zsh-theme

打开默认主题文件会发现其实就几行,像下面这样

1
2
3
4
5
6
7
local ret_status="%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ %s)"
PROMPT='${ret_status}%{$fg_bold[green]%}%p %{$fg[cyan]%}%c %{$fg_bold[blue]%}$(git_prompt_info)%{$fg_bold[blue]%} % %{$reset_color%}'

ZSH_THEME_GIT_PROMPT_PREFIX="git:(%{$fg[red]%}"
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%}"
ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[blue]%}) %{$fg[yellow]%}✗%{$reset_color%}"
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg[blue]%})"

需要将其修改为

1
2
3
4
5
6
7
local ret_status="%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ %s)"
PROMPT='${ret_status}%{$fg_bold[green]%}%p %{$fg[cyan]%}%c %{$fg_bold[blue]%} % %{$reset_color%}'

# ZSH_THEME_GIT_PROMPT_PREFIX="git:(%{$fg[red]%}"
# ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%}"
# ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[blue]%}) %{$fg[yellow]%}✗%{$reset_color%}"
# ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg[blue]%})"

也就是去掉git部分就好了,其他功能照常使用即可。

手Q一般化分享

今天在做一个需求,一般从客户端里分享出来的内容到QQ或者微信之类的地方都是设置好分享的图片、标题和内容的。

但是如果用户再次分享的话,看到分享链接样子就不是一开始分享的样子了,手机QQ会自动从页面中读取内容,通常是第一个h*标签(h1~h5),加上第一个imgp标签。

那么如果希望用户看到的分享链接的样子和页面里面实际上的样子不太一样或者话语不同的话,那么通常就需要事先写好内容,或者服务器动态生成内容,然后将内容隐藏起来。

在实际操作中,我发现有几个点需要注意:

  1. 隐藏的内容不会被预先读取出来
    如果用display:none的方式,不论是行内、页面内、还是外部样式表,都不会被预先读取。
    同时,将font-size设置为0也是无效的。
    通过使用
    1
    2
    3
    .share {
    text-indent:-999px
    }

的方式,可以将文字推出页面,但是这样页面原本有文字的部分依然会存在占位,所以还需要加上

1
2
3
4
.share {
text-indent:-999px;
position:absolut;
}

让文字部分脱离文档流。

  1. 对于图片可以一开始就使用position:absolute的方式,像这样:

    1
    2
    3
    4
    5
    .share-img {
    position:absolute;
    top:-999px;
    left:-999px
    }

  2. 对于分享链接的预读取是有缓存的,多久不清楚,所以调试的时候需要在链接后面加上?a=12312随机的东西让其认为是不同的页面。

如何自定义事件对象

之前因为开发中需要在自己的函数中增加一个事件处理机制。可惜在浏览器环境下只能自定义,如果在nodejs环境下可以继承自Event对象。

那么如何自己做一个Event类呢?

分析需求:

  • 绑定事件 : on
  • 触发事件 : fire
  • 移除事件 : remove

假设设计的api是这样的:

1
2
3
4
5
6
7
8
// 绑定事件
Event.on('some-event',handleFunc);

// 触发事件
Event.fire('some-event');

// 移除事件
Event.remove('some-event');

那么具体内部如何实现呢?

首先,我们需要一个东西保存这个事件名和事件名对应的函数。

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
function Event(){
this.eventList = {};
}

Event.prototype.on = function(eventName,fn){

// 不是string类型,就直接返回,不执行后面
if(typeof eventName != "string") return;

// 后面需要用到
var self = this;

// 如果有多个事件,分割出来
eventName = eventName.split(" ");

// 对每个事件进行遍历
eventName.forEach(function(val){
// 因为有可能对同一个事件绑定多个方法,那么就需要用一个数组来保存这个事件。
// 因此,第一次的时候这个保存这个事件的数组不存在,所以需要用下面的方式创建出来
self.eventList[val] = self.event[val] || [];

// 这里是当只有回调函数参数是函数时才会将其加入队列
if(typeof fn == "function"){
self.eventList[val].push(fn)
}
})
}

上面是绑定事件,其实按照思路写下来也是很简单的。下面是触发事件。

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
Event.prototype.fire = function(eventName){
if(typeof eventName != "string") return;

// 首先每个函数内部都可以取得一个`arguments`的类数组对象
// 该对象保存着所有传递进来的参数
// 也就是说,也可以通过arguments[0]来取得第一个传递进来的参数,以此类推。
// 那么往往有这样一个需求,在触发事件的时候,需要传递进来参数,但是通常不确实需要传递进来多少个参数,这时我们可以通过这个arguments来取得传递进来的参数。
// 但是有一个问题是,第一个参数是被触发的变量名,需要将第一个变量名剔除掉。

// 我们都知道数组对象有一个方法是`shift`,它会将数组的第一项去掉,并返回回来。
// 但是arguments只是类数组,并不是数组,需要将它转换为数组
// 最快的方式就是调用Array的slice方法,用call将slice方法的指针指向arguments,以此返回一个和arguments对象一样(参数一样)的数组
var args = Array.prototype.slice.call(arguments);
// 去掉第一个参数
args.shift();

// 取得事件数组
var eventList = this.eventList[eventName];

if(eventList instanceof Array){
eventList.forEach(function(val){
// 如果只有一个参数,确实可以直接调用的
// 但是因为参数是一个数组所以使用apply方法
val.apply(null,args)
})
}
}

到此,触发也就写好了,注意,这里我都是使用了forEach方法,这个方法在IE8以下不支持,需要改成for in方法。

其他的remove或者once等,也是在此基础上,比如remove就是找到之后删掉对应的方法,once是增加一个选项,在事件触发之后去掉该事件。

vagrant brew install git error

前言

前几天因为需要在php5.4Mysql环境中开发,所以准备搞一个虚拟机,跑一个vagrant

今天安装git的时候,感慨Mac OS下有homebrew,随便一搜,发现linux下确实也有brew,一个homebrew的分支linuxbrew

安装非常简单。

安装

首先身平台自带的安装工具yum或者apt-get安装依赖。

Debian or Ubuntu

1
sudo apt-get install build-essential curl git m4 ruby texinfo libbz2-dev libcurl4-openssl-dev libexpat-dev libncurses-dev zlib1g-dev

Fedora, CentOS or Red Hat

1
sudo yum groupinstall 'Development Tools' && sudo yum install curl git irb m4 ruby texinfo bzip2-devel curl-devel expat-devel ncurses-devel zlib-devel

之后,运行安装脚本就好了。

1
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/linuxbrew/go/install)"

安卓webView点击事件无效的问题

前阵子应公司这边需求,开发嵌入在webView里面的页面,结果测试同学发现页面第一次载入的时候,是无法点击的,只有当页面滑动之后才可以点击。

通过查看Eclipse里面的log发现,在点击的时候,webView报错,页面没有错误,页面的事件都没有触发。

通过在页面载入之后的一瞬间执行

1
2
document.body.scrollHeight = 1;
document.body.scrollHeight = 0;

就可以了。

小米部分机型存在即使这样做,也有部分点击会报错的问题。

回龙观,联通,送的Moden兼路由器无法上网问题

最近搬家到了回龙观,告别了各种奇怪情况的铁通,选择了联通。

本来第一次去办联通宽带的时候,50M一年1798,100M一年1998,我一看那100M好了。办理的时候小姑娘提醒我100M只有70、80M,50M只有40M左右,好吧,忍了。。。

后来又说最多只能连接4台电脑,这我就有点不能忍了。我妈两台电脑,我两天电脑,我老爸两台电脑,我老婆一台电脑,这是要同时考验夫妻关系、父子/母子关系、婆媳关系么?于是我就走了。

后来,想了想,又问了一下,说是最多只能4台台式机,无线设备多少都无所谓,好吧,看了看旁边中国移动(铁通),还是选择了联通。

联通的师傅还挺好,上门来给安装,只是必须用联通提供的设备上网。设备还不错,有Moden拨号的功能,还自带路由、无线功能。装上之后,手机就可以上网了。

由于家里是小米路由器连接的,后来经常有电脑没法上网。

而且是有时可以上,有时不可以,有的可以上,有的不可以,状况很奇怪。

经过检查发现,所有不能上网的设备的IP地址都是小米路由器分配的,所有可以上网的设备IP都是联通设备分配的,如此说来应该关闭小米路由器的DHCP,让所有的IP都由联通设备分配就好了。

一关上,果然不再出现问题。

当时上网找了很久没法人给出答案,希望这篇文章可以给遇到同样问题的人一点帮助。

申请微信公众服务号需要准备的东西

之前本来说好给一个创业的前辈做微信服务号的,为此特地去看了好几遍微信公众平台开发文档,寻找了好几个封装好的库(nodejs、PHP的都找了一遍)没想到后来跳票了。
但之前总结的东西不想废弃在那里,放出来希望对大家有帮助。

流程

申请微信公众号需要5个步骤,分别为:
1. 填写基本信息
2. 邮箱激活
3. 选择类型
4. 信息登记
5. 公众号信息
下面,针对每个流程,给出说明、需要的材料以及注意事项。

1. 基本信息

这个地方只需要填写邮箱和密码。
* 注意:
    邮箱作为登录账号,不可以使用注册过微信公众号的邮箱,即使是绑定在个人微信号上的邮箱也不行。
    另外,最好使用国内的邮箱(QQ邮箱,你懂的)。虽然我用gmail注册,发送邮件也是很快的,不过国外的邮箱不稳定。

2. 邮箱激活

这一步没什么好说的,微信公众平台会向上一步填写的邮箱地址发送一封激活邮件,去邮箱里面激活即可。

3. 选择类型

类型选择
确认提示

在这一步,将会选择微信公众号的类型。
因为一个公众号只能选择一次,所以一定要慎重。
具体的信息看图上就好了。

VMware Fusion Nat链接方式下固定IP

因为一些特别原因,在公司开发时只能虚拟机只能使用Nat链接方式,如果使用桥接方式,不同ap无法访问到我电脑内的虚拟机。只能通过端口转发方式,让别人的电脑访问我虚拟机做测试。

可是每次启动电脑时,虚拟机内的ip地址都会变。VMware Fusion并没有界面化的设置,需要在命令行中进行设置。

设置端口转发

1
cd /Library/Preferences/VMware Fusion/vmnet8
sudo vim nat.conf

找到

1
[incomingtcp]

# Use these with care - anyone can enter into your VM through these...
# The format and example are as follows:
#<external port number> = <VM's IP address>:<VM's port number>

在下面添加一行

1
// 9000是我本地转发的端口,假设本机IP地址:192.168.1.82,那么同事测试时访问192.168.1.82:9000即可访问到虚拟机
// 9000端口的请求,转发到虚拟机的80端口上
9000 = 172.16.59.131:80

到这一步虚拟机端口转发就做好了,Esc+ZZ或者Esc+wq保存并退出。