让我通过做出以下声明来开始这个有利于后端或服务器端程序员的博客:
“服务器端程序员(Java 或类似的)可以比 html 开发人员更快地理解 javascript 客户端或服务器端框架或库的细微差别”。
上述说法背后有两个关键原因:
- 客户端开发不限于 HTML/CSS,而是已经发展到包含 编程和设计范式 ,这对于 html 程序员来说很复杂。
- 包括模式在内的设计范例需要应用于前端代码,以保持其 可维护性、高性能和可扩展性 ——这对程序员来说是一片绿地,但对 HTML 开发者来说不是。
话虽如此,我写这篇博客是为了展示 java 程序员将概念从 java 关联到 javascript 是多么容易。我同样选择了 Backbone.js,这是一个用于开发单页 Web 应用程序的流行库。
Backbone 和 AngularJS 之间有一个主要区别,后者是一个框架,而 Backbone 是一个库。框架强加了更多的约束和假设,被认为可以让生活更轻松,但代价是更加严格和繁重(尤其是 javascript 的大小)。
“ 从 Java 程序员的角度来看,JavaScript 库类似于 Apache CommonUtils 库(可作为 JAR 分发),而框架是 Apache Wicket 或 Spring 框架(可作为 JAR 集分发)。 ”
Backbone.js 是 MVP 模式的实现(类似于 MVC 模式,但略有偏差),这对于 java 程序员(可能对于 HTML 开发人员而言)并不是一个新概念。
下面的矩阵可以方便地关联基于 Java 和 Backbone 的组件之间的概念元素:
爪哇 | JavaScript(主干) | |
---|---|---|
模型 | JPA 实体或 POJO 类 | 创建模型类扩展 Backbone.Model.extend()。 Backbone 也有 Collection 对象的概念,它不过是 Model 对象的集合。 |
看法 | JSP 或 XHTML(带有 scriplet) |
它有两个部分:
|
控制器 | POJO 类操作模型和更新视图 |
骨干路由器是类似的组件,但不完全相同。它将 URL 映射到 Javascript 函数。 |
Java JavaScript (Backbone) 模型 JPA 实体或 POJO 类 要创建模型类,请扩展 Backbone.Model.extend()。 Backbone 也有 Collection 对象的概念,它不过是 Model 对象的集合。查看 JSP 或 XHTML(使用 scriplet)它有两个部分:
- 作为 HTML 的模板——Backbone 利用自己的模板或 JS 模板库,如 Handlebar
- 以 JavaScript 形式查看渲染代码——在模型更改时,调用相关代码在 DOM 中查找元素并使用 Jquery 更新 HTML。
Controller POJO Class manipulating Models & updating View A Backbone Router 是类似的组件,但不完全相同。它将 URL 映射到 Javascript 函数。
单页客户端应用程序的逻辑架构可以可视化如下:
我创建了一个非常简单的应用程序,其中列出了员工以及一些数据元素。
上述应用程序的 javascript 源代码如下,它演示了使用主干库的简单性。
// Namespace our app
var app = {};
// define employee model
app.employee = Backbone.Model.extend({
defaults: {
company: "Lorem Ipsum",
}
});
// define view rendering logic for employee
app.employeeView = Backbone.View.extend({
tagName: "article",
template: _.template( $("#employeeElement").html() ),
render: function() {
var employeeTemplate = this.template(this.model.toJSON());
this.$el.html(employeeTemplate);
return this;
}
});
// A group (array) of employee models
app.employeeCollection = Backbone.Collection.extend({
// What type of models are in this collection?
model: app.employee
});
// defined rendering logic for employee collection
app.employeeGroupView = Backbone.View.extend({
tagName: "section",
render: function() {
this.collection.each(this.addEmployee, this);
return this;
},
addEmployee: function(employee) {
var employeeView = new app.employeeView ({ model: employee });
this.$el.append(employeeView.render().el);
}
});
// action for URLs
app.Router = Backbone.Router.extend({
routes :{
"": "noCopy",
"firstEmployee" : "firstEmployeeMessage",
"secondEmployee": "secondEmployeeMessage"
},
noCopy: function() {
$(".message").html("");
},
firstEmployeeMessage: function() {
$(".message").html("
给第一位员工的消息
// Namespace our app
var app = {};
// define employee model
app.employee = Backbone.Model.extend({
defaults: {
company: "Lorem Ipsum",
}
});
// define view rendering logic for employee
app.employeeView = Backbone.View.extend({
tagName: "article",
template: _.template( $("#employeeElement").html() ),
render: function() {
var employeeTemplate = this.template(this.model.toJSON());
this.$el.html(employeeTemplate);
return this;
}
});
// A group (array) of employee models
app.employeeCollection = Backbone.Collection.extend({
// What type of models are in this collection?
model: app.employee
});
// defined rendering logic for employee collection
app.employeeGroupView = Backbone.View.extend({
tagName: "section",
render: function() {
this.collection.each(this.addEmployee, this);
return this;
},
addEmployee: function(employee) {
var employeeView = new app.employeeView ({ model: employee });
this.$el.append(employeeView.render().el);
}
});
// action for URLs
app.Router = Backbone.Router.extend({
routes :{
"": "noCopy",
"firstEmployee" : "firstEmployeeMessage",
"secondEmployee": "secondEmployeeMessage"
},
noCopy: function() {
$(".message").html("");
},
firstEmployeeMessage: function() {
$(".message").html("
给第二名员工的消息
// Namespace our app
var app = {};
// define employee model
app.employee = Backbone.Model.extend({
defaults: {
company: "Lorem Ipsum",
}
});
// define view rendering logic for employee
app.employeeView = Backbone.View.extend({
tagName: "article",
template: _.template( $("#employeeElement").html() ),
render: function() {
var employeeTemplate = this.template(this.model.toJSON());
this.$el.html(employeeTemplate);
return this;
}
});
// A group (array) of employee models
app.employeeCollection = Backbone.Collection.extend({
// What type of models are in this collection?
model: app.employee
});
// defined rendering logic for employee collection
app.employeeGroupView = Backbone.View.extend({
tagName: "section",
render: function() {
this.collection.each(this.addEmployee, this);
return this;
},
addEmployee: function(employee) {
var employeeView = new app.employeeView ({ model: employee });
this.$el.append(employeeView.render().el);
}
});
// action for URLs
app.Router = Backbone.Router.extend({
routes :{
"": "noCopy",
"firstEmployee" : "firstEmployeeMessage",
"secondEmployee": "secondEmployeeMessage"
},
noCopy: function() {
$(".message").html("");
},
firstEmployeeMessage: function() {
$(".message").html("
您现在需要做的就是在您的页面中跟随 HTML 片段来呈现视图:
// Namespace our app
var app = {};
// define employee model
app.employee = Backbone.Model.extend({
defaults: {
company: "Lorem Ipsum",
}
});
// define view rendering logic for employee
app.employeeView = Backbone.View.extend({
tagName: "article",
template: _.template( $("#employeeElement").html() ),
render: function() {
var employeeTemplate = this.template(this.model.toJSON());
this.$el.html(employeeTemplate);
return this;
}
});
// A group (array) of employee models
app.employeeCollection = Backbone.Collection.extend({
// What type of models are in this collection?
model: app.employee
});
// defined rendering logic for employee collection
app.employeeGroupView = Backbone.View.extend({
tagName: "section",
render: function() {
this.collection.each(this.addEmployee, this);
return this;
},
addEmployee: function(employee) {
var employeeView = new app.employeeView ({ model: employee });
this.$el.append(employeeView.render().el);
}
});
// action for URLs
app.Router = Backbone.Router.extend({
routes :{
"": "noCopy",
"firstEmployee" : "firstEmployeeMessage",
"secondEmployee": "secondEmployeeMessage"
},
noCopy: function() {
$(".message").html("");
},
firstEmployeeMessage: function() {
$(".message").html("