软件工程3——第三章 代码阅读

Popush代码阅读报告——View部分

聂中天2014/11/06

真正集体开发之前,先要弄清楚如何编写。Popush集成了许多框架和设计模式,需要参照其官方文档和Popush的具体实现对比分析,才能合理高效地扩展Popush的功能。

         这一篇博文就Popush的主要前端实现机制作一个整理总结,并对部分细节测试分析。针对的文件为Popush目录下Static文件夹里的文件。

        

         前端使用了Backbonejs的框架,MVC体系结构。Model和Collection描述file和user数据,这里就不展开了。View通过js/view文件夹下的javascript描述页面内的响应逻辑。最后router.js反应页面跳转。另外浏览器端用Socket.io实现与服务器的信息交流。

         大体上这样。然后是细节。

 

1.    Router.js

因为Backbone采用的是单页面式的网页形式,用一个网页中元素的出现、消失等动作来表现页面跳转,Router.js就是处理跳转逻辑。相当于Controller的角色。

var app = app || {}; 

(function() {
  var Page = app.Page = function(opts) {
    this.shown = false;
    _.extend(this, opts);
    return this;
  };
  Page.prototype.show = function() { this.el.show(); };
  Page.prototype.hide = function() { this.el.hide(); };
  Page.prototype.fadeIn = function() { this.el.fadeIn('fast'); };
  Page.prototype.fadeOut = function() { this.el.fadeOut('fast'); };

首先获取全局变量app。下面的函数定义了Page这一对象,称之页面元素更合适,是本文件的基本数据类型。它的shown默认值是false,定义其显示、消失、淡入、淡出方法的默认函数,是该对象的el元素执行jQuery自带的操作。

  var PageRouter = Backbone.Router.extend({
    routes: {
      'login': function() { this.analy('login'); },
      'register': function() { this.analy('register'); },
      'index/*filepath': function(arg1) { this.analy('index', arg1); },
      '/*filepath': function(arg1) { this.analy('index', arg1); },
      'edit/': function(arg1) { this.analy('edit'); },
    },

定义了“五个页面”,之所以打引号是因为这些页面都只是在单页面URL加上后缀而已。后缀名是这个对象的方法名,而第三四个*filepath可匹配参数。当网页前端(比如a标签)链接到“#index/file1/file2”的时候,会由router匹配到第三个路由项,*filepath可对应得到URL中的“fil1/file2”字符串,作为后面参数arg1,去执行响应函数,也就是跳转操作了。

第五个参数arg1是多余的。统一用下面定义的analy函数响应。

 pages: {
      login: new Page({
        el: '#login',
        depend: ['_head1', '_footer', '_ads'],
        logined: 0,
        force: true,
        show: function() {
          this.el.show();
          app.views.login.show();
        },
        hide: function() {
          this.el.find('#login-padding').slideDown();
          this.el.hide();
        },
      }),

      register: new Page({
        el: '#register',
        depend: ['_head1', '_footer', '_ads'],

         接下来的实现感觉有点绕,意思是先在pages属性里定义好了所有共四个页面。包括其需要保存的信息(如是否登陆)和显示隐藏的处理。force属性没看懂。

         analy函数很长。一上来先用routeLock锁上,没有执行完此函数不对页面跳转再做反应(虽然URL还是会变);一些判断检查;recurse函数递归把该页面显示需要加载的页面元素、子页面加入数组arr里,随后逐一显示出来。(里面有个坑爹的变量j,没有说明,似乎是用来描述当前页面状态的)。

最后实例化PageRouter对象到app.router。 在某个其他地方启动了Backbone.history。至此,路由完成。

 

2.     View 文件

这些文件统一以-view结尾,里面也是一个立即函数,即直接执行的程序,使用Backbone.View.extend定义了app的视图成员。

   

var app = app || {};
(function () {
    app.AccountView = Backbone.View.extend({
        el: '#nav-head',
        events: {
            'click #btn_changepassword': 'changepasswordopen',
            'click #btn_changeavatar': 'changeavataropen',
            'click .go-logout': 'logout',
        },
        initialize: function () {
            var that = this;

首先获取全局变量app,把所有页面都定义为它的属性。接下来代码全部包裹在一个即时函数中,‘use strict’表示是JavaScript的严格模式,这样在这一段函数中的所有代码会受到更严格的限制,否则抛出异常。部分view文件有,说明上一代编写者也没有很在乎。

	app.LoginView = Backbone.View.extend({
		el: '#login',
		events: {
			'keypress #login-inputName': 'loginOnEnter',
			'keypress #login-inputPassword': 'loginOnEnter',
			'click #login-submit': 'login'
		},
		login: function () {
			var name = $('#login-inputName').val(),
			in_pw = $('#login-inputPassword');
			var pass = in_pw.val();

         接下来,利用Backbone的View定义视图对象。这里app.LoginView就是一个前端的页面,已经在Router里面添加过链接了。再用View.extend函数定义动作。

该函数的参数是一个对象,其中el属性将index.html中的DOM元素和这个视图绑定,events属性定义了前端的事件响应,比如当id为’login-inputName’的输入框接收到按键输入时,会触发loginOnEnter的事件。View.extend的参数的方法就是响应事件的处理函数,比如login方法会响应“点击登陆”。

有的地方没有el,而是如下形式:

    app.SharerView = Backbone.View.extend({
        tagName: 'li',
        template: _.template($('#sharer-template').html()),
        events: {
            'click a': 'select'
        },
        initialize: function () {
            this.listenTo(this.model, 'change', this.render);
            this.listenTo(this.model, 'remove', this.remove);
            this.listenTo(this.model, 'destroy', this.remove);
        },

它会找到index中下面的模版代码,利用模版加上信息,动态创建Dom列表元素(li)。填充这个模版里头像(avatar)、姓名(name)等元素时需要用到model。

  <script type="text/template" id="sharer-template">
  <a href="#">
	<img src="<%= avatar %>" width="32" height="32" class="sharer-avatar userlistimg user-<%= name %>" />
	<%=name%>
	</a>
  </script>

这类视图的初始化中用了事件监听ListenTo,可以随时监听model,相当于数据部分的变动。

 

3.    Index.html

头尾是脚本、样式等等不谈,中间定义了整个网站所有的Dom节点。

说得更具体一点,包括了所有后台需要操作的静态标签,按钮,滑动框,交互元素。之后是需要弹出的区块,再后面是模版(比如文件列表)。

更具体不能了。就算我写了你也没兴趣读吧。

 

小结

 

         阿西,index太长了,view文件太多了,注释太少了,又写得匆忙,疏漏颇多,请看官见谅。

         APEC愉快!

        

         

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值