总览
骨干视图为用户界面提供了有用的约定和抽象。 但是,要在Backbone本身不旨在支持的应用程序中包含UI功能,您需要考虑如何将自定义或第三方功能有效地集成到Backbone应用程序中。 因此,开发人员必须应对挑战,并避免外部库与Backbone之间的棘手冲突。
Backbone.js简介
骨干网是一种组织客户端代码的绝妙方法。 借助模型,视图和集合之类的抽象,Backbone可以帮助认真的开发人员编写井井有条的可扩展应用程序。
尽管Backbone有许多替代方案,包括Angular和Ember,但Backbone为开发人员提供了以自然而舒适的方式编写和组织代码的令人难以置信的自由,而无需过多考虑文档对象模型(DOM)的外观。
骨干视图上的瘦身
视图是Backbone中功能最强大,最灵活的组件之一。 根据骨干网的作者:
骨干视图几乎比代码更具惯例性-它们不会为您确定有关HTML或CSS的任何内容,并且可以与任何JavaScript模板库一起使用。
它们用于操纵用户在浏览器中看到的内容,并促进与模型的通信。 结果,在Model-View-Controller的范例中,将Backbone Views既视为视图又作为控制器是很有用的。
在开发具有重大用户交互作用的应用程序时,这具有严重的意义。 实际上,在许多情况下,您可能想使用其他一些库来操作DOM。 数据可视化和基于Web的游戏是两个示例,您可能希望让另一个库来处理一些面向用户的视图呈现。 结果,您可能考虑使用jQuery,d3.js,crossfilter或three.js来满足某些DOM操作需求。
幸运的是,有一些方法可以使Backbone与其他DOM机械手完美配合。
在骨干网中操作文档对象模型
在开始讨论之前,让我们回顾一下Backbone中的DOM操作。 让我们从一个基本的view对象开始。
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()
。 另外,我们可以使用其他模板库,例如Handlebars(我个人最喜欢的)。 真正重要的是,以某种方式,我们获得了一些HTML内容。
这到底是el
?
我们需要放置HTML内容的地方; 这就是el
目的。 像.render()
, el
是随骨架视图一起提供的属性。 它引用了此视图中包含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
……
最后,我们返回对对象本身的引用以允许链接。 虽然不是严格要求,返回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
JavaScript对象中。 由于我们现在可以访问生成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);
上面的代码将导致一段文字:“ Some 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内容以包括span
和文本“不再为空”。
结论
在本文中,我们回顾了Backbone视图,讨论了如何在DOM中渲染Backbone视图,并探讨了如何使Backbone与您可能想用来操纵DOM的其他库很好地协同工作。 我们还了解了局部DOM遍历,并确定了有效和低效遍历DOM的方法。
本文的下一部分将更深入地研究使多个库协同工作以处理DOM的更复杂的示例。
翻译自: https://code.tutsplus.com/articles/backbone-views-and-the-dom--cms-25643