您将要创建的内容
概述
主干视图为用户界面提供了有用的约定和抽象。但是,要在您的应用程序中包含 backbone 本身并不支持的 UI 功能,您需要考虑如何将自定义或第三方功能有效地集成到您的 Backbone 应用程序中。因此,开发人员必须应对挑战并避免外部库和 Backbone 之间的棘手冲突。
Backbone.js 简介
Backbone 是组织客户端代码的绝佳方式。通过模型、视图和集合等抽象,Backbone 帮助认真的开发人员编写组织良好、可扩展的应用程序。
虽然 Backbone 有许多替代品,包括angular和 Ember,但 Backbone 为开发人员提供了令人难以置信的自由,以自然和舒适的方式编写和组织他们的代码,而不必对文档对象模型 ( dom ) 的外观过于固执己见。
骨干视图上的瘦子
视图是 Backbone 中最强大、最灵活的组件之一。根据 Backbone 的作者:
Backbone 视图几乎比它们的代码更具约定性——它们不会为您确定有关您的 html 或css的任何内容,并且可以与任何javascript模板库一起使用。
它们用于操纵用户在浏览器中看到的内容,并促进与模型的通信。因此,在 Model-View-Controller 的范式中,将 Backbone 视图视为视图和控制器是很有用的。
这在开发具有重要用户交互的应用程序时具有严重的影响。事实上,在很多情况下,您可能希望使用其他库来操作 DOM。数据可视化和基于 Web 的游戏是两个示例,您可能希望让另一个库处理一些面向用户的视图渲染。因此,您可能会考虑使用jquery、d3.js、crossfilter 或 three.js 来满足您的一些 DOM 操作需求。
幸运的是,有一些方法可以让 Backbone 与这些其他 DOM 操作器很好地配合使用。
在 Backbone 中操作文档对象模型
在我们开始之前,让我们回顾一下 Backbone 中的 DOM 操作。让我们从一个基本的视图对象开始。
var SomeView = Backbone.View.extend({ // Some definition stuff here }); var aView = new SomeView();
伟大的。.render()现在,让我们通过定义一个方法来告诉视图如何呈现自己。
var SomeView = Backbone.View.extend({ // define how to render something render: function() { // get some HTML var htmlContent = "<p>This some HTML that will be inserted into the DOM</p>"; // insert the html this.$el.html(htmlContent); // return an instance of the object for chaining return this; } });
这里发生了几件事,所以让我们一步一步来。
定义一个.render()方法
首先,我们定义一个.render()方法来封装呈现 HTML 所需的逻辑。请注意,Backbone 带有一个.render()开箱即用的方法。但是,它什么也没做。它旨在被自定义逻辑覆盖!
获取 HTML 内容
上面的示例假设您在某处获得了 HTML。您可以使用下划线_.template()。或者,我们可以使用其他模板库,比如把手(我个人最喜欢的)。真正重要的是,不知何故,我们得到了一些 HTML 内容。
到底是el什么?
我们需要一个放置 HTML 内容的地方;这就是el目的。Like .render(),el是 Backbone Views 开箱即用的属性。它引用了该视图中包含的 HTML 元素(及其所有子元素)。在上面的例子中,我们没有指定el. 默认情况下,el是一个div. 但是,我们可以像这样轻松设置父元素:
var SomeView = Backbone.View.extend({ el: "article", ... }); var aView = new SomeView(); console.log(aView.el); // an empty "article" HTML element
还有$el, 它只是 el包装在 jQuery 中。稍后我们将看到它$el在掌握 Backbone 视图中起着强大的作用。
回this…
最后,我们返回对对象本身的引用以允许链接。虽然不是严格要求d,但返回this是一种约定。如果没有return this,我们将需要某种方式来访问元素的 HTML 内容。以下代码说明了另一种解决方案。
/** * If render() returns nothing, we are really * accessing the `el` property of undefined, which does not * exist! */ aView.render().el; // Should throw an error // Try accessing the HTML console.log(aView.el); // Should be empty (but defined!) // add HTML to the DOM of 'aView' aView.render(); // Try accessing the HTML again console.log(aView.el) // Should contain the HTML
呃,屏幕上什么都没有!
好点子。即使我们调用.render()了 ,屏幕上也没有任何内容——是什么给出的?
那是因为我们还没有与 DOM 交互。我们所做的只是生成一些 HTML 并将其表示在一个名为aView. 由于我们现在可以访问生成的 HTML,我们所要做的就是在您的 Web 应用程序的 DOM 中附加或插入 HTML。
为了继续进行,我们还将设置一个迷你应用程序,以便在页面加载时显示视图。下面是您的 HTML 和 JavaScript 的外观。
基本 HTML 设置
<html> <head> <meta charset="utf-8"> <title>My Awesome Backbone App</title> <!-- Include your CSS Here --> <link rel="stylesheet" type="text/css" href="/css/styles.css" /> <!-- Include JS dependencies --> <!-- Backbone depends on underscore and, in this example, depends on jQuery. Please note the order of the dependencies --> <script src="/js/lib/jquery.js"></script> <script src="/js/lib/underscore.js"></script> <script src="/js/lib/backbone.js"></script> </head> <body> <div class="app"></div> <!-- Include your custom Backbone code in the below script --> <script src="/js/app.js"></script> </body> </html>
这是 App.js 中发生的事情
// Create a view var SomeView = Backbone.View.extend({ initialize: function() {}, render: function() { var someHTML = "<p>This is some HTML</p>"; this.$el.html(someHTML); return this; } }); // Create a router var Router = Backbone.Router.extend({ // define your routes routes: { "": "home" }, home: function() { var aView = new SomeView(); $('.app').html(aView.render().el); } }); // Instantiate your router new Router(); // Start tracking history Backbone.history.start();
转到您的本地服务器/浏览器,加载页面,您的应用程序应该正在运行!
同时使用 Backbone 和 jQuery
Backbone 的灵活性允许我们使用第三方库来操作 DOM。一种情况是当您想同时使用 jQuery 和 Backbone 来操作您的视图时。下面是一个更新的例子。
var SomeView = Backbone.View.extend({ // Manipulate DOM indirectly by creating HTML content in a // Backbone View render: function() { var someHTML = "<p>Some HTML</p><p class='empty'><p>"; this.$el.html(someHTML); return this; }, // Manipulate DOM directly from within the Backbone View renderWithJQuery: function() { var otherHTML = "<p>Other HTML</p>"; $('.app').append(otherHTML); // may not make sense to return 'this' }, // another render method, to keep things interesting specialRender: function() { this.$('.empty').append("<span>No longer empty!</span>"); return this; } }); // Later in your app... // create the view var aView = new SomeView(); // change the DOM to reflect the newly created view $('.app').html(aView.render().el); // append more content directly to the DOM using jQuery within // a Backbone view object aView.renderWithJQuery();
上面的代码将在页面上产生两个段落。第一段包含“一些 HTML”。第二段包含“其他 HTML”。
要测试您对此的理解,请反转方法调用,如下所示:
// SomeView is already defined var aView = new SomeView(); aView.renderWithJQuery(); $('.app').html(aView.render().el);
上面的代码将产生一个段落:“一些 HTML”。在这两种情况下,还有一个 <p>元素里面什么都没有。我们稍后会讨论这个问题。
有效地操作主干视图中的 DOM
理解高效 DOM 操作(和遍历)的魔力需要理解this.$el和this.$()。通过使用this.$el,我们将 DOM 操作范围限定为视图中包含的内容。通过使用this.$(),我们将 DOM 遍历范围限定为视图中的 DOM 树。
因此,在 Backbone 上下文中,$()(而不是this.$())的某些使用可能效率低下。例如,假设我们想要遍历 DOM 来查找某个元素。我们可以使用任何常见的 DOM 遍历方法,包括.find()、.children()、.closest()、.first()等等。
如果我们先验地知道我们寻找的元素位于视图的 DOM 中,那么我们应该使用它this.$()来避免不必要地搜索更大的 DOM 树。如果我们寻找的元素位于视图的 DOM 之外,那么我们需要使用$().
例如,该.specialRender()方法使用本地化的 DOM 遍历来确保我们empty在视图的上下文中搜索具有类的元素。如果找到,它会将这些元素的 HTML 内容设置为包含 aspan和文本“不再为空”。
结论
在本文中,我们回顾了 Backbone 视图,讨论了如何在 DOM 中呈现 Backbone 视图,并探讨了如何使 Backbone 与您可能想要用来操作 DOM 的其他库很好地配合使用。我们还了解了本地化的 DOM 遍历,并确定了有效和低效遍历 DOM 的方法。
- 在 Backbone 中操作文档对象模型
- 定义一个.render()方法
- 获取 HTML 内容
- 到底是el什么?
- 回this…
- 呃,屏幕上什么都没有!
- 基本 HTML 设置
- 这是 App.js 中发生的事情
- 同时使用 Backbone 和 jQuery
- 有效地操作主干视图中的 DOM