798.space漫游指南¶
目录:
银河系的历史又翻开了新的一页¶
798.SPACE - 打造你自己的垂直社区。
引子¶
乔布斯说 : “活着就是为了改变世界”。
然后,他死了。

某年某月末日,看了一篇关于中国共产党从无到有,从小到大的故事。
不由得心潮澎湃。
这真是人类史上最宏大的史诗级创业故事。
一小撮与众不同的热血青年,除了共同信仰一无所有。
他们用自己的双手和生命,点燃神洲大陆的星星之火,缔造了一个史无前例的红色帝国。
虽然有波折,有挫败,有狰狞岁月,有九曲回肠。
但是毋庸质疑,最终,他们还是成功了。
时至今日,最初十几个人的小团队,已发展成为地球上最大全产业链集团。
这真是一个传奇,属于他们那代人的传奇。
忆古思今,我们这一代人,又将会缔造怎样“史诗级创业故事”呢。
而我,又能在其中做些什么呢?
左思右想,辗转反侧,我最终觉得,只有整合全人类的力量,拉开星际移民时代的大序幕。

唯有这样创业故事,才能媲美他们史诗级的传奇。
但,面对这样伟大的事业,我又能干什么呢?
毕竟,我只是一个写网站小程序员,就像黑客帝国里的那个码农Nero。
左思右想,辗转反侧,我最终觉得,还是写先个网站吧,毕竟整合全人类的力量首先需要一个网站。
于是,便有了后面的故事。
序¶
“我多么希望世界上有个小岛,居住的全是智慧又善良的人们”。
—爱因斯坦
访问 798.SPACE 你可以很轻松的创建自己的垂直社区。



千里之行,始于足下。

798.SPACE 名字的起源¶
798,北京著名艺术区。
前身是当年集全东德的电子工业力量,包括技术、专家、设备生产线铸成的宏大工厂。
这是一个带有很强乌托邦情怀的盛大工程,属于那个懵懵懂懂的时代。
后来,工厂没落了,柏林墙倒了,东德也成为了历史教科书上的名词。
一群流浪艺术家驻扎了过来,把废弃的厂房改造成为了中国最著名艺术区。

有一天,我注册到了 798.SPACE ( 中文含义: 798.空间 或 798.太空 )这个域名,我很喜欢这个名字。
科技与艺术,理想的老去,废土的重生,自由的创作与自我的表达,等等等等。
总而言之,我觉得它寓含了很多东西。
就是它了,798.SPACE 。
地球是人类的摇篮,但是人类绝不会永远躺在这个摇篮里
—前苏联科学家,康斯坦丁·齐奥尔科夫斯基
关于作者¶
生活不是贴在墙上的日程表。生活是充满激情、荆棘、光荣与梦想的伟大冒险。
程序是一种艺术创作,仿佛上帝在编码DNA,哺育着一个有着灵魂的数字生命。
—Noman
洛曼,喜欢科幻,每日YY。典型宅男。
与笔记本相依为命,不喜欢与人类接触。
是的,这是一只靠想象和自我催眠而维持存在的奇特地球生物。

