zoukankan      html  css  js  c++  java
  • backbone库学习-View

    Backbone中的视图提供了一组处理DOM事件、和渲染模型(或集合)数据方法(在使用视图之前,你必须先导入jQuery或Zepto)

    视图类提供的方法非常简单,我们一般在backbone.View的基础上进行扩展。但即使是特别复杂的视图类,它也应该仅仅是做界面事件、和渲染逻辑相关的操作,数据管理应该交由Model和Collection来完成,而业务逻辑应该由其它的类完成。

    上述文字来自http://blog.csdn.net/eagle_110119/article/details/8842026

    backbone框架图:http://www.cnblogs.com/nuysoft/archive/2012/03/19/2404274.html

    1.1  定义和创建视图

    先看例子1.1-1:

    <div title="列表" style="color:red" id="list" class="listview"></div>  
    <script type="text/javascript">  
        var ListView = Backbone.View.extend({  
            el : '#list'  
        });  
        var listview = new ListView();  
    </script>  

    extend部分就不看,跟collection和model一样。

    var ListView = Backbone.View.extend({  
            el : '#list'  
        }); 

    将el绑定到ListView的原型上,通过ListView实例化的对象可以直接使用。

    下一段代码:

    var listview = new ListView();  

    看一下View的构造器:

    var View = Backbone.View = function(options) {
            this.cid = _.uniqueId('view');//生成关于视图的cid
            options || (options = {});
            _.extend(this, _.pick(options, viewOptions));//将自定义属性值绑定到实例上
            this._ensureElement();//调用_ensureElement方法
            this.initialize.apply(this, arguments);//调用init方法
            this.delegateEvents();//调用delegateEvents方法
        }

    先看一下underscore的pick方法

    _.pick = function(obj) {
            var copy = {};
            var keys = concat.apply(ArrayProto, slice.call(arguments, 1));//转成数组
            each(keys, function(key) {
                if (key in obj) copy[key] = obj[key];//为copy绑定自定义的属性值,前提是属性名是viewOptions中的
            });
            return copy;
        }

    将自定义的信息绑定到this实例。

    这里例子略显简单,导致源码很多部分不能覆盖执行,我们给例子添加点东西,再进入_ensureElement方法,看例子1.1-2

    <script type="text/javascript">  
        var ListView = Backbone.View.extend({  
            tagName : 'div',  
            className : 'listview',  
            id : 'list',  
            attributes : {  
                title : '列表',  
                style : 'color:red'  
            },  
            render : function() {  
                this.el.innerHTML = 'Hello World!';  
                document.body.appendChild(this.el);  
            }  
        });  
        var listview = new ListView();  
        listview.render();  
    </script>

    其中

    {  
            tagName : 'div',  
            className : 'listview',  
            id : 'list',  
            attributes : {  
                title : '列表',  
                style : 'color:red'  
            }  

    将会被加到View的实例中。看一下_ensureElement方法

    _ensureElement: function() {
                if (!this.el) {//没有关联页面的标签,一般是创建在页面显示
                    var attrs = _.extend({}, _.result(this, 'attributes'));//将attributes的信息绑定到attrs上
                    if (this.id) attrs.id = _.result(this, 'id');//将id传给attrs。
                    if (this.className) attrs['class'] = _.result(this, 'className');//将className传给attrs
                    //至此attrs获取基本的创建标签的属性
                    var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs);//调用第三方选择器生成标签,并注入我们自定义的属性信息,但这里还没有将该对象插入HTML页面
                    this.setElement($el, false);
                } else {//声明的时候我们定义了el
                    this.setElement(_.result(this, 'el'), false);//调用进入setElement方法
                }
            }

    backbone在View这块,依赖一些第三方插件,比如jQuery,Zepto等。所以使用的时候,先将它们加载进来。进入setElement方法。

    setElement: function(element, delegate) {
                if (this.$el) this.undelegateEvents();//初始化时,不执行
                this.$el = element instanceof Backbone.$ ? element : Backbone.$(element);
                //这里给定义,调用第三方的选择器生成dom对象(并非原生dom对象,这里我们引用的是jQuery,
                // 就姑且认为是jQuery对象),将我们之前生成jQuery对象传给实例的$el属性
                this.el = this.$el[0];//获得原生对象
                if (delegate !== false) this.delegateEvents();
                return this;
            }

    这个例子中,我们没有绑定任何事件。接着我们执行构造器中的最后一个方法delegateEvents

    if (!(events || (events = _.result(this, 'events')))) return this;//没有代理事件,返回

    因为没有绑定事件,这里就直接返回了。

    例子中使用listview.render(),看一下render()

    render: function() { //这个方法默认返回实例,使用时,可以将其重载
                return this;
            }

    声明View类时,我们已经自定义了render,这将会重载系统中原有的render,那我们来看一下自定义的render

    render : function() {
                this.el.innerHTML = 'Hello World!';
                document.body.appendChild(this.el);
            }

    this.el是生成jQuery对象转成的原生对象。在其中添加"Hello World",最后再将它插入页面,最后显示在页面上

    这里我们总结下各个属性的作用,很简单

    tagName标识新标签的名称(如果没有设置,则默认是div)

    className对应标签的class样式

    id对应标签的id属性

    1.2   处理DOM事件 

    可以想一下,以往我们是怎么用jQuery绑定事件的

    <p>  
        <input type="button" value="Create" id="create" />  
        <input type="button" value="Read" id="read" />  
        <input type="button" value="Update" id="update" />  
        <input type="button" value="Delete" id="delete" />  
    </p>  
    <script type="text/javascript">  
        function createData() {  
            // todo  
        }  
        function readData() {  
            // todo  
        }  
        function updateData() {  
            // todo  
        }  
        function deleteData() {  
            // todo  
        }  
      
        $('#create').on('click', createData);  
        $('#read').on('click', readData);  
        $('#update').on('click', updateData);  
        $('#delete').on('click', deleteData);  
    </script> 

    那我们看一下backbone的view是如何处理dom事件的,先上个例子1.2-1

    <p id="view">  
        <input type="button" value="Create" id="create" />  
        <input type="button" value="Read" id="read" />  
        <input type="button" value="Update" id="update" />  
        <input type="button" value="Delete" id="delete" />  
    </p>  
    <script type="text/javascript">  
        var MyView = Backbone.View.extend({  
            el : '#view',  
            events : {  
                'click #create' : 'createData',  
                'click #read' : 'readData',  
                'click #update' : 'updateData',  
                'click #delete' : 'deleteData'  
            },  
            createData : function() {  
                console.log('create');
            },  
            readData : function() {  
                console.log('read');
            },  
            updateData : function() {  
                console.log('update');
            },  
            deleteData : function() {  
                console.log('delete');
            }  
        });  
        var view = new MyView();  
    </script>

    看一下View类的声明,将createDate,readData,updateData,deleteData加到了MyView的原型上。这里我们主要看一下构造器上的delegateEvents方法

    delegateEvents: function(events) {
                if (!(events || (events = _.result(this, 'events')))) return this;//没有代理事件,返回
                this.undelegateEvents();//进入undelegateEvents方法,去除代理绑定
                for (var key in events) {
                    var method = events[key];//获取自定义的方法名
                    if (!_.isFunction(method)) method = this[events[key]];
                    if (!method) continue;
                    var match = key.match(delegateEventSplitter);//将类似click #create分离获取
                    var eventName = match[1], selector = match[2];//获取触发事件动作名,获取选择器
                    method = _.bind(method, this);//绑定事件,将事件绑定到View的实例上
                    eventName += '.delegateEvents' + this.cid;
                    if (selector === '') {//监听事件
                        this.$el.on(eventName, method);//jQuery的原生on事件,低版本的jQuery注意
                    } else {
                        this.$el.on(eventName, selector, method);
                    }
                }
                return this;
            }

    看一下undelegateEvents方法

    undelegateEvents: function() {
                this.$el.off('.delegateEvents' + this.cid);//删除绑定事件
                return this;
            }

    创建事件之前,先将以前可能存在的事件都删除掉。这里最后绑定事件的方法其实是jQuery的on方法,所以大家在引用第三方插件的时候,注意插件的版本。

    另外就是这里的绑定事件都是绑定的都是p标签,所以使用事件委任,这写button在remove掉之后,再添加进来,依旧有事件。满足动态删减dom的情况。

    内容不多,时间刚好,以上是我的一点读码体会,如有错误,请指出,大家共通学习。 

  • 相关阅读:
    Veritca 简单安装配置过程
    本地环回,引发的血案
    Centos8的网络管理
    在做自动化测试之前你需要知道的什么是自动化测?
    APP移动测试用例总结
    Appium做Android功能自动化测试
    Selenium Webdriver模拟鼠标键盘操作
    线程锁 创建两个线程,其中一个输出152,另外一个输出AZ。要求使用线程锁,使输出为: 12A 34B 56C 78D Y
    Win10安装MongoDb Y
    linux下Docker安装 Y
  • 原文地址:https://www.cnblogs.com/wumadi/p/3321003.html
Copyright © 2011-2022 走看看