如何在 Backbone.js 中将视图代码分离为模型和控制器
How to separate view code into model and controller in Backbone.js
我有我的代码,它是一个基本的 TODO 列表,其中只有以下几行代码。
我面临的问题是几乎所有东西都挤在视图本身中。模型或集合中几乎没有任何代码行,而且也没有控制器。
这否定了我正在尝试实现的 backbone 中的 MVC。有什么方法可以从视图中删除代码并将其放入任何其他模块中吗?
(function($){
Backbone.sync = function(method, model, success, error){
success();
}
var Item = Backbone.Model.extend({});
var List = Backbone.Collection.extend({
model: Item
});
var ItemView = Backbone.View.extend({
tagName: 'div', // name of tag to be created
events: {
'click span.delete': 'remove'
},
initialize: function(){
_.bindAll(this, 'render', 'unrender', 'remove'); // every function that uses 'this' as the current object should be in here
this.model.bind('change', this.render);
this.model.bind('remove', this.unrender);
},
render: function(){
$(this.el).html("<span style='margin-left: 20px;'></span>"+this.model.get('part')+'<span class="delete" style="cursor:pointer; color:red; font-family:sans-serif;">[delete]</span>');
return this; // for chainable calls, like .render().el
},
unrender: function(){
this.model.destroy();
}
});
var ListView = Backbone.View.extend({
el: $('body'), // attaches `this.el` to an existing element.
events: {
'click button#add': 'addItem'
},
initialize: function(){
_.bindAll(this, 'render', 'addItem'); // fixes loss of context for 'this' within methods
this.collection = new List();
this.collection.bind('add', this.appendItem); // collection event binder
this.render(); // not all views are self-rendering. This one is.
},
render: function(){
var self = this;
$(this.el).append("<body style='margin: 0; padding: 0;' id='body'><div style='margin: 20px;'><h1>TODO list in plain JS and JQuery</h1><input type='text' id='taskBox' autofocus/>");
$(this.el).append("<span id='appendToSpan'></span>");
$(this.el).append("<button style='margin-left: 20px;' id='add'>Add list item</button>");
_(this.collection.models).each(function(item){ // in case collection is not empty
self.appendItem(item);
}, this);
},
addItem: function(){
var item = new Item();
var val = $(this.el).find('input#taskBox').val();
$(this.el).find('input#taskBox').val('');
//this.model.set({'part': val});
item.set({'part': val});
this.collection.add(item);
},
appendItem: function(item){
var itemView = new ItemView({
model: item
});
$('span#appendToSpan', this.el).append(itemView.render().el);
}
});
var listView = new ListView();
})(jQuery);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TODO App</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.io/backbone/backbone-min.js"></script>
<script src="views/demo1View.js" type="text/javascript"></script>
</body>
</html>
Backbonejs 不是 MVC 框架。它更像是 MVP(P - 演示者)框架。换句话说,您可以将您的逻辑驻留在视图中,该视图在真正的 MVC 框架中扮演控制器的角色。
只是尝试分离组件的职责并使其尽可能简单。
我建议对您的代码进行以下重构:
(function($){
Backbone.sync = function(method, model, success, error){
success();
}
var Item = Backbone.Model.extend({});
var List = Backbone.Collection.extend({
model: Item
});
var ItemView = Backbone.View.extend({
events: {
'click .js-delete': 'remove'
},
template: _.template($('#itemViewTemplate').html()),
initialize: function(){
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'remove', this.unrender);
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
unrender: function(){
this.$el.remove();
}
});
var ListView = Backbone.View.extend({
events: {
'click .js-addItem': 'addItem'
},
initialize: function(){
this.listenTo(this.collection, 'add', this.appendItem);
},
render: function(){
this.collection.each(this.appendItem, this);
return this;
},
addItem: function(){
var $input = this.$('input#taskBox')
var val = $input.val();
this.collection.add({part: val});
// clear input
$input.val('');
},
appendItem: function(item){
var itemView = new ItemView({
model: item,
template: this.template
});
this.$('#appendToSpan').append(itemView.render().el);
}
});
// Initialize widget and empty collection
var listView = new ListView({
el: 'body',
collection: new List()
});
// Render collection
listView.render();
})(jQuery);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TODO App</title>
<style>
body {
margin: 0;
padding: 0;
}
.container {
margin: 20px;
}
.addButton {
margin-left: 20px;
margin-top: 10px;
}
.item-name {
margin-left: 20px;
}
.item-remove {
cursor:pointer;
color:red;
font-family:sans-serif;
}
</style>
</head>
<body>
<div class="container">
<h1>TODO list in plain JS and JQuery</h1>
<input type='text' id='taskBox' autofocus/>
<div id='appendToSpan'></div>
<button class="addButton js-addItem">Add list item</button>
<!-- Item template -->
<script type="text/template" id="itemViewTemplate">
<span class="item-name"><%= part %></span>
<span class="js-delete item-remove">[delete]</span>
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.io/backbone/backbone-min.js"></script>
</body>
</html>
我有我的代码,它是一个基本的 TODO 列表,其中只有以下几行代码。
我面临的问题是几乎所有东西都挤在视图本身中。模型或集合中几乎没有任何代码行,而且也没有控制器。
这否定了我正在尝试实现的 backbone 中的 MVC。有什么方法可以从视图中删除代码并将其放入任何其他模块中吗?
(function($){
Backbone.sync = function(method, model, success, error){
success();
}
var Item = Backbone.Model.extend({});
var List = Backbone.Collection.extend({
model: Item
});
var ItemView = Backbone.View.extend({
tagName: 'div', // name of tag to be created
events: {
'click span.delete': 'remove'
},
initialize: function(){
_.bindAll(this, 'render', 'unrender', 'remove'); // every function that uses 'this' as the current object should be in here
this.model.bind('change', this.render);
this.model.bind('remove', this.unrender);
},
render: function(){
$(this.el).html("<span style='margin-left: 20px;'></span>"+this.model.get('part')+'<span class="delete" style="cursor:pointer; color:red; font-family:sans-serif;">[delete]</span>');
return this; // for chainable calls, like .render().el
},
unrender: function(){
this.model.destroy();
}
});
var ListView = Backbone.View.extend({
el: $('body'), // attaches `this.el` to an existing element.
events: {
'click button#add': 'addItem'
},
initialize: function(){
_.bindAll(this, 'render', 'addItem'); // fixes loss of context for 'this' within methods
this.collection = new List();
this.collection.bind('add', this.appendItem); // collection event binder
this.render(); // not all views are self-rendering. This one is.
},
render: function(){
var self = this;
$(this.el).append("<body style='margin: 0; padding: 0;' id='body'><div style='margin: 20px;'><h1>TODO list in plain JS and JQuery</h1><input type='text' id='taskBox' autofocus/>");
$(this.el).append("<span id='appendToSpan'></span>");
$(this.el).append("<button style='margin-left: 20px;' id='add'>Add list item</button>");
_(this.collection.models).each(function(item){ // in case collection is not empty
self.appendItem(item);
}, this);
},
addItem: function(){
var item = new Item();
var val = $(this.el).find('input#taskBox').val();
$(this.el).find('input#taskBox').val('');
//this.model.set({'part': val});
item.set({'part': val});
this.collection.add(item);
},
appendItem: function(item){
var itemView = new ItemView({
model: item
});
$('span#appendToSpan', this.el).append(itemView.render().el);
}
});
var listView = new ListView();
})(jQuery);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TODO App</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.io/backbone/backbone-min.js"></script>
<script src="views/demo1View.js" type="text/javascript"></script>
</body>
</html>
Backbonejs 不是 MVC 框架。它更像是 MVP(P - 演示者)框架。换句话说,您可以将您的逻辑驻留在视图中,该视图在真正的 MVC 框架中扮演控制器的角色。
只是尝试分离组件的职责并使其尽可能简单。
我建议对您的代码进行以下重构:
(function($){
Backbone.sync = function(method, model, success, error){
success();
}
var Item = Backbone.Model.extend({});
var List = Backbone.Collection.extend({
model: Item
});
var ItemView = Backbone.View.extend({
events: {
'click .js-delete': 'remove'
},
template: _.template($('#itemViewTemplate').html()),
initialize: function(){
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'remove', this.unrender);
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
unrender: function(){
this.$el.remove();
}
});
var ListView = Backbone.View.extend({
events: {
'click .js-addItem': 'addItem'
},
initialize: function(){
this.listenTo(this.collection, 'add', this.appendItem);
},
render: function(){
this.collection.each(this.appendItem, this);
return this;
},
addItem: function(){
var $input = this.$('input#taskBox')
var val = $input.val();
this.collection.add({part: val});
// clear input
$input.val('');
},
appendItem: function(item){
var itemView = new ItemView({
model: item,
template: this.template
});
this.$('#appendToSpan').append(itemView.render().el);
}
});
// Initialize widget and empty collection
var listView = new ListView({
el: 'body',
collection: new List()
});
// Render collection
listView.render();
})(jQuery);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TODO App</title>
<style>
body {
margin: 0;
padding: 0;
}
.container {
margin: 20px;
}
.addButton {
margin-left: 20px;
margin-top: 10px;
}
.item-name {
margin-left: 20px;
}
.item-remove {
cursor:pointer;
color:red;
font-family:sans-serif;
}
</style>
</head>
<body>
<div class="container">
<h1>TODO list in plain JS and JQuery</h1>
<input type='text' id='taskBox' autofocus/>
<div id='appendToSpan'></div>
<button class="addButton js-addItem">Add list item</button>
<!-- Item template -->
<script type="text/template" id="itemViewTemplate">
<span class="item-name"><%= part %></span>
<span class="js-delete item-remove">[delete]</span>
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.io/backbone/backbone-min.js"></script>
</body>
</html>