Backbone入門之視圖(Backbone.View)

<p><a >上一篇介紹了Backbone集合</a>,本篇將介紹Backbone視圖厅各。</p>

<p>Backbone視圖可以使用JavaScript模板队塘,根據(jù)模型數(shù)據(jù)的邏輯處理向用戶展示相應(yīng)的界面宜鸯×苄洌可以監(jiān)聽模型的change事件,并在回調(diào)函數(shù)綁定視圖的render()方法陌凳,就可以在不重繪整個頁面的情況下冯遂,更新視圖谒获。</p>

<h2>創(chuàng)建視圖</h2>

<p>可以通過擴(kuò)展Backbone.View對象創(chuàng)建一個視圖:</p>


    var app = app || {};
    app.MenuListView = Backbone.View.extend({
        tagName: 'ul',
        className: 'menu-list',
        template: function() {
            return _.template('<li><%= title %></li>');
        }, 
        render: function() {
            this.$el.html(this.template()({title: "Menu List"}));
            return this;
        },
        initialize: function() {
            this.render();
            $('body').append(this.$el);
        }
    });
    app.menulist = new app.MenuListView();
    console.log(app.menulist.el);
    console.log(app.menulist.$el);

<p>打印值如下:</p>

<p>app.menulist.el:</p>

<p>
app.menulist.el

</p>

<p>app.menulist.$el:</p>

<p>
app.menulist.$el

</p>

<h2>初始化</h2>

<p>如果視圖定義了initialize()初始化函數(shù),在創(chuàng)建視圖時赔硫,它將立即被調(diào)用盐肃。</p>

<h3>視圖與模型</h3>

<p>創(chuàng)建視圖時砸王,可以通過傳入model或collection屬性和值,將某一模型或集合直接注冊到視圖中:</p>


    var app = app || {};
    app.MenuModel = Backbone.Model.extend({
        defaults: {
            title: 'this is a menu',
            status: 'inactive'
        }
     });
     app.MenuCollection = Backbone.Collection.extend({
        model: app.MenuModel,
        initialize: function() {
            console.log('集合初始化成功');
        }
    });
    var menus = [
        {
            id: 1,
            name: '最近會話',
            status: 'active'
        },
        {
            id: 2,
            name: '通訊錄',
            status: 'inactive'
        }
    ]
    app.menus = new app.MenuCollection(menus);
    app.MenuListView = Backbone.View.extend({
        tagName: 'ul',
        className: 'menu-list',
        template: function() {
            return _.template('<li><%= title %></li>');
        }, 
        render: function() {
            this.$el.html(this.template()({title: "Menu List"}));
            return this;
        },
        initialize: function() {
            //console.log('視圖初始化');
            this.render();
            $('body').append(this.$el);
        }
    });
    app.menulist = new app.MenuListView({
        collection: app.menus
    });
    console.log(app.menulist.collection);

<p>打印如下:</p>

<p>
app.menulist.collection

</p>

<h2>視圖與DOM</h2>

<p>我們希望通過使用Backbone視圖生成頁面文檔,將頁面展示給用戶瘪菌,就必須將視圖與DOM關(guān)聯(lián)起來嘹朗,通過操作視圖改變DOM屹培。</p>

<ul>
<li><p>Backbone提供兩種方式關(guān)聯(lián)視圖和DOM:</p>

<ul>
<li><p>創(chuàng)建</p>

<p>創(chuàng)建視圖時創(chuàng)建一個新元素,然后將該元素插入至DOM壁顶。</p></li>
<li><p>引用</p>

<p>視圖直接引用頁面已經(jīng)存在的元素若专。</p></li>
</ul></li>
<li><p>創(chuàng)建</p>

<p>Backbone視圖創(chuàng)建元素時只需要使用tagName蝴猪、id、className屬性嚎莉。此Backbone視圖對象的el屬性是一個指向該元素的引用。</p>

<p><em>tagName默認(rèn)值為div赃额。</em></p>


    app.MenuListView = Backbone.View.extend({
        tagName: 'ul', //元素標(biāo)簽類型跳芳,必選飞盆,未設(shè)置時默認(rèn)為div
        className: 'menu-list', //元素class次乓,可選
        id: 'menus', //元素id票腰,可選
        initialize: function() {
            $('body').append(this.$el);
        }
    });
    app.menulist = new app.MenuListView();
    console.log(app.menulist.el);
    //logs: <ul id="menus" class="menu-list"></ul>

<p><em>注:此時Backbone視圖生成的元素并沒有插入到文檔DOM杏慰。</em></p></li>
<li><p>引用</p>

