Backbone 中的 View 用来反映你 app 中 Model 的模样。它们会监听事件并作出相应的反应。
接下来的教程我不会告诉你如何把 Model 和 Collection 绑定到 View 上,而是主要讨论 View 是如何使用 javascript 模板库的,尤其是 Underscore.js's _.template。
这里我们使用 jQuery 来操作 DOM 元素,当然你也可以使用其他的库,例如 MooTools 或者 Sizzle,但是 Backbone 的官方文档推荐我们使用 jQuery。
接下来,我们以搜索框为例来新建一个 View:
SearchView = Backbone.View.extend({ initialize: function(){ alert("Welcome to Backbone!"); } }); var search_view = new SearchView();
无论是 Model,View 还是 Collection,当被实例化时,initialize() 方法都会被自动触发。
el 属性
el 属性指的是已经在浏览器中创建好的 DOM 对象,每个 View 都有一个 el 属性,如果它未被定义,Backbone 将会自己创建一个空的 div 元素作为 el 属性。
下面让我们来为 View 创建一个 el 属性,并设为 #search_containe。
<div id="search_container"></div> <script type="text/javascript"> SearchView = Backbone.View.extend({ initialize: function(){ alert("Welcome to Backbone!"); } }); var search_view = new SearchView({ el: $("#search_container") }); </script>
此时,View 的 el 属性指的是 id 为 search_container 的 div 元素。我们此时变绑定了这个 div 元素,那么任何我们希望触发的事件都必须在这个 div 元素中。
加载模板
Backbone 是强依赖于 Underscore.js 的,所以我们可以使用 Underscore.js 中的小型模板。
现在,让我们添加一个 render() 方法,并且在 initialize() 中调用它,这样当 View 初始化时便会自动触发 render() 方法。
这个 render() 方法将会通过 jQuery 把模板加载到 View 的 el 属性中去。
<script type="text/template" id="search_template"> <label>Search</label> <input type="text" id="search_input" /> <input type="button" id="search_button" value="Search" /> </script> <div id="search_container"></div> <script type="text/javascript"> SearchView = Backbone.View.extend({ initialize: function(){ this.render(); }, render: function(){ // 通过 Underscore 编译生成模板 var template = _.template( $("#search_template").html(), {} ); //讲生成的模板加载到 el 属性中 this.$el.html( template ); } }); var search_view = new SearchView({ el: $("#search_container") }); </script>
添加监听事件
我们使用 View 的 events 属性添加监听事件,记住监听事件只能添加到 el 属性的子元素上。现在,我们来给子元素 button 添加一个监听事件。
<script type="text/template" id="search_template"> <label>Search</label> <input type="text" id="search_input" /> <input type="button" id="search_button" value="Search" /> </script> <div id="search_container"></div> <script type="text/javascript"> SearchView = Backbone.View.extend({ initialize: function(){ this.render(); }, render: function(){ var template = _.template( $("#search_template").html(), {} ); this.$el.html( template ); }, events: { "click input[type=button]": "doSearch" }, doSearch: function( event ){ // 当 button 被点击时触发 alert alert( "Search for " + $("#search_input").val() ); } }); var search_view = new SearchView({ el: $("#search_container") }); </script>
向模板中传递参数
模板可以通过 <%= %> 的形式使用从 View 中传来的参数。
<script type="text/template" id="search_template"> <!-- 通过 <%= %> 形式使用传来的参数 --> <label><%= search_label %></label> <input type="text" id="search_input" /> <input type="button" id="search_button" value="Search" /> </script> <div id="search_container"></div> <script type="text/javascript"> SearchView = Backbone.View.extend({ initialize: function(){ this.render(); }, render: function(){ //定义需要传递的参数 var variables = { search_label: "My Search" }; // 通过 Underscore 生成模板,同时传递参数 var template = _.template( $("#search_template").html(), variables ); // Load the compiled HTML into the Backbone "el" this.$el.html( template ); }, events: { "click input[type=button]": "doSearch" }, doSearch: function( event ){ alert( "Search for " + $("#search_input").val() ); } }); var search_view = new SearchView({ el: $("#search_container") }); </script>
处理DOM事件
视图很重要的一个特性是帮助我们自动绑定界面事件。回想一下我们以前是如何为界面标签绑定事件的?可能就像这样:
<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>
这是一个典型的通过jQuery绑定DOM事件的例子,如果你正在开发或曾经开发过一些复杂的应用,你可能尝试过通过某种方式将这些代码更好的组织起来,以便使它们看起来结构更加清晰,更易维护。
Backbone的视图对象为我们提供了事件的自动绑定机制,用于更好地维护DOM和事件间的关系,来看看下面的例子:
<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() { // todo }, readData : function() { // todo }, updateData : function() { // todo }, deleteData : function() { // todo } }); var view = new MyView(); </script>
在这个例子中,我们将4个按钮放在一个id为view的标签中,并将这个标签与视图类MyView进行了关联。
在定义视图类时,我们声明了一个events属性,它表示视图中的用户事件列表,描述方式如下:
事件名称 选择器 : 事件处理函数
视图对象会自动解析events列表中的描述,即使用jQuery或Zepto获取选择器描述的DOM对象,并将事件处理函数绑定到事件名称中。这些操作都会在视图类被实例化时自动完成,我们可以更关心视图类本身的结构,而不是刻意地去考虑如何绑定事件。
你可能在担心另外一个问题:如果视图的DOM结构是动态生成的,Backbone是否提供了相应的方法用于动态绑定和解除事件?
其实你并不需要关心这个问题,因为events中的事件是通过delegate()方法绑定到视图对象的el元素上,而并非是选择器所描述的元素。因此视图内的结构无论如何变化,events中的事件都是有效的。
(如果你对jQuery比较熟悉,可能了解它所提供的delegate()方法。该方法实际上将事件绑定在父层元素,然后在事件冒泡过程中,通过检查目标子元素来触发事件。)
视图对象通过delegate()方法绑定事件,意味着我们不需要关心视图结构变化对事件产生的影响,同时也说明events中选择器所对应的元素必须处于视图的el元素之内,否则绑定的事件是无法生效的。
尽管如此,有些情况下可能我们仍然需要手动绑定和解除事件,视图对象提供了delegateEvents()和undelegateEvents()方法用于动态绑定和解除events事件列表,你可以通过查看API文档来了解它们。
渲染视图和数据
视图主要用于界面事件的绑定和数据渲染,然而视图对象仅仅提供了一个和渲染相关的方法render(),并且它是一个没有任何逻辑、也没有任何地方引用到的空方法,我们需要重载它来实现自己的渲染逻辑。
视图中可能包含许多界面逻辑,这里建议所有的视图子类都重载render()方法,并将它作为最终渲染的入口方法。在团队开发中,严格按照规范编码可以帮助别人更好地理解和维护你的代码。
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]