欢迎关注我的 新浪微博
‘洛曼’ 昵称的由来¶
雷军在小米创业初期,很低调,他说:“人若无名,便可专心练剑” 。
一旦大家知道是雷军在做,期望值就会高,他希望用户认为“就是张三、王五做的,甚至没有名字做的。”
心有戚戚。红尘多纷扰。
太多机会、太多诱惑,常让人忘记出发的初心。
隐姓埋名,专心做事。
不与人争论,不多加解释。
于是,启用 Noman(诺曼)作为化名。
但,诺曼太西化了,便改写为 “洛曼”。
加盟指南¶
想加入开发,请邮件 noman@798.space ,写明您的姓名,城市,擅长技能,微信或QQ 。我们会进一步联系您。
更多资源请参见文档首页的 相关链接 。
项目规划¶
2015-4-13¶
我们需要实现的几个基本功能如下:
- 基本的用户注册登录
- 实现类似google reader的RSS订阅阅读功能
- 垂直社区可以默认订阅一批社区中的优秀博客,作为这个社区的资讯聚合和上网导航
- 桥接入微信公众号的订阅
- 手机浏览器的适配
- 完善程序的开发文档,以便于新人加入
配置开发环境¶
运行docker镜像¶
配置开发环境是一个既繁琐又无趣的事情。
人生漫漫,有很多山峰等值我们去征服。但毫无疑问,配置开发环境不是其中之一。
我们以基于Centos7.0为例讲讲一下部署步骤。
大家可以在 QingCloud 上开启一个全新的Centos7.0系统运行该脚本。
以下各步骤都以root身份运行。
如果不是root用户,可以先sudo su切换到root用户
sudo su
我们先更新升级系统 , 安装 docker 和 hg
yum update -y
yum install epel-release -y
yum install docker mercurial nginx tmux -y
然后启动 docker ,并添加到开机启动
service docker start
service nginx start
systemctl enable docker
systemctl enable nginx
因为众所周知的原因,国内的docker被墙了,我们需要启用一下加速服务
访问 DaoCloud的docker加速服务器 (登录后点此链接),按照网页底部的 操作手册->Centos 篇配置一下docker加速服务器。
接下来,我们pull最新798的镜像。
这个需要的时间比较漫长,我们通过nohup让其在后台一直运行,这段时间,我们可以断开ssh去睡觉了。
nohup docker pull 798space/798 &
我们可以通过tail来观察pull的进度( Ctrl+退出观察)
tail -f nohup.out
如果出现以下文字就是更新完毕:
Status: Downloaded newer image for 798/798:latest
我们可以通过 docker images 浏览看到 798 镜像。
如果出现问题可以重新pull一下,多尝试几次也许就好了。
接下来我们用hg clone下我们开发环境的home目录 ,并且启动docker
mkdir -p /home/
cd /home/
hg clone https://bitbucket.org/798space/docker_home 798
rm -rf /home/798/.hg
cd /home/798/
hg clone https://bitbucket.org/798space/798
最后启动docker
docker run -d -i -p 4242:4242 \
-p 10922:22 -p 10900:10900 -p 10901:10901 \
-p 10902:10902 -v /home:/home --name 798 \
798space/798 /etc/init.d/ssh start -D
注意,你需要配置云主机的防火墙,暴露 10922 , 4242 端口以便于我们从远程ssh访问登录docker镜像和修改html后浏览器自动刷新。
启动后,我们可以通过
docker ps
看到我们正在运行的docker
关机后重启这个docker镜像的命令是
docker start 798
然后我们就可以ssh登录进入docker
ssh 798@127.0.0.1 -p10922
127.0.0.1 也可以改为你服务器远程访问的IP
docker的798用户默认的密码是 798devos
登录进入docker镜像后,我们先修改一下文件权限
sudo chown 798:798 /home/798 -R
然后我们需要生成一下nginx的配置文件
cd ~/798/cli/docker
cp config.example.py config.py
你可以编辑config.py
vi config.py
修改域名为你自己域名。如果你想启用真实的域名,请将裸域名和泛域名都指向这台服务器
如果只是为了开发,可以保留原来的测试域名,然后在本机修改hosts文件指向此服务器。
如何配置hosts ?¶
windows用户用笔记本打开
C:\Windows\System32\drivers\etc\hosts
mac和linux用户请修改 /etc/hosts
在末尾添加3个域名 ,其中IP改为你自己服务器的IP,域名为你自己配置的域名,ministe.xxx通过798.space创建的垂直社区的域名,可以是任意域名
192.168.10.169 798.space
192.168.10.169 798-docs.798.space
192.168.10.169 minisite.xxx
生成配置文件¶
运行脚本生成配置文件
python ~/798/cli/docker/make_config.py
注意,因为我们的vim默认配置了折叠插件,命令模式下zn可以打开折叠
然后我们 ** 回到docker的母机 ** ,修改nginx的配置文件
vi /etc/nginx/nginx.conf
删除配置文件最后整个 server 那一大段(因为default server冲突)
然后软链nginx的配置文件,重启nginx服务器
cd /etc/nginx/conf.d
ln -s /home/798/798/build/nginx.conf 798.conf
service nginx restart
OK,大功告成。
我们回到docker服务器中,启动开发环境
cd ~/798
./cli/dev
你应该可以看到网页了,COOL !
如何发布到线上?¶
还是先编辑 /cli/docker/config.py
修改HOST域名为线上服务器的域名,修改STATIC_HOST为静态文件服务器的域名。
其中STATIC_HOST静态文件最好是与主站完全不同的根域名,这可以避免http请求头中总是包含cookie的开销。
我们建议使用 七牛云存储 的 空间设置 -> 镜像存储,直接镜像主域名,做它的CDN的反向代理,以加速访问。
同时还建议在启用其 空间设置 -> 域名设置 中的 HTTPS, 然后就把这个支持https的qbox.me的域名作为STATIC_HOSTd的域名即可。
完成以上步骤后,运行 make_config.py 生成配置文件。重启母机的nginx。
然后运行 ./cli/publish 更新发布的html即可。
798.space 目录导读¶
我们先来看一下项目的目录结构, 常用的目录和文件如下
首先是最重要的启动开发环境脚本,我们在这个脚本中启动了FIS,PLIM,CoffeeScript,Scss的自动编译进程
- cli
- dev
然后是rpc目录 。
- rpc
- root.json.py
写静态页面时,可以先与后端约定好交互数据数据结构。
在后端接口完成之前,在此按约定好的结构定义一些假的json数据,以实现并行开发 。
rpc 目前中是存放的是python脚本,以 .json.py 结尾,文件内容类似
class FAKE:
index = [
"昵称",
32, #未读消息数
...
]
启动开发环境后,当你修改.json.py文件是,会自动编译生成对应的json数据的静态文件到build目录下(生成的文件于.json.py的文件名,以及FAKE中的函数名相对应)。
同时build目录也是FIS发布项目时候生成静态文件的部署目录。
我们可以通过访问诸如 http://你的域名/rpc/root.index 来看到生成的内容。
这样我们就可以在javascript中很方便使用 /rpc/root.index 这个地址来获取数据(这与后端真正实现接口后的数据获取路径是一致的,区别只是域名不同)。
- build
- rpc
- root.index 由root.json.py生成
leancloud云代码,该目录内容相当于用js写的后端代码
leancloud
- cloud 后台由coffee编译的js代码
- coffee 后台coffee代码
- config 配置文件目录
- public
- deploy 将本地源码推送到 LeanCloud 云代码平台运行 ./deploy
其它目录
pure
- fis-conf.js fis配置文件
- css css通常由scss生成,一般不会直接修改
- html html通常由plim生成,一般不会直接修改
- modules 由coffee生成的js文件存放目录,一般不会直接修改
- lib 库文件存放目录,库文件例如semantic等,包含css和js
plim plim文件存放目录
coffee coffee文件存放目录
scss scss文件存放目录
docs 文档
config.rb compass配置文件
replace_line.py 用于替换文件中字符串的脚本,FROM_STRING是原来的字符串,TO_STRING是替换后的字符串,修改完之后F12运行一下完成文件中的替换
coffee目录中的plim¶
在我们写网站的时候,经常会有写弹出框的需求.这时通常我们会在coffee文件中引入plim文件,为了解决查找麻烦的问题,我们将会用到的plim文件写在coffee的目录下,这样当引用plim文件时将会更加方便。
我们用到了下列技术
FIS¶
798.space 使用基于 FIS 的 PURE 作为我们纯前端开发框架的基础框架。
我们运行 ./cli/dev 脚本启动开发环境的时候,就启动了pure (PURE是FIS的一个定制版)。
FIS是专为解决前端开发中自动化工具、性能优化、模块化框架、开发规范、代码部署、开发流程等问题的工具框架。
它提供了很多实用的特性来提供我们的开发效率。比如,修改保存之后html或脚本文件之后,浏览器会自动刷新网页。
详情参阅 * FIS前端工具框架
我们特别强调几点。
FIS可以通过pack来进行资源文件的合并,比如我们需要将DEMO中的公共库文件打包在一起,可以修改fis-conf.js配置,加入pack配置:
fis.config.set('pack', {
'pkg/lib.js': [
'/lib/mod.js',
'/modules/underscore/**.js',
'/modules/backbone/**.js',
'/modules/jquery/**.js',
'/modules/vendor/**.js',
'/modules/common/**.js'
]
});
FIS可以在javascript脚本中对于声明其关于javascript和css的依赖关系,输出时,会自动在生产的HTML静态文件中引用相关的样式和脚本。
也可以在javascript通过 __inline 引用html文件, 这对于编写单页面全动态的网站(类似Gmail这种)帮助巨大。
详情参见 三种语言能力
leancloud¶
LeanCloud 提供一站式后端云服务,从数据存储、实时聊天、消息推送到移动统计,涵盖应用开发的多方面后端需求。
以后再也不用租服务器,也不用写后端代码了。
js数据存储开发相关链接 :
leancloud云代码命令行工具¶
leancloud云代码命令行工具是用来管理、部署云代码项目的命令行工具,称之为avoscloud-code项目。通过它,你可以部署、发布、回滚云代码,并且可以对同一个云代码项目做多应用管理,还可以查看云代码日志,批量上传文件到LeanCloud平台上等
安装avoscloud命令行工具:
sudo cnpm install -g avoscloud-code
在你开发和本地测试云代码项目通过后,你可以直接将本地源码推送到 LeanCloud 云代码平台运行,只要执行 deploy 命令:
./deploy
PLIM模板¶
plim 是 MAKO模板 的一种简便写法。
所以,你需要先了解什么是Mako。
请先仔细阅读相关文档
用plim模板写html有一些好处。
- 比写html更加简单,代码量更加少
- 再也不用担心html标签的闭合问题
- 简单的缩进表示嵌套让代码看起来更整洁
通常的页面,我们通过继承简化代码结构,比如继承基模板(基模板是所有页面都要继承的模板)
-inherit /_base/page.plim
基模板将html分成head,body,script 三部分(mako中的block),三部可以分别被重载.
比如,继承基模板的head(head部分一般引用css文件):
-block head
= parent.head()
<!-- @require /css/index.css -->
如果是直接继承/_base/page.plim,parent.head可以省略,下同。
继承基模板的script(一般位于模板结尾,引用js文件):
-block script
= parent.script()
scrpit
require('798')
其他部分将自动插入基模板的next.body()部分
SASS¶
Sass是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护。
Sass的使用方法使你的css的扩展和维护工作变的更加容易
相关链接 :
通常情况下SCSS分成三个等级来引用:全局级,模块级,页面级
全局级和模块级的SCSS文件名用下划线开头,如_base.scss,_head.scss等
其中head部分,sidebar部分一般作为一个模块被引用。
当页面级的SCSS需要被其他SCSS引用时,请用@import
所有的SCSS导入文件都可以忽略后缀名.scss。
不被直接引用的css样式组件,我们以 _ 作为文件名的开头,如 _mixin.scss 。
这种文件在导入的时候可以不写下划线,可写成
@import "mixin"。
Compass¶
简单说,Compass是Sass的工具库(toolkit)。
Sass本身只是一个编译器,Compass在它的基础上,封装了一系列有用的模块和模板,补充Sass的功能。它们之间的关系,有点像Javascript和jQuery、Ruby和Rails、python和Django的关系。
我们使用compass来编译我们的scss脚本。
相关链接 :
Coffeescript¶
CoffeeScript,是一种更好的JavaScript。
使用Coffeescript可以避免书写JavaScript时候遇到的许多问题,同时也能简化我们的代码书写。
比如,忘记用var定义变量,导致局部变量成为全局变量,进而导致名字空间的污染。
比如,可以用 for ... in , 而不用 for(var i=0;i<arr.length;++i) 如此麻烦的写法。
我们在项目中禁止书写原生JavaScript,所有的脚本都请用Coffeescript编写。
如果你在网上找到一些JavaScript脚本,希望copy&paste加以使用,请先通过 js2.coffee 将其转换。
相关链接 :
Semantic UI¶
Semantic UI—完全语义化的前端界面开发框架
跟 Bootstrap 和 Foundation 比起来,还是有些不同的,在功能特性上、布局设计上、用户体验上均存在很多差异。
Semantic UI 比Bootstrap更语义化,使用了更容易理解的标签名称:导航的是nav,主要内容的是main,class名也很明确,而且不像Bootstrap需要套很多层。Bootstrap很通用,兼容性很好,甚至能兼容低版本的IE,Semantic-UI则更Geek,有不少CSS3的特性,比如Shape和Reveal就很有趣。从界面设计风格来说,Semantic比Bootstrap(2)更扁平化.
我们在基模板中引用Semantic UI,编写代码时,注意复用Semantic UI中已有的功能组件
相关链接 :
avalon¶
avalon是一个简单易用迷你的MVVM框架,为解决同一业务逻辑存在各种视图呈现而开发出来的。
MVVM将所有前端代码彻底分成两部分,视图的处理通过绑定实现, 业务逻辑则集中在一个个叫VM的对象中处理。我们只要操作VM的数据,它就自然而然地同步到视图。
相关链接 :
开发环境导读¶
在正式开始开发之前,我们不妨回顾一下我们在docker开发环境中的Linux命令,以及一些我们自定义的小工具。
- TAB 键自动补全
- ls 列出目录
- ls -al 使用格式化列出隐藏文件
- pwd 显示当前目录
- cd <dir> 切换到 dir 目录
- cd 切换到 home 目录
- cd .. 切换到父目录
- mkdir <dir> 创建目录
- touch <file> 创建文件
- cat <file> 显示文件内容
- less <file> 逐页显示文件内容
- more <file>
- head <file> 显示文件头 10 行
- tail <file> 显示文件后 10 行
- tail -f <file> 开始监控文件内容改动
- xtail /var/log/nginx/* 批量监控nginx日志
- ctrl+c 结束程序
- ctrl+z 停止当前程序,可使用 fg 恢复
- ctrl+w 删除当前行中文字
- ctrl+u 删除整行文字
- ctrl+a/e 将光标移动至行首/尾
- ctrl+r 搜索最近使用的命令
- bg 列出已停止或者后台程序
- fg 将最近作业带到前台
- locate <file> 查找某个文件所在位置
- top 参看当前运行的进程
删除vim非正常关闭的临时文件 deltmp¶
当vim非正常关闭或文件被同时打开两次时的时候,会有临时文件
如何当一个文件上次打开时被非正常关掉.再打开时,按R恢复文件,然后:wq保存退出。
最后用deltmp命令删除临时文件
tree 以树形显示当前目录结构¶
- tree 以树形结构显示当前目录下所有文件和目录
- tree -d 仅显示目录
- tree -L <num> 限制目录的最大深度
ag 搜索¶
- ag <something> 在目录所有文件中寻找 something
- ag <something> -py 在所有 Python 文件中搜索 something (CSS,JS同理)
autojump 一键直达目录¶
在命令行中切换目录是最常用的操作,不过很少有比一遍又一遍重复“cd ls cd ls cd ls ……”更令人沮丧的事情了。如果你不是百分百确定你想要进入的下一个目录的名字,那么你不得不使用ls来确认,然后使用cd来进入你想要进的那一个。所幸的是,现在大量的终端和shell语言提供了强大的自动补全功能来处理该问题。但是,你仍然需要一直疯狂地敲击TAB键来干这事。如果你和我一样懒惰,你一定会对autojump感到惊喜。
autojump是一个命令行工具,它允许你可以直接跳转到你喜爱的目录,而不用管你现在身在何处。
- j <dir> 根据最近工作目录记录跳转到最合适的位置。
如果你不确认哪里是不是你要跳转的地方,敲击TAB键就会列出完整路径。
还是同样的例子,输入
autojump d
然后敲击tab键,将会返回/root/home/doc或者/root/home/ddl 。
如果你突然想要把当前目录变成你的最爱和使用最频繁的文件夹,你可以在该目录通过命令的参数 i 来手工增加它的权重
j -i [权重]
这将使得该目录更可能被选择跳转。相反的例子是在该目录使用参数 d 来减少权重
j -d [权重]
42qucc¶
42qucc 是在线的随手贴,可以随意地自定义网址来自己记录或与朋友分享文字。
保存¶
42qu.cc 提供在线分享文本文件的功能。在命令行中输入
42qucc < 某个文件名
即可获得诸如 http://42qu.cc/6nhxuqpg 格式的网址,打开该链接即可看到分享的内容。
我们也可以自定义生成的网址
42qucc xxx < 某个文件名
Linux的回收站 - trash-cli¶
凡事只要有可能出错,那就一定会出错。
—墨菲定律
啊,删错文件了!!!
好吧,这已然是第N+1次了。
“此情可待成追忆,只是当时已枉然”。
我一直认为Linux最不人性化的设计就是没有回收站。
长期以来,rm命令就像一颗隐形的地雷,不知道什么时候就被踩到,壮烈牺牲。
“出师未捷身先死,长使英雄泪满襟”。
幸好,我们还有trash-cli,Linux的回收站。
与其等不小心误删除后去追悔莫已,去苦心钻研如何恢复文件,不如一开始就防患于未然。
故,兵书曰,善战者无赫赫之功。
想使用trash-cli,首先安装
sudo pip install trash-cli
然后修改全局的bashrc
alias rm="trash-put"
trash-empty 99
这样删除文件就会进入回收站而不被直接删除了。同时清空删除超过99天的文件。
通常全局bashrc的路径是
/etc/profile
此外,我们可以在root用户的crontab中配置
trash-empty 99
每天晚上3点执行,自动清空删除超过99天的文件
trash-cli 的命令如下
- trash-empty 清空回收站
- trash-list 查看被删除的文件
- restore-trash 恢复被删除的文件
- trash-rm 从回收站中删除单个文件
更多内容请浏览trash-cli 官方主页
本工具在798的docker镜像已中经内置并默认启用
如何贡献代码¶
如果你想给798项目贡献代码,请遵循以下步骤
然后修改一下hg配置文件
vi ~/.hgrc
修改
username = undefined <undefined@798.com>
修改为你自己的昵称和邮箱
然后运行
ssh-keygen
一路回车生成你自己的公私钥, 然后
cat ~/.ssh/id_rsa.pub
然后注册 bitbucket , 将这个公钥贴到 右上角头像 > Manage account -> 左侧栏 SSH keys -> Add Keys ,Label可以留空,内容为上面cat显示的公钥。
- 注册 bitbucket 账户
- 访问 https://bitbucket.org/798/798/fork fork 项目 798
- 修改 hgrc
- 运行ssh-keygen生成私钥,并配置bitbucket的ssh私钥
- 提交pull-request
常用js函数¶
NProgress.js¶
显示进度条:
NProgress.start()
设定一个百分比:
NProgress.set(0.4)
增加一点进度:
NProgress.inc()
完成进度:
NProgress.done()
store.js¶
store.js 是一个兼容所有浏览器的 LocalStorage 包装器,不需要借助 Cookie 或者 Flash。store.js 会根据浏览器自动选择使用 localStorage、globalStorage 或者 userData 来实现本地存储功能。
相关链接 :
__uri¶
js中,可以使用编译函数__uri(path)来定位资源,fis分析js文件或html中的script标签内内容时会替换该函数所指向文件的线上url路径。 如,源码:
js = __uri('demo.js')
编译后:
js = '/demo_33c5143.js'
798.coffee¶
解释一下该文件的代码
其中的:
clientWidth = $(window).width()
if clientWidth < 414
scale = (clientWidth/414)
document.write("<style>body{zoom:#{scale}}</style>")
用于做对手机的适配
其中的:
if current_user
current_user.fetch()
src = __uri("/modules/798/login1.js")
else
src = __uri("/modules/798/login0.js")
document.write("""<script src="#{src}"></script><script>require("798/login#{!!current_user-0}")</script>""")
当用户登录时,引用login1.js
当用户未登录时,引用login0.js
require.js的用法¶
引入require.js的原因:当我们要引用多个js文件时,首先,加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序,依赖性最大的模块一定要放到最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。而require.js的异步加载方式和依赖加载方式能够很好地解决这一问题。
在coffee中引入依赖模块的写法:
require_async(
["jquery","wow"]
->
...
)
其中require_async接收两个参数,一个是数组,数组元素即是依赖模块文件(省略.js);另一个是回调函数,当前面指定的模块都加载成功后,它将被调用。
有关模块化编程的相关链接 :
弹出窗效果modal.coffee¶
文件目录coffee/lib/modal.coffee
文件共两个调用函数:
$.modal,$.modal_alert
$.modal接收四个参数,分别是html代码,semantic UI modal模块的配置option对象(可选,默认为空对象),avalon view的id(可选),view对应的回调函数(可选)。$.modal无返回值。
$.modal_alert接收两个参数,分别是html代码,semantic UI modal模块的配置option对象(可选,默认为空对象)
两者效果都是弹出框,前者是一般性的弹出框,后者弹出”我知道了”作为确认提示.
出错提示工具$.error_tip()¶
工具所在文件coffee/lib/jquery_ext.coffee
$.error_tip()接收两个参数,分别是出错提示对象elem,focus出错时是否选中文本并focus第一个出错位置。
引入js工具$$¶
工具所在文件coffee/lib/async.coffee
为了方便调用注册,登录等模块,我们经常将其写成js,并用$$工具引入。
$$引入的js有其固定的写法,当coffee文件的位置为 coffee/SSO/auth.coffee时,该文件的开头写成:
$.SSO.auth = {
new : ->
...
login : ->
...
}
可以用$$(‘SSO/auth.new’)和$$(‘SSO/auth.login’)调用
基础知识:
avalon - 前端¶
avalon是很好用的双向绑定框架。
为了方便使用,我们做了一些小修改。
首先,ms-controller 改名叫做 ms-view ,我们觉得 controller 这个单词太长了。
其次,事件的回调函数中 return false 可以阻止事件继续传播 , 这可以jquery的使用习惯保持一致。
然后,为了方便不同的 view (controller) 之间相互调用,我们引入了一个全局变量 V 指向 avalon.vmodels 。
最后,我们因为已经使用了百度fis提供的mod作为require加载器,所以我们使用的avalon的shim版本。
常用工具 :
vim¶
vim 快速入门¶
vim 简介¶
在这个蔚蓝色的星球上,流传着两大神器的传说:Emacs是神的编辑器,而Vim是编辑器之神。
VIM , 全称 Vi Improved , Vi的增强版 。
Vi 在 1976 年发布,奉行 Unix 传统的“Do one thing and do it well”哲学,每个程序只做一件事但做到最好,通过程序之间的配合得到强大的功能。
Emacs则奉行“Everything at reach”设计哲学,通过强大的扩展性,达到在一个软件里做所有的事。Emacs可以用来编辑文档、时间管理、浏览图片、阅读pdf、听音乐、写程序、运行程序、调试程序、接受发送邮件、看新闻组、玩游戏、管理系统、Telnet/FTP、版本控制、写LaTex…被称为“伪装成编辑器的操作系统”。
江湖中有一句话: “ 世界上的程序员分三种,一种使用Emacs,一种使用Vim,剩余的是其它” 。
基本概念¶
Vim 有两种模式——Normal 模式和 Insert 模,所有命令都是在 Normal 模式下执行。启动 Vim 后,默认进入 Normal 模式, 可以按 i 键进入 Insert 模式,或者 s 删除当前字符并进入 Insert 模式,退出 Insert 模式进入 Normal 按 ESC 。
下面的教程中约定 + 表示同时按其左右的按键,小写字母(如 i)表示按该字母一次,大写字母(如 G)表示同时按 shift+g。
基本用法¶
- i insert 输入
- v 行选中
- ctrl+v 列选中
- G 至文末
- gg 至文首
- :q 未修改退出
- :q! 强制不保存退出
- :x / :wq 保存并退出
- J 合并多行
- d 删除当前所选
- dd 删除多行并存在剪贴板中(剪切)
- y 复制当前所选
- yy 复制整行
- p 粘贴
- u 撤销操作
- w 光标移动到下一个单词处
- b 光标移动到上一个单词处
- ^ 光标移动到行首
- $ 光标移动到行尾
- kjhl 或者上下左右键移动光标
- shift+上下键 翻页
- shift+左右 光标乙至上/下一个单词(以空格/标点区分单词)词首
- u 撤销上一步操作
- zo/zn/zc 折叠/展开代码块
- :vsp 新建工作区
- ctrl+w 松手后再按 方向键 切换工作区
- :MR 选择最近打开的文件(需安装插件)
- F12 运行当前文件
- # 搜索光标处短语
- :set paste 进入粘贴模式
- :%s/target/something/g 替换全部 target 字段
- :s/target/something/g 替换选中区域 target 字段
vim名词解释¶
模式 ~~~
vim有5中基本模式,分别是
- Normal Mode 也就是最一般的普通模式,默认进入vim之后,处于这种模式。
- Visual Mode 一般译作可视模式,在这种模式下选定一些字符、行、多列。 在普通模式下,可以按v进入。
- Insert Mode 插入模式,其实就是指处在编辑输入的状态。普通模式下,可以按i进入。
- Select Mode 在gvim下常用的模式,可以叫作选择模式吧。用鼠标拖选区域的时候,就进入了选择模式。 和可视模式不同的是,在这个模式下,选择完了高亮区域后,敲任何按键就直接输入并替换选择的文本了。 和windows下的编辑器选定编辑的效果一致。普通模式下,可以按gh进入。 ps:这种模式好无用啊
- Command-Line/Ex Mode 就叫命令行模式和Ex模式吧。两者略有不同,普通模式下按冒号(:)进入Command-Line模式,可以输入各种命令, 使用vim的各种强大功能。普通模式下按Q进入Ex模式,其实就是多行的Command-Line模式。 ps:经常使用EX模式的都是神阶vimer
注:本文中所说的快捷键若无特殊说明则是Normal Mode下的模式
Windows/窗口¶
vim可以将窗口分成好多个独立的块来显示不同的文件,我们把这些块叫做窗口。当然你可以选择竖着分或者横着分,横着分的叫做split window,竖着分的叫做vsplit window。
Tab/标签页¶
就像chrome的标签页一样。
Buffer/缓冲区¶
缓冲区(Buffer)是一块内存区域,里面存储着正在编辑的文件。如果没有把缓冲区里的文件存盘,那么原始文件不会被更改。 可以通过:ls或:buffer命令查看缓冲区
插件¶
Vundle插件管理器¶
Vundle的功能是用于安装和管理其他插件,它能够直接从github上下载并自动安装置顶的插件。其本身也托管在github上,我们可以使用下面的命令快捷的安装它。
git clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim
然后只需要在.vimrc文件中写入要安装的插件然后在vim中运行Vundle的插件安装命令就可以自动下载安装指定的插件了。 更详细的使用方法可参考Vundle的文档。
MRU最近打开的文件¶
MRU的功能是从底部弹出一个最近打开的插件列表,其默认启动命令是:MRU,为了使用方便我将其设为mr。
nerdtree文件目录树¶
nerdtree是一个用于显示目录树的工具默认启动方式是:NERDtree,好难打的样子,所以我把它设成了nt。
关于这个插件有一个非常实用的设置是它可以忽略指定类型的文件,例如我们希望将所有的pyc或者其他没用的文件从目录树中过滤调的时候就可以使用它的这个功能,就像这样
let NERDTreeIgnore=['\.pyc$', '\~$']
它在github上的readme比较渣,没有介绍什么具体的用法和功能,我这里列出一些我用过的,还有一些大家可以通过:help Nerdtree查看。
- o.......打开文件并将焦点移动到打开的文件或展开当前文件夹
- Enter...跟o一样
- go......跟o一样,但将焦点留在NerdTree
- t.......在新tab中打开文件
- T.......同t,但保留焦点
- i.......在一个新的 split window中打开文件
- gi......同i,保留焦点
- s.......在新的 vsplit 窗口打开文件
- gs......同s保留焦点
- O.......递归打开当前文件夹
- x.......关闭当前文件夹的父文件夹
- X.......递归关闭当前文件夹
- P.......跳到根目录
- p.......跳到当前目录的父目录
- q.......退出NerdTree
CtrlP模糊搜索文件¶
CtrlP是一个用于模糊搜索文件的插件,其文档比较健全看看它的readme就能学会其用法,而且其默认启动快捷键就是Ctrl+p。
其跟NerdTree一样,也可以在split(Ctrl+s)和vsplit(Ctrl+v)窗口以及新tab(Ctrl+t)打开文件。
还有一个使用的设置就是忽略指定类型文件,像这样
let g:ctrlp_custom_ignore = {
\'file' : '\v\.(pyc|html\.py)$',
\}
ag和CtrlSF¶
ag是一个linux下非常好用的代码搜索工具(代码在github上需要手动安装),它可以快速搜索你的代码内容。vim的ag插件允许我们在vim中使用ag命令搜索代码,CtrlSF插件跟ag插件的不同在于前者可以显示代码的上下文,显然是CtrlSF更为强大。
CtrlSF的默认命令就是:CtrlSF,然后输入要搜索的字符再敲回车。好难打,好难用,所以我设置了下面的快捷键:
nmap <C-S>f :CtrlSF
nmap <C-S>o :CtrlSFOpen<CR>
nmap ss :CtrlSF <C-R><C-W><CR>
vnoremap ss y:CtrlSF <C-R>"<CR>
- Ctrl+s+f................适用于normal模式,就跟:CtrlSF一样
- Ctrl+s+o................适用于normal模式,打开搜索结果的窗口
- ss......................适用于normal模式,搜索当前光标所在的单词
- ss......................适用于visual模式,搜索当前选中的文字
tpope/vim-commentary 批量注释¶
这货可以批量注释代码,就像eclipse的Ctrl+j一样。当然你以可以使用选中再批量插入的方式开实现批量注释,但你需要按5个键(Ctrl,v,Shift,I,Est)而commentry只需三个键就可以了。
首先,我们设个快捷键以及将python的注释符设为#
vnoremap <Backspace> :Commentary <CR>
autocmd FileType python set commentstring=#\ %s
这样在可视模式选中要注释的内容后可以按退格键批量注释,再次选中按退格键就解除注释。
Syntastic语法检查¶
该插件的功能是检查和标记语法错误及不规范的问题,在我们的项目下
supertab,补全插件¶
vim-coffee-script,CoffeeScript语法高亮¶
mako.vim,mako语法高亮¶
vim-mercenary 支持hg blame和diff¶
vim-colors-solarized 漂亮的颜色主题¶
luochen1990/rainbow 彩虹括号,匹配的括号显示为同一颜色¶
godlygeek/tabular 自动对齐¶
hynek/vim-python-pep8-indent python自动缩进¶
indentLine垂直缩进对齐线¶
MatchTag高亮显示匹配的html标签¶
移动¶
- :[n] 移动光标当第n行。
- H,M,L 分别移动光标到当前屏幕首行,中间行和尾行。
- Ctrl+f和Ctrl+b向下和向上翻页,相当于pageup和pagedown。
- h,j,k,l向左下上右移动一个字符。
- f和F加字符,将光标移动到下一个或上一个该字符的位置,例如fa会将光标移动到下一个a的位置。
- m设定标记,`跳转到指定标记。例如可以用ma在某行设定标记,再使用`a跳转到改行。
- shift+左右 光标移至上/下一个单词(以空格/标点区分单词)词首。
- w 光标移动到下一个单词处
- b 光标移动到上一个单词处
- ^ 光标移动到行首
- $ 光标移动到行尾
插入¶
- a和i分别在当前字符前和后插入。
- A和I分别在当前行尾和行首插入。
- 批量插入。首先在可视模式下选中要插入的行,然后按I可在选中处之前批量插入字符
复制、粘贴、替换和删除¶
- r可以替换当前字符。
- yy和dd可以分别复制和剪切当前行。
- y2y和d2d可以分别复制和剪切当前行开始的2行。
- :3,8y和:3,8d可以分别复制和剪切第3到第8行。
- yw和dw可以分别复制和剪切光标所在的单词。
- d(可视模式) 删除当前所选
- dd 删除多行并存在剪贴板中(剪切)
- y 复制当前所选
- p 粘贴
分屏相关¶
- :vsp和:sp分别竖着和横着分割当前窗口。
- Ctrl + v和Ctrl + s也可以竖向和横向分屏。
- Ctrl + w + 箭头键(hjkl)在不同窗口键移动。
- Ctrl + = 将所有的窗口大小调成相同大。
查找和替换¶
- / + 要搜索的内容搜索。
- n和N跳到下一个或上一个搜索结果。
- # 搜索当前光标所在的单词。
折叠代码¶
- zc,zC,zo,zO折叠或打开折叠当前行的代码,其中大写Z和O表示折叠或打开折叠所有层。
- zn,zm折叠或打开折叠当前文件的所有代码。
定制的快捷键¶
- F12..................运行python文件或使用zencode补全html
- F11..................格式化代码
- F5,F6,F7,F8..........调整窗口大小
- Ctrl+s+f.............使用ag搜索
- Ctrl+s+o.............打开ag搜索结果
- ss...................使用ag搜索光标所在的单词
- ss(可视模式).........搜索选中的单词
- Backspace(可视模式)..注释/解除注释代码
- nt...................打开NerdTree
- mr...................打开MRU
- tl...................打开taglist
- bn...................打开下一个buffer
- bp...................打开上一个buffer
其他¶
- u和CTRL+r分别是undo和redo的功能。
- :set nu和:set nonu分别为显示和不显示行号。
- Shift + < 或 >分表表示向左或向右缩进一层,也可以选中后批量缩进。
- n + Shift + < 或 >可批量缩进n层。
- i insert 输入
- v 行选中
- ctrl+v 列选中
- :q 未修改退出
- :q! 强制不保存退出
- :x / :wq 保存并退出
- J 合并多行
- shift+上下键 翻页
- :set paste 进入粘贴模式
- :%s/target/something/g 替换全部 target 字段
非正常退出vim后恢复文件 & deltmp
实例教程 :
实例讲解¶
下面是coffee/SSO/auth.coffee的部分代码:
modal = (html, color, id, callback)->
$.modal(
html
{
dimmerClassName : 'form '+color
}
id
callback
)
$.SSO.auth = {
password_set_mail: (mail)->
self = modal(
__inline("/html/coffee/SSO/password_set_mail.html")
"purple"
"ssoAuthPasswordSetMail"
(elem)->
error_tip = $.error_tip(elem)
m = {
o:{
mail
}
submit : ->
error={}
if m.o.mail.indexOf("@") <= 0
error.mail = "请输入有效的邮箱地址"
if not error_tip.set error
AV.User.requestPasswordReset( m.o.mail, {
success: ->
href="http://"+m.o.mail.split("@")[1]
$.modal_alert """<h1><p><span style="padding-right:30px;">重置密码邮件已发送。</span><a target="_blank" href="#{href}">点此查看</a></p><p>没有收到?<a class="resend" style="padding-left:30px;cursor:wait;" href="javascript:void(0)">点此重新发送<span class="timer"></span></a></p></h1>""", {
onApprove:->
location.href="/"
onShow:->
resend = $(@).find(".resend")
timer = resend.find(".timer")
run = ->
c = 60
counter =->
if c == 0
clock = ""
resend.click send
resend.css {cursor:"pointer",color:""}
else
c-=1
clock = "(#{c})"
setTimeout(counter,1000)
timer.text clock
counter()
resend.css {color:'#444'}
send = ->
AV.User.requestPasswordReset(m.o.mail, {})
resend.unbind 'click'
run()
run()
}
error: (_error) ->
if _error.code == 205
error.mail = "该账号不存在"
else
error.mail = _error.message
error_tip.set error
})
false
}
)
}
其中$.SSO.auth.password_set_mail是实现发送重置密码邮件的方法
该方法中调用了modal()函数,modal()函数在文件的开始定义,用于显示弹出窗。该调用分别传了__inline(“/html/coffee/SSO/password_set_mail.html”),”purple”,”ssoAuthPasswordSetMail”和一个回调函数这四个参数。第一个参数是个内嵌的html,用了fis的写法;第二个参数是一个class名的一部分;第三个参数是View的id名;最后的回调函数是该方法的主体。m对象作为avalon的View方法的第二个参数传进。m中包括对象o和方法submit,对象o即为View中的变量,用于avalon变量绑定,submit()作为提交函数定义。submit()中的AV.user.requestPasswordReset函数用于LeanCloud向用户的Email地址发送重置密码邮件,它接收一个email地址字符串,一个包含成功和错误回调函数的对象。发送成功后,success方法执行,我们用$.modal_alert来提示发送成功,弹出框里我们可以点击链接查看邮箱网站,也可以点击链接重新发送重置密码邮件。重发邮件每隔1分钟可点击一次,该部分效果写在onshow方法里。如果发送邮件失败,error方法执行,接收参数_error(加下划线用于区分error,error用于定义错误提示对象,在一定的情况下显示一定的错误信息。),然后根据错误提示码显示出错提示信息,其中$.error_tip()用于提示出错。
附录:
文档写法¶
开发服务器上,文档的默认路径是:
~/798/docs/source
写完之后,在:
~/798/docs/source
运行:
make html
可以生成html, 访问 798-docs.798.space 可以浏览你新生成的文档
手工配置开发环境¶
生成配置文件¶
首先创建主配置文件:
cp 798/cli/docker/config.example.py 798/cli/docker/config.py
修改 config.py 中的 HOST , 然后生成nginx和fis(pure)的配置文件
/798/cli/docker $ python make_config.py
这个脚本会输出生成的配置文件的路径。
然后打开nginx的配置文件:
sudo vi /etc/nginx/nginx.conf
在http段的靠前位置加入:
include /home/web/798/build/nginx.conf
其中,include后面的路径应为你实际生成nginx配置文件的路径。
然后重启nginx
sudo /etc/init.d/nginx restart
程序员知识点考评大纲¶
常用工具¶
Gentoo¶
- emerge –autounmask-write 然后 etc-update 然后 -3
- emerge =xxx-版本号
自定义的命令¶
- dirreplace
- replace_line.py
- deltmp
高级篇¶
- dstat
- dirreplace
- replace_line.py
tmux¶
- Ctrl+B
xshell¶
vim¶
- F12
- MR
- 批量注释
- = 排版
- vsp
- 替换
- 替换选中部分
版本控制¶
- hg
- blame
- log + -l
- revert -r
- fetch
- st
- ignore
- diff
- grep
- bisect 定位BUG出现的版本
- serve
- resolve + -l + -m
自定义小工具 :
./hg_close_branch ./hg_update_branch
前端¶
HTML¶
label for属性
绑定表单元素id,实现点击label选中相应radio或checkbox
链接都必须写上href属性, 空链接请写成:
<a href="javascript:void(0)"></a>
反复出现的按钮图标用 a标签 配合 css设置背景图 来实现,不要反复的写img标签(减少代码的冗余度)
semantic-ui.com
CSS¶
- 模块分级
- 全局级
- 模块级
- 页面级
分栏布局
例如左宽665px,父容器宽1000px,在layout.css中定义:
.R665{float: left; margin-left: 688px; width:312px;} .L665{float: left; width: 665px; margin-left: -100%;}
参考:
绝对底部
清除浮动
子选择器
利用父级元素id进行选择
CSS盒模型
垂直居中
如何制作三角
- :first-child 和 :last-child
- 案例 : 圆圈 , padding
如果内容可变,就不要设置高度
- 写完页面依次检查
对齐
- 字体
- 大小
- 粗细
- 颜色
留白
- 42web
- HTML中如何引用图片
图片上传至七牛,使用外链地址 * CSS中如何引用图片:
background:url(/css/_img/xxx)
- 不要引用站外的图片
checkbox 和 radio 的 样式
不要用空格做间距
我们常用的CSS样式¶
- 按钮
- 功能
- 强调
设计¶
- 对齐
- 留白的一致性
- 粗体
- 字号
javascript¶
获取时间戳:
(new Date).getTime()
在js中取得当前用户:
$.current_user
$$
例如调用弹窗(可有多个参数):
$$('SITE/auth/login')
require
$.require
- $.dialog
- 需要登录调用$.login_dialog(参考submit_project.coffee)
$.errtip
err = {} if xxx: err.xxx = "xx" if xx : err.xx ="xx" if not errtip.set err: xxxxx
jQuery¶
- $.extend([deep],target,object)
jQuery 自定义扩展¶
$.timeago
接受一个时间戳作为参数,返回距离当前时间描述
$.isotime
- $.getJSON1
- jsonp 跨域调用
$.postJSON1
$.html 模版
参考egg_new.coffee
jQuery UI¶
- Accordion
- Datepicker
- Tagit
CoffeeScript¶
avalon¶
Firebug¶
- 控制台面板中,点击“保持”按钮,页面重新载入时不清空面板
Photoshop¶
工具¶
- Chrome插件
- PerfectPixel
- Page Ruler
- Windows
- Color Picker
后端¶
python¶
- 闭包
- 正则表达式
- collections - defaultdict
- itertools
- enum - IntEnum
- enumerate
- time.mktime(time.strptime(“2007-03-04 21:08:12”, “%Y-%m-%d %H:%M:%S”))
- dateparser
- python 的 新式类与旧式类 , 以及super的意义
mongodb¶
- find
- limit
- skip
- sort
delete
remove(删除条件)
- save
- 填充默认值
upsert
MySQL¶
- get
- mc_get
- mc_get_list
Kv¶
- id_by_value
- get
- mc_get
nginx¶
mako¶
- this 比如 this.get_argument(‘q’)
- ${json_encode(xxx)|n}
redis¶
- hset
- set
- zset
- list
- expire
mongo¶
- 时间用int保存
- mongo默认值需要是一个生成函数 * pyhton常见的默认值陷阱,以create_time=time()为例
gearman¶
supervisor¶
- 线上服务器如何看异常
tornado¶
- 通过编写 Base View简化业务开发
42web¶
- 新建url页面
- render
- css,js的引用
- merge.conf
- 新建css,js,修改merge.conf需要重启开发服务器
- View的类型
- 分页
- 在页面取得当前用户
- 搜索
- 自动补全
- gearman 异步调用
- JsOb
- rendermail 发送邮件
- redis key的定义 , R.
- model 中 使用绝对路径import以防止redis提示key重复定义
- import _env
- 配置文件 的 定义 与 自适应
- make.py 生成配置文件
开发习惯¶
修改函数接口后, 用ag查找并修改些调用过的地方
函数命名规则 :名词在前动词在后 , 常用命名如下
- user_new 新建
- user_rm 删除
- user_dumps 返回一个包含各种相关数据的json对象
- user_id_list_by_com_id(limit, offset) 查询
- user_new 新建
- user_rm 删除
- user_dumps 返回一个包含各种相关数据的json对象
- user_id_list_by_com_id(limit, offset) 查询
- user_id_count_by_com_id
我们通常把user_id作为第一个参数
友情链接¶
项目规划¶
类似 weebly.com 的编辑器
相关链接¶
- 代码仓库
- 在线文档
- 聊天沟通工具 798.bearychat.com
- 微信公众号 798