<p>可以為Backbone視圖對象傳入一個el屬性,來匹配頁面文檔已存在的元素鹃愤。</p>


    app.MenuListView = Backbone.View.extend({
        el: 'body', //值為CSS選擇器
        initialize: function() {
        }
    });
    app.menulist = new app.MenuListView();
    console.log(app.menulist.el);
    //logs: <body>...</body>

<p>我們也可以在創(chuàng)建視圖時软吐,為對象el屬性設(shè)置值:</p>


    app.menulist = new app.MenuListView({el: 'body'});

<p><em>el屬性值為CSS選擇器凹耙,Backbone視圖對象將根據(jù)此選擇器匹配頁面元素肖抱。</em></p></li>
</ul>

<h2>視圖屬性與方法</h2>

<p>要深入理解Backbone視圖异旧,必須理解視圖一些重要的屬性和方法。</p>

<ul>
<li><p>el</p>

<p>el是視圖的一個核心屬性拌屏,也是使用視圖對象時必然會用到的一個屬性术荤。</p>

<blockquote>
<p>el是DOM元素的一個引用瓣戚,所有視圖都有其el屬性。視圖可以通過使用el構(gòu)成它的元素內(nèi)容舱权,在觸發(fā)瀏覽器最少次數(shù)重排和重繪的情況下刚照,將所有內(nèi)容一次性插入文檔DOM无畔。</p>
</blockquote></li>
<li><p>$el吠冤、$()</p>

<p>對視圖和DOM操作拯辙,經(jīng)常要用到j(luò)Query函數(shù)涯保,Backbone通過為視圖定義$el屬性和$()函數(shù),為我們操作視圖和DOM提供了很多便利未荒。視圖的$el屬性等價于$(View.el)片排,$(selector)等價于$(View.el).find(selector)速侈。</p></li>
<li><p>setElement()</p>

<p>Backbone提供setElement()方法倚搬,支持將現(xiàn)有Backbone視圖應(yīng)用于不同的DOM元素比默,調(diào)用該方法將創(chuàng)建一個緩存$el引用,并且將視圖委托事件從舊元素移動到新元素乙各。</p>


    var MyView = Backbone.View.extend({
        events: {
            click: function(e) {
                console.log(myView.$el.html());
            }
        }
    });
    var btn1 = $('<button>button 1</button>');
    var btn2 = $('<button>button 2</button>');

    //視圖元素el是btn1
    var myView = new MyView({el: btn1});

    btn1.trigger('click');  //logs: button 1

    //視圖元素el指向btn2
    myView.setElement(btn2);

    btn1.trigger('click');
    btn2.trigger('click'); //logs: button 2
    console.log(myView.$el.html);// button 2

</li>
</ul>

<h2>渲染模板-render()</h2>

<p>render()函數(shù)是一個可選函數(shù),需要我們主動調(diào)用沛善,通常我們在里面實現(xiàn)根據(jù)模型屬性渲染視圖模板塞祈,生成HTML標(biāo)記议薪;然后使用el或$el屬性,將這些HTML標(biāo)記設(shè)置為視圖的el屬性所引用的 DOM元素的HTML內(nèi)容产捞。</p>


    app.MenuModel = Backbone.Model.extend({
        defaults: {
            title: 'this is a menu',
            status: 'inactive'
        }
       });
    app.MenuCollection = Backbone.Collection.extend({
        model: app.MenuModel,
        initialize: function() {
            console.log('集合初始化成功');
            this.on('reset', function(cols, options) {
                console.log('重置集合');
            }, this);
            this.on('add', function(model) {
                console.log('添加模型坯临,cid: ' + model.cid);
            });
             this.on('change', function(model) {
                console.log('模型屬性改變?yōu)? ' + model.get('name'), model);
            });
            this.on('change:name', function(model) {
                console.log('模型name屬性改變?yōu)? ' + model.get('name'));
            });
            this.on('remove', function(model) {
                console.log('移除模型: ' + model.cid);
            });
        }
    });
    var menus = [
        {
            id: 1,
            name: '最近會話',
            status: 'active'
        },
        {
            id: 2,
            name: '通訊錄',
            status: 'inactive'
        }
    ]
    app.menus = new app.MenuCollection(menus);
    app.MenuItemView = Backbone.View.extend({
        tagName: 'li',
        className: 'menu-item',
        template: function() {
            return _.template('<a title="<%= title %>"><%= name %></a>');
        },
        render: function() {
            this.$el.html(this.template()(this.model.toJSON()));
            return this;
        }
    }); 
    app.MenuListView = Backbone.View.extend({
        tagName: 'ul',
        className: 'menu-list',
        template: function() {
            return _.template('');
        }, 
        render: function() {
            //遍歷集合看靠,集合中每個模型對應(yīng)一個菜單項
            _.each(this.collection.models, function(model) {
                //為每個集合模型衷笋,創(chuàng)建一個新菜單項視圖實例
                var menuItemView = new app.MenuItemView({model: model});
                //在父視圖-菜單列表視圖中添加子菜單-菜單項視圖
                this.$el.append(menuItemView.render().el);
            }, this);
            console.log(this.el);
            return this;
        },
        initialize: function() {
            this.render();
            $('body').append(this.$el);
        }
    });
    app.menulistview = new app.MenuListView({
        collection: app.menus
    });

