玩转前端总结
by 程序范儿 2014-01-05 22:15
适合读者
前端工程师,想做小站的程序员
我的需求
以前写的几个博客都荒废了,最近想重新拾荒,开始考虑在WordPress上搭建,但这样一来就没有了玩程序的感觉,后来又看上了GitHub Pages这个服务,因为朋友们在上面玩的都不错,这里也推荐一个博客,如果你对IOS感兴趣可以看看lzyy.github.com,这个博客就是基于GitHub Pages
的,如果你想了解这种博客是怎样维护的,你可以看看他写的文章使用github作为博客引擎,当然如果你很懒也可以直接fork他的项目https://github.com/lzyy/lzyy.github.com,在这个基础上直接改出你的博客。
Github自己也说的很清楚,这不是他们自己的技术,而是整合了Jekyll,有兴趣的同学可以自己看看。
最终我没有采纳这种形式,于是着手开始自己写,这样一个小东西远没有我以前写的任何系统高端上档次,能让我感觉到的就是生活比较轻松,状态比较自然,也不用考虑那么多性能和带宽方面的问题。
Bootstrap
现在人们的阅读都在从PC上向移动端转移,像博客这样的系统,最好能够在不同尺寸的屏幕上都有良好的阅读体验,于是能想到的就是Bootstrap,它能够实现自适应的版面和布局,如果你能够按照它的方式编写HTML和CSS,在不同的终端下都有很好的体验效果。
有兴趣的同学可以看一下这几个官方的例子:
http://v3.bootcss.com/examples/grid/
http://v3.bootcss.com/examples/jumbotron/
改变一下浏览器的尺寸看看,效果应该都不错,当然这里也推荐一个小插件Window Resizer,在Chrome和Firefox下都有,这个插件可以很方便的改变尺寸,让你看到效果:
Bootstrap官方网站其实就是一个很好的宣传:
网页尺寸
手机尺寸
右上角那个是可以点开的,上面一排仅仅是被折叠了而已。
最近也为新公司开发了一套后台,以前写后天界面就要折腾半天,终于找到了一套基于Bootstrap的后台模板,可以说算是比较养眼的,而且套上去也不费力,名字叫Matrix Admin,我截了两张图,一张是正常浏览器尺寸下的,另外一张是屏幕缩小以后的:
网页尺寸
手机尺寸
引用bootstrap的方法也很简单,只需要引入三个文件:
<link rel="stylesheet" href="http://cdn.bootcss.com/twitter-bootstrap/3.0.3/css/bootstrap.min.css"> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="http://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script> <script src="http://cdn.bootcss.com/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
如果想用Bootstrap的js插件,JQuery要同时被引入进来。
AngularJS
选定了Bootstrap作为CSS的首选,接下来要选择JS框架,选择AngularJS有那么几个原因:
- 他能很干净的实现JS的MVC,几乎在HTML文件里不会再看到任何JS代码,都被封装到了不同的Controller里,这和一般的后端框架使用起来是一样的。
- 他的Template比我以前用的其它JS模板都要强悍,普通的JS模板只能实现变量的替换,稍微强一点的可以实现一些控制语句,如IF LOOP等,部分模板可以实现对时间等特殊变量的重新格式化,我能想到的需求它都可以满足。
- 以前写JS为了让数据和展示同步,例如用户的登录信息等,都需要自己来处理,在AngularJS这是它的标准能力,你渲染完模板以后,如果你的数据被重新加载,那么模板会自动重新渲染。
- 它可以很友好的让不同JS之间共享数据或服务,例如我们需要维护用户的Session信息,这些都可以轻松的搞定。
- 他可以把HTML上的事件和Controller里的方法直接关联起来,这样代码会更干净。
例如程序范儿的JS结构是这样的:
/js /js/app.js /js/app /js/app/controller /js/app/controller/articlelist.js /js/app/controller/comment.js /js/app/controller/login.js /js/app/controller/site.js /js/app/service.js
我在渲染页面当中文章列表的时候,我就用上了模板:
<div ng-controller="CArticleList" ng-init="init()"> <div ng-repeat="item in items"> <div><h3><a href="/article?id="></a></h3></div> <p>by <a href="/">程序范儿</a> <mydate>0NaN-NaN-NaN NaN:NaN</mydate></p> <div ng-bind-html="item.summary"></div> </div> </div>
这里的CArticleList
就是/js/app/controller/articlelist.js
文件对应的类,这里的工作就是把绑定在CArticleList上文章列表数据渲染出来,贴一下实现:
myApp.controller('CArticleList', function($scope, session, $http, $sce) { $scope.pos = 0; $scope.len = 10; $scope.items = []; $scope.init = function() { $scope.items = []; $scope.list(); } $scope.actionMore = function() { $scope.list(); } $scope.list = function() { $http.get('/api/article/list?&pos=' + $scope.pos + '&len=' + $scope.len).success(function(res) { if(res.code == 0) { items = res.data.items; for(i in items) { items[i]['summary'] = $sce.trustAsHtml(items[i]['summary']); $scope.items.push(items[i]); } $scope.pos = res.data.pos; } }); } });
所以AJAX被封装在Controller里和HTML分离的很干净,如果你改变了$scope.items
的内容,那么HTML这一端会自动重新渲染,不需要程序员费心。
你可以看到了程序范儿
最早的设计是有用户登录这个环节的,后来我给雪藏了,因为这里只有文章也没有别的什么值得大家筑巢的。
但是我也贴一段旧代码,体验一下如何设计登录和维护Session信息,先贴Session设计/js/app/service.js
:
myApp.factory('session', function($http) { var data = null; $http.post('/do/session').success(function(res) { if(res.code == 0) { data = res.data; } }); return { set:function(d) { $http.post('/do/session').success(function(res) { if(res.code == 0) { data = res.data; } }); }, get:function() { return data; }, clean:function() { $http.post('/do/logout').success(function(res) { if(res.code == 0) { data = null; } }); } }; });
代码也比较简洁,直接从接口里读取,Service是AngularJS当中一种可以用来共享数据的方法,我在/js/app/controller/site.js
里获取到了共享的session信息:
myApp.controller('CSite', function($scope, session) { $scope.session = session; $scope.pos = 0; $scope.len = 10; $scope.articles = []; $scope.getSession = function() { return session.get(); } $scope.actionLogout = function() { $scope.session.clean(); } $scope.actionAdd = function() { if($scope.session.get()==null) $scope.actionLogin(); } $scope.actionLogin = function() { if(!$scope.isLogin == false) { return; } $scope.dialogTemplatePath = "/login"; $('#g-dialog').modal(true); } });
接着我就可以在HTML里面去展示用户的登录状态:
<body ng-controller="CSite"> //...省了一千字 <ul ng-if="getSession()"> <li> <a href="#" data-toggle="dropdown"><b></b></a> <ul> <li></li> <li> <a href="#" ng-click="actionLogout();">退出</a> </li> </ul> </li> </ul> <ul ng-if="!getSession()"> <li> <a href="#" ng-click="actionLogin()">登录</a> </li> <li> <a href="#">注册</a> </li> </ul>
ng-if
是一个很不错的标记,只有当getSession()
返回数据的时候才会显示,如果没有回来数据就显示登录界面,当用户登录成功写入session信息/js/app/controller/login.js
:
myApp.controller('CLogin', function($scope, session) { $scope.session = session; $('#g-login-form').validate({ submitHandler: function(form) { $(form).ajaxSubmit({ dataType: "json", beforeSubmit: function() { }, success: function(res) { if(res.code == 0) { $scope.session.set(); $('#g-dialog').modal('hide'); } else { } } }); } }); });
所以相当于CLogin
和CSite
共享了session
服务。
Uglify
MVC化的JS写起来很方便,但AngularJS并没有解决引用问题,如果想在当前页面使用CSite
你首先要先引用它:
<script type="text/javascript" src="/js/libs/angularjs/1.2.7/angular.js"></script> <script type="text/javascript" src="/js/app/service.js"></script> <script type="text/javascript" src="/js/app/controller/site.js" ></script>
自从使用JQuery以后也知道min.js
后缀的意义,就是被压缩的JS,Uglify算是公认的比较理想的压缩工具。所以程序范儿
的引入的JS是:
<script type="text/javascript" src="/res/js/main.min.js?v=2" ></script>
JS被压缩了,所以很难看到刚才讲到的那些JS结构,这个压缩的JS包括了:
- JQuery
- Bootstrap
- AngularJS
- Other
Grunt
虽然Uglify
能很好的压缩JS,但平时开发的时候,如果你每写一句就要去编译一次哪也是很麻烦的,所以Grunt出现了,可以利用Grunt
的watch
功能,实现对JS
代码或者CSS
代码的监控,当代码被改变自动合并或者压缩代码。
平时工作的时候为了简单高效,虽然也是合并出main.min.js
但这个文件不是用Uglify
压缩的,而是采用grunt-contrib-concat
进行了合并,这样编译的速度会快很多,基本上这边保存,立即就能生成结果。
当我去发布正式版本的时候,我才会执行:
grunt uglify grunt cssmin
后面那个命令用来压缩css,前面那个是用来压缩js。
所以Grunt的另外一个好处是他可以实现更复杂的功能,可以全面照顾到CSS和JS。
开发的时候我只需要一个命令:
grunt watch
这个命令会一直观察我的文件改动情况,当我保存了代码,就会立即重新生成新的main.min.js
和main.min.css
文件。
Grunt虽然很智能,但配置起来还是需要点功夫,我贴一下我自己的Grunt配置:
module.exports = function (grunt) { var jsrc = [ '../lib/jquery/jquery-1.10.2.js', '../lib/jquery/**/*.js', '../lib/angular/angular.js', '../sass/javascripts/bootstrap/modal.js', '../sass/javascripts/bootstrap/dropdown.js', '../js/app.js', '../js/app/service.js', '../js/app/controller/**/*.js' ]; var csrc = [ 'stylesheets/main.css', '../lib/font-awesome/css/font-awesome.css' ]; var sasssrc = [ '../sass/sass/*.scss', '../sass/include/*.scss', ]; grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), compass: { dist: { options: { config: '../sass/config.rb' } } }, concat: { js: { src: jsrc, dest: '../../wwwroot/res/js/<%= pkg.name %>.min.js' }, css: { src: csrc, dest: '../../wwwroot/res/css/<%= pkg.name %>.min.css' } }, cssmin: { css: { src: csrc, dest: '../../wwwroot/res/css/<%= pkg.name %>.min.css' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n', mangle: false }, build: { src: jsrc, dest: '../../wwwroot/res/js/<%= pkg.name %>.min.js' } }, watch: { //js: { files: jsrc, tasks: [ 'uglify' ,'compass'] }, js: { files: jsrc, tasks: ['concat'],}, css: { files: sasssrc, tasks: ['compass', 'concat'] }, livereload:{ options:{ livereload:true }, files:[ '../sass/sass/*.scss', '../sass/include/*.scss', '../js/app/**/*.js', '../../layout/**/*.php', '../lib/jquery/**/*.js', ] } } }); // load plugins grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-compass'); grunt.loadNpmTasks('grunt-contrib-cssmin'); // register at least this one task grunt.registerTask('default', [ 'watch' ]); grunt.registerTask('css', [ 'compass', 'concat' ]); };
这里的亮点是这几行配置:
livereload:{ options:{ livereload:true }, files:[ '../sass/sass/*.scss', '../sass/include/*.scss', '../js/app/**/*.js', '../../layout/**/*.php', '../lib/jquery/**/*.js', ] }
LiveReload
程序员一般有两个屏幕,如果你还没有两个显示器,希望你赶快让公司帮你改善一下环境,作为程序员你太可怜了。
左边用来编写代码,右边用来放浏览器查看结果,以前我们需要手工去刷新浏览器,现在用LiveReload(http://livereload.com/),你可以监控一些文件,当他们改变的时候让你的浏览器自动刷新。
所以我的流程就变成了写JS或者CSS
/保存
/concat合并
/LiveReload自动刷新
。
这里另外一个亮点是这一行:
'../../layout/**/*.php'
当我的PHP模板改变了以后,也会自动刷新我右边的浏览器,这样的效果的确是不错的。
Sass & Compass
虽然Bootstrap可以满足我大部分的样式需求,但你肯定还有自己的需要,这时候你需要从Less和Sass当中选一种方式,我选了Sass
,这也意味着我同时选择了Compass,这两个之间的关系就是一对儿好基友的关系,就像Ruby on Rails,Compass
是Sass
的加强。
如果你还不了解它们,我推荐你读几篇文章,都是一个人写的,这个人的博客你也可以多留意:
这人的文章写的干净简洁,很不错。
Sass可以让你写CSS更有逻辑性,Compass可以帮你解决很多CSS的兼容性问题,例如圆角。
cssmin
这个没什么太多可讲的,就是压缩css用的,要结合grunt
用。
Fontawesome
我以前不知道有这么个东西,当我去用Matrix Admin
的时候我才知道,这个东西很神奇,把我们常用的ICON变成了特殊的字体,这样就不用为去找那些常用ICON烦恼了,以前都是去easyicon找ICON。
Fontawesome一共369个ICON,使用方法很简单:
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"> <i></i>RSS
这就是程序范儿
右上角那个RSS的图标,不是美工的设计,是一个特殊的字体,可以改变大小、颜色也可以被鼠标选中。
我现在用的这个Markdown编辑器也支持Fontawesome
,这个编辑器叫StackEdit,支持向各种云存储同步,这样写内容不会丢失,但StackEdit
仅仅是Chrome浏览器的一个插件,用的时候也不用到处去找。
RequireJS
在使用Grunt之前,也尝试了一下RequireJS,它可以帮我动态的加载JS,但一定要符合AMD规范,这种方法也不错,一样可以让AngularJS
跑起来,不过配置的东西太多,按照同事的说话,CSS和JSS全部合并起来也就是一张图片的size何必计较太多呢,于是改成了Grunt。
--EOF--
若无特别说明,本站文章均为原创,转载请保留链接,谢谢