[转]Backbone.js简单入门范例
本文转自:http://dmyz.org/archives/598
11年刚开始用前端MVC框架时写过一篇文章,当时Knockout和Backbone都在用,但之后的项目全是在用Backbone,主要因为它简单、灵活,无论是富JS应用还是企业网站都用得上。写这篇文章的动机,是最近跟做在线教育的朋友聊,谈到比较好的中文入门教程不多,于是想针对自己用得最多的框架写一篇,说明如下:
1. 结构上分4节,介绍Model/View/Collection,实现从远程获取数据显示到表格且修改删除; 2. 名为“范例”,所以代码为主,每节的第1段代码都是完整代码,复制粘贴就能用,每段代码都是基于前一段代码来写的,因此每段代码的新内容不会超过20行(大括号计算在内); 3. 每行代码没有注释,但重要内容之后有写具体的说明; 4. 开发环境是Chrome,使用github的API,这样用Chrome即使在本地路径(形如file://的路径)也能获取数据。
0. Introduction
几乎所有的框架都是在做两件事:一是帮你把代码写在正确的地方;二是帮你做一些脏活累活。Backbone实现一种清晰的MVC代码结构,解决了数据模型和视图映射的问题。虽然所有JS相关的项目都可以用,但Backbone最适合的还是这样一种场景:需要用JS生成大量的页面内容(HTML为主),用户跟页面元素有很多的交互行为。
Backbone对象有5个重要的函数,Model/Collection/View/Router/History。Router和History是针对Web应用程序的优化,建议先熟悉pushState的相关知识。入门阶段可以只了解Model/Collection/View。将Model视为核心,Collection是Model的集合,View是为了实现Model的改动在前端的反映。
1. Model
Model是所有JS应用的核心,很多Backbone教程喜欢从View开始讲,其实View的内容不多,而且理解了View意义不大,理解Model更重要。以下代码实现从github的API获取一条gist信息,显示到页面上:
XHTML
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<table id="js-id-gists" class="table">
<thead><th>description</th><th>URL</th><th>created_at</th></thead>
<tbody></tbody>
</table>
<script type="text/javascript">
var Gist = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return (response[0]);
}
}),
gist = new Gist();
gist.on('change', function (model) {
var tbody = document.getElementById('js-id-gists').children[1],
tr = document.getElementById(model.get('id'));
if (!tr) {
tr = document.createElement('tr');
tr.setAttribute('id', model.get('id'));
}
tr.innerHTML = '<td>' + model.get('description') + '</td><td>' + model.get('url') + '</td><td>' + model.get('created_at') + '</td>';
tbody.appendChild(tr);
});
gist.fetch();
</script>
</body>
</html>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<table id="js-id-gists" class="table">
<thead><th>description</th><th>URL</th><th>created_at</th></thead>
<tbody></tbody>
</table>
<script type="text/javascript">
var Gist = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return (response[0]);
}
}),
gist = new Gist();
gist.on('change', function (model) {
var tbody = document.getElementById('js-id-gists').children[1],
tr = document.getElementById(model.get('id'));
if (!tr) {
tr = document.createElement('tr');
tr.setAttribute('id', model.get('id'));
}
tr.innerHTML = '<td>' + model.get('description') + '</td><td>' + model.get('url') + '</td><td>' + model.get('created_at') + '</td>';
tbody.appendChild(tr);
});
gist.fetch();
</script>
</body>
</html>
|
- LINE4~8: 加载要用到的JS库。ajax请求和部分View的功能需要jQuery支持(或者重写ajax/View的功能);Backbone的代码是基于Underscore写的(或者用Lo-Dash代替);加载bootstrap.css只是因为默认样式太难看…
- LINE16~22: 创建一个Model并实例化。url是数据源(API接口)的地址,parse用来处理返回的数据。实际返回的是一个Array,这里取第一个Object。
- LINE24~33: 绑定change事件。还没有使用View,所以要自己处理HTML。这10行代码主要是get的用法(model.get),其他的功能之后会用View来实现。
- LINE34: 执行fetch。从远程获取数据,获到数据后会触发change事件。可以重写sync方法
打开Chrome的Console,输入gist,可以看到Model获得的属性: 
Model提供数据和与数据相关的逻辑。上图输出的属性是数据,代码中的fetch/parse/get/set都是对数据进行操作,其他的还有escape/unset/clear/destory,从函数名字就大致可以明白它的用途。还有很常用的validate函数,在set/save操作时用来做数据验证,验证失败会触发invalid事件:
JavaScript
var Gist = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return (response[0]);
},
defaults: {
website: 'dmyz'
},
validate: function (attrs) {
if (attrs.website == 'dmyz') {
return 'Website Error';
}
}
}),
gist = new Gist();
gist.on('invalid', function (model, error) {
alert(error);
});
gist.on('change', function (model) {
var tbody = document.getElementById('js-id-gists').children[1],
tr = document.getElementById(model.get('id'));
if (!tr) {
tr = document.createElement('tr');
tr.setAttribute('id', model.get('id'));
}
tr.innerHTML = '<td>'+ model.get('description') +'</td><td>'+ model.get('url') +'</td><td>'+ model.get('created_at') +'</td>';
tbody.appendChild(tr);
});
gist.save();
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
/* 替换之前代码的JS部分(LINE16~34) */
var Gist = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return (response[0]);
},
defaults: {
website: 'dmyz'
},
validate: function (attrs) {
if (attrs.website == 'dmyz') {
return 'Website Error';
}
}
}),
gist = new Gist();
gist.on('invalid', function (model, error) {
alert(error);
});
gist.on('change', function (model) {
var tbody = document.getElementById('js-id-gists').children[1],
tr = document.getElementById(model.get('id'));
if (!tr) {
tr = document.createElement('tr');
tr.setAttribute('id', model.get('id'));
}
tr.innerHTML = '<td>'+ model.get('description') +'</td><td>'+ model.get('url') +'</td><td>'+ model.get('created_at') +'</td>';
tbody.appendChild(tr);
});
gist.save();
|
跟之前的代码比较,有4处改动:
- LINE7~9: 增加了defaults。如果属性中没有website(注意不是website值为空),会设置website值为dmyz。
- LINE10~14: 增加validate函数。当website值为dmyz时,触发invalid事件。
- LINE18~20: 绑定invalid事件,alert返回的错误。
- LINE31: 不做fetch,直接save操作。
因为没有fetch,所以页面上不会显示数据。执行save操作,会调用validate函数,验证失败会触发invalid事件,alert出错误提示。同时save操作也会向Model的URL发起一个PUT请求,github这个API没有处理PUT,所以会返回404错误。
在Console中输入gist.set(‘description’, ‘demo’),可以看到页面元素也会有相应的变化。执行gist.set(‘description’, gist.previous(‘description’))恢复之前的值。这就是Model和View的映射,现在还是自己实现的,下一节会用Backbone的View来实现。
2. View
用Backbone的View来改写之前代码LINE24~33部分:
XHTML
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<table id="js-id-gists" class="table">
<thead><th>description</th><th>URL</th><th>created_at</th><th></th></thead>
<tbody></tbody>
</table>
<script type="text/javascript">
var Gist = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response[0];
}
}),
gist = new Gist();
var GistRow = Backbone.View.extend({
el: 'tbody',
MODEL: gist,
events: {
'click a': 'replaceURL'
},
replaceURL: function () {
this.MODEL.set('url', 'http://dmyz.org');
},
initialize: function () {
this.listenTo(this.MODEL, 'change', this.render);
},
render: function () {
var model = this.MODEL,
tr = document.createElement('tr');
tr.innerHTML = '<td>' + model.get('description') + '</td><td>' + model.get('url') + '</td><td>' + model.get('created_at') + '</td><td><a href="javascript:void(0)">®</a></td>';
this.el.innerHTML = tr.outerHTML;
return this;
}
});
var tr = new GistRow();
gist.fetch();
</script>
</body>
</html>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<table id="js-id-gists" class="table">
<thead><th>description</th><th>URL</th><th>created_at</th><th></th></thead>
<tbody></tbody>
</table>
<script type="text/javascript">
var Gist = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response[0];
}
}),
gist = new Gist();
var GistRow = Backbone.View.extend({
el: 'tbody',
MODEL: gist,
events: {
'click a': 'replaceURL'
},
replaceURL: function () {
this.MODEL.set('url', 'http://dmyz.org');
},
initialize: function () {
this.listenTo(this.MODEL, 'change', this.render);
},
render: function () {
var model = this.MODEL,
tr = document.createElement('tr');
tr.innerHTML = '<td>' + model.get('description') + '</td><td>' + model.get('url') + '</td><td>' + model.get('created_at') + '</td><td><a href="javascript:void(0)">®</a></td>';
this.el.innerHTML = tr.outerHTML;
return this;
}
});
var tr = new GistRow();
gist.fetch();
</script>
</body>
</html>
|
- LINE25: 所有的View都是基于DOM的,指定el会选择页面的元素,指定tagName会创建相应的DOM,如果都没有指定会是一个空的div。
- LINE27~32: 绑定click事件到a标签,replaceURL函数会修改(set)url属性的值。
- LINE33~35: View的初始化函数(initialize),监听change事件,当Model数据更新时触发render函数。
- LINE36~42: render函数。主要是LINE41~42这两行,把生成的HTML代码写到this.el,返回this。
- LINE44: 实例化GistRow,初始化函数(initialize)会被执行。
点击行末的a标签,页面显示的这条记录的URL会被修改成http://dmyz.org。
这个View名为GistRow,选择的却是tbody标签,这显然是不合理的。接下来更改JS代码,显示API返回的30条数据:
JavaScript
var Gist = Backbone.Model.extend(),
Gists = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response;
}
}),
gists = new Gists();
var GistRow = Backbone.View.extend({
tagName: 'tr',
render: function (object) {
var model = new Gist(object);
this.el.innerHTML = '<td>' + model.get('description') + '</td><td>'+ model.get('url') + '</td><td>' + model.get('created_at') + '</td><td></td>'
return this;
}
});
var GistsView = Backbone.View.extend({
el: 'tbody',
model: gists,
initialize: function () {
this.listenTo(this.model, 'change', this.render);
},
render: function () {
var html = '';
_.forEach(this.model.attributes, function (object) {
var tr = new GistRow();
html += tr.render(object).el.outerHTML;
});
this.el.innerHTML = html;
return this;
}
});
var gistsView = new GistsView();
gists.fetch();
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
/* 替换之前代码的JS部分(LINE16~45) */
var Gist = Backbone.Model.extend(),
Gists = Backbone.Model.extend({
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response;
}
}),
gists = new Gists();
var GistRow = Backbone.View.extend({
tagName: 'tr',
render: function (object) {
var model = new Gist(object);
this.el.innerHTML = '<td>' + model.get('description') + '</td><td>'+ model.get('url') + '</td><td>' + model.get('created_at') + '</td><td></td>'
return this;
}
});
var GistsView = Backbone.View.extend({
el: 'tbody',
model: gists,
initialize: function () {
this.listenTo(this.model, 'change', this.render);
},
render: function () {
var html = '';
_.forEach(this.model.attributes, function (object) {
var tr = new GistRow();
html += tr.render(object).el.outerHTML;
});
this.el.innerHTML = html;
return this;
}
});
var gistsView = new GistsView();
gists.fetch();
|
- LINE2~9: 创建了两个Model(Gist和Gists),parse现在返回完整Array而不只是第一条。
- LINE11~18: 创建一个tr。render方法会传一个Object来实例化一个Gist的Model,再从这个Model里get需要的值。
- LINE26~34: 遍历Model中的所有属性。现在使用的是Model而不是Collection,所以遍历出的是Object。forEach是Underscore的函数。
Backbone的View更多的是组织代码的作用,它实际干的活很少。View的model属性在本节第一段代码用的是大写,表明只是一个名字,并不是说给View传一个Model它会替你完成什么,控制逻辑还是要自己写。还有View中经常会用到的template函数,也是要自己定义的,具体结合哪种模板引擎来用就看自己的需求了。
这段代码中的Gists比较难操作其中的每一个值,它其实应该是Gist的集合,这就是Backbone的Collection做的事了。
3. Collection
Collection是Model的集合,在这个Collection中的Model如果触发了某个事件,可以在Collection中接收到并做处理。第2节的代码用Collection实现:
XHTML
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<table id="js-id-gists" class="table">
<thead><th>description</th><th>URL</th><th>created_at</th><th></th></thead>
<tbody></tbody>
</table>
<script type="text/javascript">
var Gist = Backbone.Model.extend(),
Gists = Backbone.Collection.extend({
model: Gist,
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response;
}
}),
gists = new Gists();
var GistRow = Backbone.View.extend({
tagName: 'tr',
render: function (model) {
this.el.innerHTML = '<td>' + model.get('description') + '</td><td>'+ model.get('url') + '</td><td>' + model.get('created_at') + '</td><td></td>'
return this;
}
});
var GistsView = Backbone.View.extend({
el: 'tbody',
collection: gists,
initialize: function () {
this.listenTo(this.collection, 'reset', this.render);
},
render: function () {
var html = '';
_.forEach(this.collection.models, function (model) {
var tr = new GistRow();
html += tr.render(model).el.outerHTML;
});
this.el.innerHTML = html;
return this;
}
});
var gistsView = new GistsView();
gists.fetch({reset: true});
</script>
</body>
</html>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<table id="js-id-gists" class="table">
<thead><th>description</th><th>URL</th><th>created_at</th><th></th></thead>
<tbody></tbody>
</table>
<script type="text/javascript">
var Gist = Backbone.Model.extend(),
Gists = Backbone.Collection.extend({
model: Gist,
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response;
}
}),
gists = new Gists();
var GistRow = Backbone.View.extend({
tagName: 'tr',
render: function (model) {
this.el.innerHTML = '<td>' + model.get('description') + '</td><td>'+ model.get('url') + '</td><td>' + model.get('created_at') + '</td><td></td>'
return this;
}
});
var GistsView = Backbone.View.extend({
el: 'tbody',
collection: gists,
initialize: function () {
this.listenTo(this.collection, 'reset', this.render);
},
render: function () {
var html = '';
_.forEach(this.collection.models, function (model) {
var tr = new GistRow();
html += tr.render(model).el.outerHTML;
});
this.el.innerHTML = html;
return this;
}
});
var gistsView = new GistsView();
gists.fetch({reset: true});
</script>
</body>
</html>
|
- LINE17~23: 基本跟第2节的第2段代码一样。把Model改成Collection,指定Collection的Model,这样Collectio获得返回值会自动封装成Model的Array。
- LINE38: Collection和Model不同,获取到数据也不会触发事件,所以绑定一个reset事件,在之后的fetch操作中传递{reset: true}。
- LINE42~45: 从Collection从遍历Model,传给GistRow这个View,生成HTML。
Collection是Backbone里功能最多的函数(虽然其中很多是Underscore的),而且只要理解了Model和View的关系,使用Collection不会有任何障碍。给Collection绑定各种事件来实现丰富的交互功能了,以下这段JS代码会加入删除/编辑的操作,可以在JSBIN上查看源代码和执行结果。只是增加了事件,没有什么新内容,所以就不做说明了,附上JSBIN的演示地址:http://jsbin.com/jevisopo/1
JavaScript
var Gist = Backbone.Model.extend(),
Gists = Backbone.Collection.extend({
model: Gist,
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response;
}
}),
gists = new Gists();
var GistRow = Backbone.View.extend({
tagName: 'tr',
render: function (model) {
this.el.id = model.cid;
this.el.innerHTML = '<td>' + model.get('description') + '</td><td>'+ model.get('url') + '</td><td>' + model.get('created_at') + '</td><td><a href="javascript:void(0)" class="js-remove">X</a> <a href="javascript:void(0)" class="js-edit">E</a> </td>'
return this;
}
});
var GistsView = Backbone.View.extend({
el: 'tbody',
collection: gists,
events: {
'click a.js-remove': function (e) {
var cid = e.currentTarget.parentElement.parentElement.id;
gists.get(cid).destroy();
gists.remove(cid);
},
'click a.js-edit': 'editRow',
'blur td[contenteditable]': 'saveRow'
},
editRow: function (e) {
var tr = e.currentTarget.parentElement.parentElement,
i = 0;
while (i < 3) {
tr.children[i].setAttribute('contenteditable', true);
i++;
}
},
saveRow: function (e) {
var tr = e.currentTarget.parentElement,
model = gists.get(tr.id);
model.set({
'description' : tr.children[0].innerText,
'url': tr.children[1].innerText,
'created_at': tr.children[2].innerText
});
model.save();
},
initialize: function () {
var self = this;
_.forEach(['reset', 'remove', 'range'], function (e) {
self.listenTo(self.collection, e, self.render);
});
},
render: function () {
var html = '';
_.forEach(this.collection.models, function (model) {
var tr = new GistRow();
html += tr.render(model).el.outerHTML;
});
this.el.innerHTML = html;
return this;
}
});
var gistsView = new GistsView();
gists.fetch({reset: true});
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/* 替换之前代码的JS部分(LINE16~51) */
var Gist = Backbone.Model.extend(),
Gists = Backbone.Collection.extend({
model: Gist,
url: 'https://api.github.com/gists/public',
parse: function (response) {
return response;
}
}),
gists = new Gists();
var GistRow = Backbone.View.extend({
tagName: 'tr',
render: function (model) {
this.el.id = model.cid;
this.el.innerHTML = '<td>' + model.get('description') + '</td><td>'+ model.get('url') + '</td><td>' + model.get('created_at') + '</td><td><a href="javascript:void(0)" class="js-remove">X</a> <a href="javascript:void(0)" class="js-edit">E</a> </td>'
return this;
}
});
var GistsView = Backbone.View.extend({
el: 'tbody',
collection: gists,
events: {
'click a.js-remove': function (e) {
var cid = e.currentTarget.parentElement.parentElement.id;
gists.get(cid).destroy();
gists.remove(cid);
},
'click a.js-edit': 'editRow',
'blur td[contenteditable]': 'saveRow'
},
editRow: function (e) {
var tr = e.currentTarget.parentElement.parentElement,
i = 0;
while (i < 3) {
tr.children[i].setAttribute('contenteditable', true);
i++;
}
},
saveRow: function (e) {
var tr = e.currentTarget.parentElement,
model = gists.get(tr.id);
model.set({
'description' : tr.children[0].innerText,
'url': tr.children[1].innerText,
'created_at': tr.children[2].innerText
});
model.save();
},
initialize: function () {
var self = this;
_.forEach(['reset', 'remove', 'range'], function (e) {
self.listenTo(self.collection, e, self.render);
});
},
render: function () {
var html = '';
_.forEach(this.collection.models, function (model) {
var tr = new GistRow();
html += tr.render(model).el.outerHTML;
});
this.el.innerHTML = html;
return this;
}
});
var gistsView = new GistsView();
gists.fetch({reset: true});
|
Afterword
虽然是入门范例,但因为篇幅有限,有些基本语言特征和Backbone的功能不可能面面俱到,如果还看不懂肯定是我漏掉了需要解释的点,请(在Google之后)评论或是邮件告知。
Backbone不是jQuery插件,引入以后整个DOM立即实现增删改查了,也做不到KnockoutJS/AnglarJS那样,在DOM上做数据绑定就自动完成逻辑。它是将一些前端工作处理得更好更规范,如果学习前端MVC的目的是想轻松完成工作,Backbone可能不是最佳选择。如果有一个项目,100多行HTML和1000多行JS,JS主要都在操作页面DOM,那就可以考虑用Backbone来重写了。它比其他庞大的MVC框架要容易掌握得多,作为入门学习也是非常不错的。
[转]Backbone.js简单入门范例的更多相关文章
- EChart.js 简单入门
EChart.js 简单入门 最近有一个统计的项目要做,在前端的数据需要用图表的形式展示.网上搜索了一下,发现有几种统计图库. MSChart 这个是Visual Studio里的自带控件,使用比 ...
- JS简单入门教程
JS简单教程 使用方法:放到任意html页面的head标签下 Test1方法弹出当前时间对话框 Test2方法for循环输出 Test3方法for(…in…)输出数组内容 <script typ ...
- angular.js简单入门。
小弟刚接触angular js 就写了一个简单的入门.后续慢慢补... 首先看 html 页面. <html> <meta charset="UTF-8"> ...
- 98、vue.js简单入门
本篇导航: 介绍与安装 vue常用指令 一.介绍与安装 vue是一套构建用户界面的JAVASCRIPT框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层, ...
- anime.js 简单入门教程
anime.js是一个强大的用来制作动画的javascript库,虽然功能没有GASP(greensock)强大,但胜在它足够轻便,gzip压缩完只有9kb左右,麻雀虽小,却五脏俱全. 下面就来看看如 ...
- 13、vue.js简单入门
本篇导航: 介绍与安装 vue常用指令 一.介绍与安装 vue是一套构建用户界面的JAVASCRIPT框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层, ...
- template.js简单入门
template.js是一款开源的JavaScript模板引擎,用来渲染页面的. github地址 https://github.com/yanhaijing/template.js 下载templa ...
- Vue.js简单入门
这篇文章我们将学习vue.js的基础语法,对于大家学习vue.js具有一定的参考借鉴价值,有需要的朋友们下面来一起看看. Vue.js是一个数据驱动的web界面库.Vue.js只聚焦于视图层,可以很容 ...
- JS简单入门
------------恢复内容开始------------ JavaScript,可以减少网页的规模,提高网页的浏览速度,丰富页面的表现和功能 HTML是进行基本结构的创建的,比如说表格和表单等, ...
随机推荐
- 轻松掌握:JavaScript状态模式
状态模式 状态模式(State)允许一个对象在其内部状态改变的时候改变它的行为,对象看起来似乎修改了它的类. 状态模式的使用场景也特别明确,有如下两点: 一个对象的行为取决于它的状态,并且它必须在运行 ...
- JavaScript学习笔记-函数
函数的两种创建方式:函数定义表达式.函数声明语句 编译时,函数声明语句创建的函数会‘被提前’至外部函数的作用域顶部,在该作用域内可以被随意调用: 而函数表达式创建的函数,要调用它必须赋值给一个变量,编 ...
- python任务执行之线程,进程,与协程
一.线程 线程为程序中执行任务的最小单元,由Threading模块提供了相关操作,线程适合于IO操作密集的情况下使用 #!/usr/bin/env python # -*- coding:utf-8 ...
- IOS5中的Safari不兼容Javascript中的Date问题,做下笔录吧!奶奶的,折腾我半天!
在做Mobile终端的Website开发中,我遇到一个很懊恼的问题. 在IOS5以上版本(不包含IOS5)中的Safari浏览器能正确解释出Javascript中的 new Date('2013-10 ...
- ArcGIS Desktop 遇到严重的应用程序错误
由于项目初验,忙了几个月(感觉忙得并不值),好久都没更新博客了. 一.问题 在关闭ArcMap时,ArcGIS Desktop 遇到严重的应用程序错误.环境是Windows 10,新装的系统.以前出现 ...
- SharePoint 2013 重命名网站集名称(SharePoint 2013 rename site collection)
最近使用SharePoint中,遇到一个需要重命名网站集的需求,主要是网站用数据库备份/还原的方式,想要改网站集的地址,然后搜了一下PowerShell: $site = Get-SPSite -Id ...
- linux集群运维工具:pssh
由于需要安装hadoop集群,有10台机器需要安装,一开始打算用SCP复制,后来觉得不可接受(实际现场可能数倍的机器集群,就是10台也不想干).后来在网上找了,发现了clustershell和pssh ...
- Get item by sharepoint web service jquery
对于sp2010,在ie浏览器中这个代码无法生效,只有chrome可以生效. //获取附件id function GetAttachments(listName) { var soapEnv = '& ...
- iOS关于启动页自定义特殊处理
平常开发中对于启动页可能会有一些特别的要求,比如在启动页加动画或加一些按键可以响应事件等,最近项目中要在启动页增加版本号,因为版本号是不断的改变,所以要动态实现把它加到启动页上:在XCode上面配置的 ...
- 【代码笔记】iOS-拍照动画
代码: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. se ...