<p>控制臺打印值如下:


this.el

</p>

<p>頁面效果如圖:


頁面效果圖

</p>

<p><em>我們通常在render()函數(shù)底部返回this以開啟鏈?zhǔn)秸{(diào)用,該視圖可以在其他父視圖里被重用泊脐。</em></p>

<h2>Events對象</h2>

<p>Backbone提供events對象支持我們通過設(shè)置在el下的自定義CSS選擇器容客、事件類型和事件監(jiān)聽器,為DOM元素綁定事件缩挑。</p>


    app.MenuItemView = Backbone.View.extend({
        tagName: 'li',
        className: 'menu-item',
        events: {
            'click .menu': 'openMenu',
            'dblclick .menu': 'edit'
        },
        template: function() {
            return _.template('<a class="menu" title="<%= title %>"><%= name %></a>');
        },
        render: function() {
            this.$el.html(this.template()(this.model.toJSON()));
            return this;
        },
        initialize: function() {
            this.dbltimer = null;
        },
        openMenu: function(e) {
            if (this.dbltimer) {
                clearTimeout(this.dbltimer);
                this.dbltimer = null;
            }
            this.dbltimer = setTimeout(function(){ 
                console.log('opened');
            },300);
        },
        edit: function(e) {
            if (this.dbltimer) {
                clearTimeout(this.dbltimer);
                this.dbltimer = null;
            }
            console.log('edit');
        }
    }); 
    app.MenuListView = Backbone.View.extend({
        tagName: 'ul',
        className: 'menu-list',
        template: function() {
            return _.template('');
        }, 
        render: function() {
            _.each(this.collection.models, function(model) {
                var menuItemView = new app.MenuItemView({model: model});
                this.$el.append(menuItemView.render().el);
            }, this);
            // this.$el.html(this.template()({title: "Menu List"}));
            console.log(this.el);
            return this;
        },
        initialize: function() {
            this.render();
            $('body').append(this.$el);
        }
    });
    app.menulistview = new app.MenuListView({
        collection: app.menus
    });

<p><em>若沒有設(shè)置CSS選擇器,則默認(rèn)為el所引用DOM元素綁定事件芥丧。</em></p>

<h2>移除視圖-remove()</h2>

<p>調(diào)用View.remove()擅耽,從DOM中移除一個視圖乖仇。同時將調(diào)用stopListening來移除通過 listenTo綁定在視圖上的所有事件。</p>


    app.menulistview.remove();

<p>以上是對Backbone視圖的回顧與總結(jié)询兴,下一篇將介紹<a >Backbone事件</a>乃沙。</p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蕉朵,隨后出現(xiàn)的幾起案子崔涂,更是在濱河造成了極大的恐慌阳掐,老刑警劉巖始衅,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缭保,居然都是意外死亡汛闸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門艺骂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人厘肮,你說我怎么就攤上這事耍属『衿” “怎么了厦瓢?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我杉武,道長,這世上最難降的妖魔是什么祈搜? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任蘸秘,我火速辦了婚禮,結(jié)果婚禮上颈嚼,老公的妹妹穿的比我還像新娘。我一直安慰自己霞揉,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布抚官。 她就那樣靜靜地躺著凌节,像睡著了一般朴上。 火紅的嫁衣襯著肌膚如雪畔裕。 梳的紋絲不亂的頭發(fā)上垢粮,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音,去河邊找鬼翩概。 笑死牍鞠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播攀芯,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼紧武,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起畦幢,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎印颤,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體矢否,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡畏鼓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年陨界,在試婚紗的時候發(fā)現(xiàn)自己被綠了俏扩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡崔拥,死狀恐怖慈俯,靈堂內(nèi)的尸體忽然破棺而出略号,到底是詐尸還是另有隱情羽利,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布玲献,位于F島的核電站礼预,受9級特大地震影響励堡,放射性物質(zhì)發(fā)生泄漏鹅龄。R本人自食惡果不足惜玷坠,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岛杀。三九已至遗锣,卻和暖如春笔咽,著一層夾襖步出監(jiān)牢的瞬間甩十,已是汗流浹背达吞。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工遮咖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子委刘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容