欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

宁皓网 Backbone 基础 有大用 有大大用

为应用提供一个骨架。

来自 https://ninghao.net/course/1444#toc

1)介绍

Backbone 是一套非常优秀的类库,可以用在开发前端应用程序上面。它为应用程序提供了一个骨架,也就是它提供了一个很好的结构,可以让我们的应用程度更容易维护和管理。

这个课程我们会去介绍 Backbone 里的几个很重要的概念 ,怎么样去创建模型,设置模型的属性,监听模型相关的事件。怎么样把模型添加到集合里面。去为模型创建视图,再把渲染之后的模型放到集合的视图里面。

再了解下什么是路由器。

最后我们会用 Backbone 跟服务端的应用相互沟通,去从服务端那里提取数据,创建,更新,还有删除数据。

来自 https://ninghao.net/video/1445#info

2)准备

在这个课程的资料里,你可以找到一个 starter 目录 ... 你可以使用这个目录里的东西,跟课程一步一步去学习 Backbone ...

这个目录的根目录下面,有一个 index.html ... 这就是应用的首页 ...

在这个文档里面,已经嵌入了 Backbone 应用需要用到的一些东西 .. Backbone 唯一依赖的,是这个 underscore ... 其它的东西都是可选的 ..

app.js 这里可以存入应用程序需要的一些代码 ... 为了演示方法,我们会把所有需要的代码都放到这一个文件里面 ... 在创建真正的应用程序的时候,你可以需要想办法按照功能,把代码分割成几个部分 ...

我在演示的时候,也没有在代码里面,使用命名空间的概念 ... 所有的变量都是在全局环境下面定义的 .. 你在创建真正应用的时候,最好把代码封闭到一两个对象里面。尽量减少在全局环境下面的变量 ...

另外,在这个课程里,我经常会用到浏览器的控制台,你可以使用 Chrome 浏览器 ..

来自  https://ninghao.net/video/1446#info

模型

3)模型 - Model

创建一个模型,也就是创建一个 model ,可以使用 Backbone Model 的 extend 方法。比如我们要做一个记笔记的应用,可能会有的模型就是笔记这个模型,可以使用英文 note 来表示笔记 ...

var Note ,一般这个名字的首字母都是使用大写的,等于 ... Backbone.Model.extend({});

var Note = Backbone.Model.extend({});

这个 Note 就有点像是一个 class ,也就是一个类 ... 它里面已经有了一些定义好的属性还有方法 ... 因为它继承了 Backbone 的 Model ...

在这个 extend 方法里面,我们可以去添加一些属性和方法 ... 这些属性和方法就是基于 Note 这个类创建的对象所拥有的属性和方法 ...

我们可以先去看一下 .. 打开浏览器 ... 用浏览器打开应用的首页 ... 这里我用的是 Chrome ... 再打开它的开发者工具 ... alt + command + J

在这里,我们先去试试,创建一个 note 对象 ... var note1 ... 这个对象的名字叫 note1 ... 等于 new Note() ... 它就是刚才我们创建的那个类 ...

var note1 = new Note;

这个动作就是去实例化一下这个 Note 类 ... 这里的 note1 就是 Note 类的一个实例,或者叫 Note 类的一个对象 ...

再输入 note1 .. 回车 ..

这里会显示目前 note1 这个对象拥有的一些属性还有方法 ... _changing ... 现在它的值是 false .. _pending ... 它的值也是 false ...

这里还有一个 attributes 属性 ... 目前它里面啥也没有 ...

我们给对象添加的属性,都会包含在这个 attributes 属性里面 ... 下面,可以再去试一下给对象添加一些属性 ...

再去创建一个 Note 对象 .... var note2 等于 new Note ... 这里我们在实例化 Note 类的时候,可以给它一些属性 ...

输入一组括号 .. 里面是一个对象 ... 用一组花括号 ... 然后再去定义属性还有对象的值 ... 在笔记里面,可能有的属性,比如标题,内容,作者,创建和修改的日期等等 ... 先添加一个标题属性 ... 可以叫做 title ... 冒号 ... 然后是这个属性对应的值 ... 西红柿炒鸡蛋的做法 ... 再输入一个逗号分隔一下 ... 继续去添加其它的属性 ... created_at ... 用它来表示笔记的创建的日期 ... 它的值可以实例化一下 JavaScript 的 Date 对象 ... 默认它会返回当前的日期和时间 ...

var note2 = new Note({title: '西红柿炒鸡蛋的做法', created_at: new Date()})

再看一下这个 note2 对象 ... 打开它 ... 再打开它的 attributes 属性 ..

你会看到这里会有两个属性 ... created_at ... 表示笔记的创建的日期 ... 另外还有一个 title 属性,它的值就是我们在创建这个对象的时候设置的,西红柿炒鸡蛋的做法。

来自 https://ninghao.net/video/1447#info

4)获取,添加,删除,清空属性

想得到对象里面的属性,可以访问对象的 attributes 属性 ...

note2.attributes

得到的是一个对象,里面就是这个 note2 对象的属性 ... 或者,我们也可以使用 toJSON() 这个方法 ...

note2.toJSON()

返回的结果也是一个对象 ...

要把这个对象的属性转换成 JSON 的形式... 可以把这个对象交给 JSON.stringify 去处理一下 ...

JSON.stringify(note2)

判断这个对象是否有指定的属性,可以使用 has 方法 ... 我们看一下 note2 这个对象有没有 title 这个属性 ...

note2.has('title')

返回的结果是 true ,表示有这个属性 ... get 这个方法可以得到某个属性的值。比如要得到 title 这个属性的值,可以这样 ..

note2.get('title')

结果就是 西红柿炒鸡蛋的作法 ...

删除某个属性,用的是 unset 方法 ... 要删掉 title 这个属性,可以这样做 ..

note2.unset('title')

再去判断一下有没有 title 这个属性 ...

note2.has('title')

结果是 false .... 因为前面,我们用了 unset 方法,把 title 这个属性从 note2 这个对象里面删除掉了 ...

再给这个对象去添加属性,可以使用 set 方法 ... 比如再去添加一个 title 属性 ..

(#command + K,清空屏幕)
note2.set('title', '西红柿炒鸡蛋的做法')

再去访问一下这个属性 ...

note2.get('title')

会得到它的值 ...

设置多个属性,可以给 set 方法传递一下对象 ... 比如再去添加一个 author 作者属性,还有一个 location ,表示笔记记录位置的属性 ...

note2.set({author: '王皓', location: '济南'})

再查看一下 note2 的所有的属性 ...

note2.attributes

在这里,你会看到之前添加的 title ,还有 created_at 属性,还有刚才用 set 添加的 author 和 location 这两个属性 ...

清空对象的属性,用的是 clear 方法

note2.clear()

再查看一下对象的属性 ...

note2.attributes

这次会返回一个空白的对象 ... 因为 note2 的所有的属性,已经用 clear 这个方法清空了 ...

来自  https://ninghao.net/video/1448#info

5)默认值 - defaults


在定义模型的时候,我们可以去设置一下模型的 defaults 属性,去给模型添加一些默认的属性,还有对应的这些属性默认的值 ... 这样在创建模型的实例以后,这个实例就会拥有这些默认的属性了。下面,我们一起去看一下 ...

在这个 Note 模型里面 ... 添加一个 defaults 属性 ... 它的值是一个对象 ...

defaults: {}

在这里面,可以添加一个笔记的标题属性 .. title ... 它的值默认是个空白的字符串 ...

再添加一个表示笔记创建的时间的属性 ... created_at ... 这个属性默认的值可以是当前的时间 ...

defaults{
title: '',
created_at: new Date()
}

保存 ... 回到浏览器 ... 打开应用的首页 ... 刷新一下 ... 然后在控制台上,我们可以去创建一个 Note 对象的实例 ...

var note = new Note

再查看一下 note 这个对象 ...

打开它的 attributes 属性 ... 虽然在创建这个 note 对象的时候,我们并没有去给它指定属性 ... 不过在 Note 这个模型里面,添加了一些默认的属性 ... 所以,创建的对象,就会拥有这些默认的属性...

这里你会看到 title ,还有 created_at 这两个默认的属性 ... 这些属性的值,可以在创建这个对象的时候覆盖掉 ...

来自  https://ninghao.net/video/1449#info


6)初始化 - initialize

基于这个模型创建了一个实例以后,会去调用模型里面的 initialize 这个方法 ... 在这个方法里,你可以去做一些事情 ... 比如去监听属性的变化事件什么的 ...

回到编辑器 ... 在这个 Note 模型里面 ... 再去定义这个 initialize 方法 ... 这里我们先只是简单的在控制器上输出一点文字 ...

initialize: function() {
console.log('新创建了一条笔记 :' + this.get('title'));
}

这里的 this 这个关键词,表示的就是被创建的这个对象,或者说被实例化的这个对象 ... this.get('title'),可以输出被创建的对象的标题属性的值 ...

保存 ... 回到浏览器 ... 先刷新一下 ..

然后,在控制台上,去创建一个 Note 类的实例 ...

var note = new Note({title: '西红柿炒鸡蛋的做法'})

在创建了这个对象以后,就会去调用 initialize 方法 ... 在这个方法里,我们暂时只是让它在控制器上输出一点文字 ... 这里就是 新创建了一条笔记 :西红柿炒鸡蛋的做法。

来自  https://ninghao.net/video/1450#toc

7)属性值变化发生的事件 - change

当我们使用 set 方法,去给对象设置属性的时候,如果新设置的属性的值照原来的值发生了改变,就会在这个模型上面触发一个 change 事件... 同时也会在这个特定的发生变化的属性上面触发一个 change 事件 ... 这个事件的名字可以使用 change 后面加上冒号,再加上这个属性的名字来表示。比如,如果 title 的值发生了变化,就会触发一个 change 事件,还会触发一个 change:title 的事件。

下面,我们可以利用这个变化的事件去做点事 ...

在这个模型的初始化方法里面,可以使用 on ,去监听这个 change 事件 ... 用 this 关键词,可以表示当前的这个模型的对象 ... on 方法的第一个参数是要监听的事件的名字 ... 这里就是 change ... 第二个参数是处理这个事件要执行的函数 ..

这里我们用一个匿名函数 ... 它可以接受两个参数 ... 模型对象,还有选项 ... 用 model 表示当前的对象 ... 用 options 表示选项 ...

发生 change 事件,要做的事就是在控制台上,输出一点文字 ...

// 处理属性值改变以后发生的 change 事件
this.on('change', function(model, options) {
console.log('属性的值发生了变化');
});

下面,我们可以再去监听一下改变标题属性的值的时候发生的改变事件 ..

这里要监听的事件是 change:title ... 事件发生以后,同样在控制台上输出点东西 ...

this.on('change:title', function(model, options) {
console.log('标题属性的值发生了变化');
});

保存 ... 下面到浏览器上去试试 ... 新建一个模型对象 .. 再去设置一下它的 title 属性的值 ..

var note = new Note
note.set('title', 'Hello')

回车 ... 在控制台上,会显示 ...

标题属性的值发生了变化 还有 属性的值发生了变化 这两条信息 ... 模型里的属性的值发生了变化 ... 会触发 change 事件 ... 同时,也会触发 change:title 事件,因为 title 这个属性的值也发生了变化 ...

再打开这个对象看一下 ...

这里有一个 changed 属性 ... 打开看一下 ... 这个属性里面的东西就是发生变化的属性,还有对应的值 ...

再设置一下同样的值 ....

因为要设置的 title 属性的值跟当前对象里面的 title 属性的值没有变化 ... 也就不会去触发 change 事件。

来自  https://ninghao.net/video/1451#info

8)验证属性的值 - validate

在用 set,或者 save 方法,去设置属性的值,还有把模型保存到数据库之前,都可以先去验证一下属性的值,验证通过以后,才能去执行这些动作,不然的话,就会返回一个 false ,还有一条事先设置好的错误信息。

这个验证的功能,是通过模型的 validate 方法来做的。

下面,我们去给 Note 这个模型里的 title 属性,去添加一个验证 .. 要求设置的标题属性字符数必须要大于 3。

在 Note 模型里面,去添加一个 validate 这个方法 ... 这接受两个参数 ... 一个是对象的属性,还有一个是选项参数 ... 属性可以用 attributes 来表示 ... 选项可以使用 options ...

然后在这个方法里,用 if 语句,去判断一下 ... 判断的条件是对象的 title 属性这个字符串的长度不能小于 3 ...

attributes.title 可以得到 title 这个属性 ... 后面再加上一个点 length ,可以得到这个字符串的长度 ... 小于 3 。意思就是,如果对象的标题属性的字符串长度小于3,这会验证失败 ...

validate: function(attributes, options) {
if (attributes.title.length < 3) {
return '笔记的标题字符数要大于 3';
}
}

下面,我们去试一下 ... 打开浏览器 ... 先新建一个 note 对象 ... 然后再用 set 方法,去设置一下 note 对象的 title 属性 ... 把属性的值设置一个长度小于 3 的值 ... hi ... 然后再给这个方法传递一个选项参数 ... 在这里,把 validate 这个属性设置成 true ... 表示要使用验证的功能 ...

var note = new Note
note.set('title', 'hi', {validate:true})

回车 ... 在控制台上,会返回一个 false .. 表示验证没有通过,因为给 title 属性设置的值的长度小于 3 ...

再去查看一下这个 note 对象 ... 打开它的 attributes 属性 ... 这里它的 title 属性的值仍然是默认的值 ...

注意在这个对象里面,validationError 这个属性里面,会包含验证失败以后的这条错误的信息。

下面,我们可以重新再去给 title 设置一下值 ... 设置成 hello ...

这回验证就会通过了 ... 因为 hello 的长度大于 3 ... 打开这个返回来的对象 ... attributes .. 在这里, title 的值,已经设置成了 hello ...

来自  https://ninghao.net/video/1452#info


9)利用验证失败后的事件 - invalid

在验证失败以后,会触发一个 invalid 事件,我们可以去监听这个事件,在它发生以后,去做一些事情,比如显示一条错误的提醒信息。

在 validate 属性里面设置的验证条件,用 return ,返回来的东西,就是验证失败以后返回来的错误信息。下面,我们可以把这里设置的这条错误信息显示到控制台上看一下。

在模型被初始化以后,可以去监听一下这个 invalid 事件 ... 在 initialize 这里,使用 on 这个方法去监听事件 ... this 表示的就是被实例化的对象 ... 在 on 这个方法里,先指定一下要监听的事件的名字 ... 这里就是 invalid 事件 ...

这个事件发生以后,会去执行一个函数,可以在这个方法的第二个参数里,去指定一下处理这个事件的函数 ... 这里我们用一个匿名函数 ...

函数可以授受两个参数,model 对象,还有 error 错误信息 ...

在里面,用一个 console.log,把这个 error ,错误信息显示到控制台上 ...

//处理验证失败以后发生的 invalid 事件

this.on('invalid', function(model, error) {
console.log(error);
});

保存 ... 回到浏览器上去试一下 ...

先新建一个对象 ... var note = new Note

设置一下它的 title 属性 ... 设置成 hi ... 然后指定一下要使用验证 ...

note.set('title', 'hi', {validate: true})

回车 ... 验证失败,因为要给 title 属性设置的值的长度小于 3 ,所以就会发生一个 invalid 事件,在创建这个 note 对象的时候,我们已经监听了这个事件 ... 这个事件发生以后,就在控制台上,显示验证失败返回来的错误信息。

这里就是 笔记的标题字符数要大于 3 ...

来自  https://ninghao.net/video/1453#info

视图

10)视图 - View

在 Backbone 里面的视图,一般不会包含应用程序上用到的 HTML 标签。它其实是把模型里面的数据展示给用户的一套逻辑。在视图里,经常会使用 JavaScript 的模板去组织在模型里面的数据。比如我们可以 Underscore 的 模板功能,或者 Mustache 等等。

视图里面的 render() 方法,可以跟模型的 change 事件绑定到一块,这样模型一旦发生了变化,视图就会立即做出响应,而且不需要重新刷新整个页面。

创建

下面,我们可以先去创建一个视图。var NoteView ,要创建的视图的名字叫做 NoteView ... 让它等于 Backbone的 View 的 extend() 方法 ...

这样我们就创建好了一个视图,叫做 NoteView ...

el

在视图里面有一个很重要的属性,叫做 el ,每个视图都得有这个属性 ... 它实际上就是一个 DOM 元素, 视图要用它来组织内容,然后一块儿插入到 DOM 里面。默认这个 el 属性的值,是一个 div 标签 ...

下面,我们可以去看一下 ...

保存 ... 回到浏览器 ... 打开控制台 ...

先新建一个视图的实例 ...

var noteView = new NoteView

然后查看一下它的 el 属性 ...

noteView.el

返回的结果是一组 div 标签 ...

在定义视图的时候,我们可以去修改这个元素的名字 ... 回到编辑器 ...

比如我们要用一个 li 元素 ... 在这个视图里面,设置一下 tagName 属性 ... 它的值就是 el 属性要用到的元素的名字 ...

tagName: 'li'

如果想在这个元素上面添加一些属性,可以再设置一下 attributes 属性,或者如果只想设置在这个元素上的 class 属性或者 id 属性,可以直接使用 className ,还有 id ...

className: 'item'

这样每个 li 元素上面,都会有一个 class 属性,属性的值就是 item ... 如果要设置 id 的属性的话,可以在下面再去定义一个 id 这个属性,还有对应的值 ...

或者还想添加一些其它的属性,可以设置一下 attributes 属性 ... 这个属性的值是一个对象 ... 在这里面,添加一个叫做 data-role 的属性 ... 属性的值,可以设置成 list ... 注意这个 data-role 这个名字中间有个小横线,所以,它的周围需要用一组引号 ...

attributes: {
'date-role': 'list'
}

保存 ... 回到浏览器 ...

新建一个视图的实例 ... 然后再去查看一下 el 属性 ...

var noteView = new NoteView
noteView.el

你会发现,这个 el 属性的值就是我们刚才设置的那个 ... 元素的名字是 li ,并且在上面,会有一个 data-role 的属性,值是 list ,还有一个 class 属性,值是 item ...

来自  https://ninghao.net/video/1454#info

11)渲染视图 - render

视图里面都有一个 render 方法,我们可以使用这个方法去组织一下在模型里面的内容。

先去新建一个模型 ... var note = new Note ... 设置一下它的标题属性 ...

var note = new Note({
title: '西红柿炒鸡蛋的作法'
});

然后再去创建一个 NoteView 这个视图的实例 ... var noteView 等于 new NoteView ... 在创建的时候,可以告诉一下这个视图要用到的模型是哪个 ... 设置一下 model 属性 ... 它的值,就是在上面我们创建的这个 note 对象 ...

var noteView = new NoteView({model: note});

在这个视图里面,我们可以访问到模型里面的属性,比如标题属性,创建日期的属性等等 ...

想利用这些属性,需要在视图里面,再去定义一个 render 方法 ...

render: function() {
this.$el.html(this.model.get('title'));
}

在这个方法里面,可以设置一下在 el 属性里面设置的那个元素里面包含的内容 ... 现在这个元素的标签是 li ... 上面有一个 item 的类,还有一个 data-role 的属性。

在这个 li 元素里面的内容,就是来自 note 模型里面的属性的值 ...

先用一个 this ... 表示当前这个视图 ... 调用它的 $el ,这个 $el 会返回一个用 el 元素的 jQuery 的对象,这样我们就可以继续去使用 jQuery 的其它的方法,去处理这个 el 元素。

比如,去设置一下这个元素里面的内容 ...

关于 jQuery 的使用方法,可以参考宁皓网的《 jQuery 基础教程》

这里,我们用一个 html 方法,去设置一下这个 el 属性的元素里面的内容 ... 用一个 this.model ,表示当前视图对象的模型 ... 这个模型就是在实例化这个视图的时候,传递进来的那个 ...

然后用 get 方法,可以得到模型里面的属性的值 ... 比如我们要得到 note 模型里的 title 属性 ... 输入 title ...

测试

下面,我们可以去试一下 ...

回到浏览器 ...

先去调用一个视图里面的这个 render 方法 ... 让它去组织一下模型里的数据 ...

noteView.render()

然后再访问一下视图里的 el 属性的值 ...

noteView.el

因为我们在视图里面定义了 render 方法,去组织在模型里面的内容 .... 所以,这里你会发现,在 li 元素里面,会包含在 note 模型里面的 title 属性的值 ...

来自  https://ninghao.net/video/1455#info

12)模板 - template

目前我们直接是在 render 方法里面去组织模型内容的结构 .. 如果需要用到模型的很多个属性的话,这里会变得越来越混乱 .. 所以,我们可以使用模板。

这个视频,我们去给视图准备一个模板。JavaScript 模板的功能并不是 Backbone 提供的,你可以使用第三方提供的模板功能,比如 Mustache ,Handlebars ,或者 Underscore 的模板功能。

这里我们使用 Underscore 的模板功能,去给这个 NoteView 视图准备一个模板。

打开 index.html ... 可以在这个页面的任何的地方去定义这个模板 ...

输入一组 script 标签 ... 然后设置一下它的 type 属性 ... 一般可以设置成 text/template,这样浏览器就不会把它当成是 JavaScript 去处理了。 ... 然后在上面,再去定义一个 id ... 这个 id 就是这个模板的名字..

<script type="text/template" id="list-template"> </script>

在这组 script 标签里面,就是模板的具体的形式 ... 因为我们要用的是 Underscroe 的模板功能。所以,可以使用这样的形式来输出模型里的属性的值 ... 小于号百分号,加上一个等于号 ... 空格 ... 然后是属性的名字 ... 结束的地方,再输入一个百分号加上一个大于号 ...

<%= title %>

这小段代码会输出模型里面的 title 这个属性的值 ... 也就是,可以使用它来表示模型里面的 title 属性 ...

在它的周围,可以加上一组 span 标签 ...

在它后面,再加上一组 small 标签 ,在这个标签上,再加上一个 css 类 .. 设置一下它的 class 属性,值是 pull-right ,这个类可以让元素靠右去显示 ... 里面的内容可以是 Note 模型的 created_at 这个属性 ...

使用这种形式,你可以去组织模型里面的内容的展示形式

保存一下 ...

回到 app.js ...

在这个视图里面,去设置一下 template 这个属性 ... 然后用 Underscore 的 template 方法,指定一下要使用的模板 ...

找到页面上的 id 叫是 list-template 的元素 ... 然后得到它里面的内容 ...

template: _.template(jQuery('#list-template').html()),

再去改造一下 render 方法 ... 去掉 html 这个方法里面的这行代码 ... 然后用 this.template,表示当前这个视图的 template 方法 ...

再把模型里面的属性交给这个 template 方法 ... 模型里的属性是在 this.model ,也就是当前这个视图的 model 下面的 attributes 这个属性里面 ...

this.$el.html(this.template(this.model.attributes));

演示

下面再到浏览器上试试 ...

先调用一个视图的 render() 方法 ...

noteView.render()

然后再去访问一下这个视图里的 el 属性 ...

noteView.el

你会看到,这里面的内容,会按照我们在模板里面设置的形式展示出来 ... 标题周围有一组 span 标签 ... 创建的日期的周围有一组 small 标签 .. 上面有一个类,是 pull-right ...

来自  https://ninghao.net/video/1456#info

集合

13)集合 - Collection

Collection ,中文可以翻译成集合,在 Backbone 里面,集合就是一些模型的组合。比如在我们的这个笔记应用里,单个的笔记可以用模型来表示,把多个笔记组合在一起,就是一个集合了。

下面,我们可以去给 Note 这个模型,去创建一个集合。

这个集合可以叫做 NoteCollection ... 让它去继承 Backbone 的 Collection ...

var NoteCollection = Backbone.Collection.extend({})

在这个集合里,可以设置一下 model 属性 .. 去指定一个跟这个集合相关的模型。这里我们设置成 Note ...

model: Note

在下面,我们去创建几个模型 ... var note1 等于 new Note ... 设置一下模型里的属性 ... 这里我们可以添加一个 id 属性,这个属性的值可以标示模型的唯一性。

在集合里面,使用这个 id ,我们可以得到对应的模型。

var note1 = new Note({id: 1, title: '西红柿炒鸡蛋的作法'});
var note2 = new Note({id: 2, title: '周六参加朋友的婚礼'});
var note3 = new Note({id: 3, title: '晚上回家洗尿布'});

这里我们创建了三个模型,note1,note2,还有 note3 ... 保存一下 ..

然后回到浏览器 ...

打开控制台 ... 然后去新建一个集合的实例 .. var noteCollection .. 这个集合可以叫做 noteCollection ...

var noteCollection = new NoteCollection

再看一下这个集合 ...

noteCollection

现在这个集合里是空的 ... length 属性的值是 0 ... models 里面,也没有东西 ...

添加模型

在创建集合的时候,我们就可以给这个集合里面添加一些模型 ... 刷新一下 ...

两重新去创建这个集合 ... 这次,给它一个数组 参数 ... 这个数组就是要包含在这个集合里的模型 ... 之前我们已经创建了几个模型 ... note1, note2 ,还有 note3 ...

我们先把 note1 还有 note2 这两个模型放到这个集合里面 ...

var noteCollection = new NoteCollection([note1, note2])

回车 .. 再看一下这个集合 ...

noteCollection

你会发现,length 属性的值是 2 ,表示这个集合里面有两个模型 ... 在 models 属性里面,会包含这两个模型 ...

来自  https://ninghao.net/video/1457#info


14)添加模型到集合里

除了在创建集合的时候,可以为集合指定一些模型,我们也可以在创建集合以后,继续去为集合添加新的模型进去。我们可以使用 add 这个方法。

下面,我们先去创建一个空白的集合 ...

var noteCollection = new NoteCollection

再看一下 ...

noteCollection

length 属性的值是 0 ,表示这个集合里面还没有包含模型。下面,我们用 add 方法去添加一个模型到这个集合里面。

noteCollection.add(note1)

这样,会把创建的 note1 这个模型添加到这个集合里面。再查看一下 ... noteCollection ... 现在,这里已经有了一个模型 ... 就是刚刚添加的那个 note1 这个模型 ...

使用 add 方法,也可以同时把多个模型添加到集合里面。 需要给 add 方法传递一个数组参数 ... 这个数组里的项目就是要添加到集合里面的模型 ...

noteCollection.add([note2, note3])

这样会把 note2 还有 note3 添加到 noteCollection 这个集合里面。可以再确认一下 ... noteCollection ...

显示这个集合里面,现在有三个模型 ...

(# 清屏幕 command + K)

merge

如果要添加的模型在集合里面已经存在了,默认,会跳过去,不过,我们也可以给 add 方法添加一个选项参数,把 merge 设置成 true ,这样要添加的模型会跟已有的模型合并到一块儿 ...

使用 noteCollection 的 add 方法 ... 这个方法可以添加已有的模型 .. 或者也可以直接在这里指定模型的属性,去创建一个新的模型 ... 然后添加到这个集合里面 ... 因为在定义这个集合的时候已经指定了跟这个集合相对应的模型是 Note ... 所以,在这里新添加的模型自动就会是一个 Note 类型的模型。

noteCollection.add({id:1, title: '今天天气不错'})

在这里,我们设置一下模型的 id 属性为 1 ,这个 id 为 1 的模型已经在这个集合里面存在了 ... 然后再设置一下 title 标题...

按下回车 ...

再打开 id 是 1 的这个模型看一下 ... 这里它的 title 属性的值,还是 西红柿炒鸡蛋的做法。并没有变化 ..

下面,我们再给 add 方法添加一个选项参数 ... 设置一下 merge 属性的值为 true ...

noteCollection.add({id:1, title: '今天天气不错'}, {merge: true})

回车 ... 再去看一下 ... 现在,你会看到,在这个集合里面,id 号是 1 的这个模型的标题 ... 就从刚才的 西红柿炒鸡蛋,变成了 今天天气不错 ...

而且这个变化也会影响到原来的这个模型 ... 可以去查看一下这个模型的属性 ... 这个模型应该叫做 note1 ...

note1.attributes

同样,它的 title 属性,也会变成 今天天气不错 ...

来自  https://ninghao.net/video/1458

15)从集合中移除模型 - remove, reset, pop, shift

从集合里面删除掉模型,可以使用 remove 方法,在这个方法里指定要删除的模型就可以了,删掉的可以是一个模型,也可是多个模型,如果是多个模型的话,需要给这个方法传递一下模型的数组作为它的参数。

如果想一下清空集合里面的所有的模型,用的是 reset 方法,这个方法也可以接受一个模型的列表作为它的参数,如果给它指定参数的话,它就会用这个列表里面的模型替换掉原来集合里面的所有的模型。

另外想从集合里面删除掉最后一个模型,可以使用 pop 方法,要删除掉第一个模型,用的是 shift 方法。下面,我们去试一下这些从集合里面删除掉模型的方法。

这里我们先去新建一个集合,让它包含 note1 ,note2,note3 这几个模型 ...

var noteCollection = new NoteCollection([note1, note2, note3])

再查看一下这个集合

noteCollection

现在这里面一共有三个模型 ... 想移除掉指定的模型,可以使用 remove 方法 .. 在这个方法里,指定一下要从集合里面删掉的模型 ...

noteCollection.remove(note1)

这样会从 noteCollection 这个集合里,删除掉 note1 这个模型 ... 这个方法会返回移除模型之后的集合 ... 打开看一下 .. _byId ... 目前这里只有 id 号是 2 还有 3 的这两个模型 .. id 号是 1 的模型已经被删除掉了 ..

reset

下面,我们再去试一下 reset 方法 ... 如果不给这个方法指定参数的话,会清空集合里面的所有的模型 ... 如果指定了模型列表作为它的参数,它会用这个列表替换掉集合里面的所有的模型 ...

现在,这个集合里的模型是 note2 还有 note3 ... 下面,我们用 note1 还有 note2 这两个模型替换掉这个集合里面的现有的两个模型 .. 它的参数是一个数组 ... 在数组里,指定一下要放到集合里面的模型 ... note1 ,还有 note2 ..

noteCollection.reset([note1, note2])

回车 ... 现在,这个集合里面,会用 note1 还有 note2 这两个模型来代替原来的 note2 ,还有 note3 .. 也就是新指定的这个模型的列表,替换掉原来在集合里面的模型。

noteCollection.reset()

如果不给它指定参数的话 ... 它会清空集合里面的所有的模型 ..

pop

刷新一下这个页面 ... 然后再重新创建一个集合 ... 把 note1 ,note2,还有 note3 放到里面 ...

var noteCollection = new NoteCollection([note1, note2, note3])

这次,我们再去试试 pop 还有 shift 方法 ...

想要删除集合里面的最后一个模型,可以使用 pop ...

noteCollection.pop()

不需要给它参数 ... 直接回车 ...

它会返回被它删除掉的模型 ... 打开看一下 ... 注意这个模型的 id 号是3 ,也就是集合里面的最后一个模型 note3 ...

shift

要从集合里删掉第一个模型 ... 可以使用 shift ..

noteCollection.shift()

这个方法也可返回被它删除掉的模型 .. 这个模型的 id 号是 1 ,也就是在 noteCollection 这个集合里面,排在第一位置上的模型 ....

来自  https://ninghao.net/video/1459#info

16)push, unshift,at: index

在往集合里添加模型的时候,我们可以控制模型在集合里面的位置。比如我们可以给 add 方法添加一个 at 选项, 这个选项的值就是模型在集合里面的索引号。

或者,如果只想把模型追加到集合的最后一个位置上,可以使用 push 方法。想要把模型添加到集合的最开始的位置上,可以使用 unshift 方法。

这里我们可以准备一个集合 ... 然后先把 note2 这个模型添加到这个集合里面 ..

var noteCollection = new NoteCollection(note2)

下面,我们可以使用 push 方法,追加一个模型到集合里面 ...

noteCollection.push(note1)

这个方法会返回追加到集合里面的这个模型 .. 再查看一下这个集合 ... noteCollection

打开 models ... 排在最后位置上的这个模型,就是刚才我们使用 push 方法追加到这个集合里的那个 note1 模型 ...

unshift

下面我们再用 unshift 方法,去在集合的最前面添加一个模型 ...

noteCollection.unshift(note3)

方法也会返回这个新添加的模型 ... 再查看一下这个集合 noteCollection

你会看到,索引号是 0 ,也就是排在第一位置上的这个模型 ... 就是刚才用 unshift 方法添加进来的 id 号是 3 的这个模型 ...

at:index

在 add 方法里面,可以指定一个 at 选项参数,它可以决定添加的模型在集合中的索引号 ... 也就是,你可以决定这个模型在集合中出现的位置。

先刷新一下页面 ... 重新再去创建一个模型 .. 这里,我们把 note1 ,还有 note2 这两个模型添加到这个集合里面 ...

var noteCollection = new NoteCollection([note1, note2])

再查看一下 ... noteCollection ... 打开 models 这个属性 ... 现在这里索引号是 0 的笔记模型就是 note1 这个模型 ...

索引号是 1 的这个模型是,note2 这个模型 ...

现在,如果我们想新添加一个模型,让它的索引号是 1 ,也就是让它在 note3 这个模型的位置上 .. 可以这样 ... 使用集合的 add 方法 ... 指定一下要添加的模型 ... note3 ... 然后,给它一个选项参数 ... 这个选项是一个对象,所以要放在一组花括号里面 ... 再设置一下 at 这个选项 ... 它的值,就是要添加的这个模型的索引号 ... 这里,我们设置成 1 ...

noteCollection.add(note3, {at: 1})

回车 ... 再去查看一下这个集合 ... noteCollection ...

打开 models 属性 ... 再打开索引号是 1 的这个模型 ...

你会发现,这个模型就是刚才我们用 add 方法添加进来的 ... 原来这个位置上的模型是 note2 ... 现在,因为我们添加 note3 的时候,手工设置了它的索引号为 1 ,所以,这里就会是这个模型 ...

note2 这个模型的索引号,会往下移一位 ...

也就是,现在索引号是 2 的这个模型,就是 note2 这个模型 ...

来自  https://ninghao.net/video/1460

17)事件 - add, remove, change

在添加,删除,重置,更新,排序集合里面的模型的时候,都会触发相应的事件。我们可以在集合的 initialize 方法里面,去监听这些事件,当发生这些事件的时候,去做一些事情。下面,我们来看几个跟集合相关的事件。

在这个集合里面,先添加一个 initialize 方法 ...

然后,使用 on 方法,去监听这些事件... this.on ,表示为当前的这个集合对象去监听事件 ... 可以分别去监听这些事件 ... 也可以这样 ... 给这个 on 方法一个对象 ...

对象里的东西就是要监听的事件,还有处理这个事件用到的方法 ...

this.on({})

先去监听一下 add 事件 ... 在添加新的模型到集合里的时候,会触发这个事件 ... 处理这个事件的函数可以接受三个参数,第一个参数是被添加的模型,第二个参数是集合,第三个参数是一个选项 ...

这个事情发生的时候,可以在管制台上输出点文字 ... 这里的 model.id 可以输出被添加的模型的 id 号 ...

'add': function(model, collection, options) {
console.log('ID: ' + model.id + ' 模型添加到了集合里');
},

用一个逗号分隔一下 .. 然后继续去设置其它要监听的事件 .. 再添加一个 remove 事件 ... 把模型从集合里移除掉的时候,会触发这个事件。

处理这个事件的函数同样授受三个参数 ... 模型,集合,还有选项 ... 发生这个事件的时候,也在控制台上输出点文字 ...

'remove': function(model, collection, options) {
console.log('ID: ' + model.id + ' 模型从集合里删除掉了');
},

最后,我们再去监听一个 change 事件 ... 当集合里面的模型发生变化的时候,比如更改了某个模型里的属性的值,就会在这个集合上触发一个 change 事件 ...

处理这个事件的函数接受两个参数,model ,还有 options ... 发生这个事件的时候,在控制台上显示 集合里的模型发生了变化 ...

演示

保存 ... 再去浏览器上试试这些事件 ... 打开控制台 ... 然后新建一个空白的集合 ...

var noteCollection = new NoteCollection()

再用 add 方法去给它添加几个模型 ...

noteCollection.add([note1, note2, note3])

添加模型到集合里,会触发 add 事件,所以在控制台上,会显示,添加了这些模型的提示信息。

再试一下移动模型发生的事件 ..

noteCollection.remove([note2, note3])

移除的时候会发生 remove 事件,在控制台上也会出现提示 ...

最后再试一下 change 事件 ... 我们可以去修改一下在集合里的 note1 这个模型的标题 ... 使用 add 方法 ..

要修改的模型的 id 是 1 ,再设置一下新的标题 ... 然后再把 merge 参数设置成 true

noteCollection.add({id: 1, title: '今天天气不错'}, {merge: true})

回车 ...

因为我们在定义 Note 这个模型的时候,也监听了一些事件 ... 所以在这里会显示一些提示 ...

最后这个 集合里的模型发生了变化 ,是我们在集合里监听的 change 事件要显示的提示内容 ...

来自  https://ninghao.net/video/1461#info

18)更聪明的添加模型到集合里的方法 - set


Backbone 的 Collection 相关的方法里面,还有一个 set 方法。这可以更聪明的把模型添加到集合里面。用这个方法,去指定一个模型的列表,在列表里面的模型,如果在原来的集合里面没有的话,就会添加到集合里面,如果在集合里面已经存在了,就会去合并或者叫更新这个模型 ... 如果在原来集合里面的模型不在这个要添加的模型的列表里面,就会从集合里面删除掉这些模型。

不过这些行为,我们也可以使用 set 方法的选项参数去控制。下面,我们去看一下这个 set 方法。

先去创建一个集合 ... 在这个集合里,可以添加一个模型 .. note1

var noteCollection = new NoteCollection([note1])

然后,我们再用 set 这个方法 ... 指定一个模型的列表 ... note1, note2 ...

noteCollection.set([note1, note2])

现在,noteCollection 这个集合里面就是包含 note1 还有 note2 这两个模型 ... 因为 note1 这个模型已经在集合里存在了,所以,会去合并这个模型,相当于是使用 add 方法添加模型的时候,把 merge 选项设置成 true 的作用。

另外的 note2 这个模型,在集合里还不存在,所以,就会把这个模型添加到集合里面。

再试一下 ... 这次这个模型的列表是 note2 ,还有 note3

noteCollection.set([note2, note3])

现在,集合里面已经有了 note2 这个模型,这样就会去合并这个模型 ... 集合里没有 note3 这个模型,所以会把它添加到集合里面 ... 集合里面的 note1 这个模型,并没有在这个 set 方法的模型列表里 ... 这样就会从集合里面,删除掉这个 note1 模型 ...

通过 set 方法的选项参数,我们可以控制它的行为 ... 如果,我们不想从集合里面删除掉在 set 方法的列表里面不存在的模型 .. .这样,可以把 remove 这个选项设置成 false ... 类似的还有 merge 和 add 选项 ..

noteCollection.set([note1], {remove: false})

这回 ... noteCollection 这个集合里面,会包含 note1,note2 ,还有 note3 这几个模型 ...

虽然 note2,还有 note3 ,不包含在用 set 方法指定的模型列表里面,因为我们把 remove 这个选项的值设置成了 false .. 所以,也就不会删除掉这些不包含在模型列表里面的模型了。

来自  https://ninghao.net/video/1462


19)获取在集合里的模型

想要得到在集合里的模型,可以使用 get 还有 at 方法。使用 get 方法,可以指定一下要得到的模型的 id 号,也就是在模型里的 id 属性 ...

如果用 at 方法的话,要指定一下模型在集合里面的索引号。这个索引号就是模型在集合里面的序号,默认情况下,最先添加到集合里面的模型的索引号是 0 ,然后依次往下排 ...

下面,我们还是先去创建一个集合 .. 在给这个集合添加几个模型 ... 最开始是 note2,还有是 note1,最后是 note3 ..

var noteCollection = new NoteCollection([note2, note1, note3])

输入 noteCollection ... 查看一下这个集合 ...

打开这个 _byId 属性 .. .

这里的 1,2,3 ,就是在这个集合里面的模型的 id 号。

再打开 models 这个属性 .. .

这里面有号码是模型的索引号 ... 索引号是 0 的这个模型代表的就是最开始添加到集合里面的模型 ... 也就是 note2 这个模型 ...

索引号是 1 的模型,是 note1 模型 ... 索引号是 2 的模型,就是这具 note3 ...

下面,我们先去试一下 get 方法 ... 这个方法接受的参数,就是模型的 id 属性 ...

noteCollection.get(3)

得到的就是 id 号是 3 的模型 ... 为了更清楚一点,可以在后面加上一个 attributes 属性,得到模型里面的所有的属性 ...

noteCollection.get(3).attributes

你会看到,这个模型的 id 属性的值是 3 ... title 标题是,晚上回家洗尿布 ...

下面,我们再去试一下 at 方法 ... 比如要得到索引号是 1 的模型 ... 这里应该就是 note1 这个模型,因为这个模型是第二个添加到集合里面的 ... 所以,它的索引号应该就是 1 ... 后面再加上 attributes 属性 ... 可以得到模型里面的所有的属性 .. .

noteCollection.at(1).attributes

得到的这个模型的 id 号是 1 ,也就是 note1 这个模型,标题是 西红柿炒鸡蛋的作法 ... 这个模型是第二个被添加到集合里面的 ...

来自  https://ninghao.net/video/1463


20)集合视图

我们可以给集合也准备一个视图,然后把集合里面的每一个渲染之后的模型的视图,都放到这个集合的视图里面。 下面,我们先去新建一个视图 .. 命名为 NoteCollectionView ...

var NoteCollectionView = Backbone.View.extend({})

然后,可以先设置一下视图的 el 属性 ... 默认这个属性的使用的标签是 div ... 这里,我们可以把这个标签设置成 ul ,无序列表标签 ...

tagName: 'ul',

然后我们要做的就是,去把集合里面的每个模型,使用模型的视图渲染一下,然后把它渲染之后的结果,添加到这个集合视图里面。

先去创建一个这个集合视图的实例 ... 可以叫它 noteCollectionView ... 创建的时候,给它指定一下在这个视图里用到的集合 ...

var noteCollectionView = new NoteCollectionView({collection: noteCollection});

在上面,我们再去创建这个集合 ... 在这个集合里,添加几个模型 ... note1, note2, note3

var noteCollection = new NoteCollection([note1, note2, note3]);

再回到定义这个集合视图的地方 ...

设置一下视图的 render 方法 ... 我们要把集合里面的每一个模型都添加到这个集合视图的 el 属性里面 ...

因为在实例化这个视图的时候,已经给它指定了要用到的集合 ... 所以,在这里,我们可以使用 this.collection ,得到这个集合 ...

调用 each 方法,去循环的处理集合里的模型 ... 这是一个在 Underscore 里面带的方法,你可以参考宁皓网的《Underscore 基础教程》去了解更多关于 Underscore 的使用。

在这个方法里,先指定一下处理模型用到的函数 .. this.addOne ... 等会儿,再去定义这个 addOne 方法 ...

然后我们需要把上下文设置成 this ...    //第二个参数this啥意思,假如没有第二个参数this,是不是就是调用collection对象本身的this了,而现在调用的

                         //是NoteCollectionView的this


this.collection.each(this.addOne, this);

在这个 render 方法里,一般最后都要用一个 return this ... 这样我们就可以使用链式调用其它的方法 ...

return this;

在下面,再去定义 addOne ...

这个方法可以接受一个模型参数 ... 可以使用 note 表示 .. 然后,我们要根据集合里的每个模型,去创建一个 Note 视图 ...

var noteView = new NoteView({model: note})

再去调用这个 Note 视图的 render 方法,得到渲染之后的 Note 视图的 el 属性,再把它追加到这个集合视图的 el 里面 ..

this.$el.append(noteView.render().el);

为了可以使用这样的链式调用,我们得去改一下 NoteView 这个视图的 render 方法 ... 在这里,用一个 return this; ...

下面,我们可以再去设置一下这个视图的 initialize 方法 ... 也就是在初始化这个视图的时候,要做的事 ...

可以去监听集合的 add 事件 .. 这样当有新的模型添加到集合里面的时候,再去执行一次这里的 addOne ... 把新的模型渲染以后,再追加到集合视图里面。 最后,在初始化的时候,去执行一下这个视图对象的 render() 方法 ...

initialize: function() {
this.collection.on('add', this.addOne, this);
this.render();
},

保存 ... 打开浏览器 ... 控制台 ... 输入 noteCollectionView.el

得到的结果就是,渲染之后的 note 模型的列表 ... 这个列表会包含在集合视图里面。

我们可以把这个结果添加到页面上 .. 回到应用的首页,添加点 html 元素 ..

div.container>h1.page-header{Collection View}+div#note_list

这里有一组 div 标签 ,上面有一个 note_list 的 id ... 我们可以把渲染之后的集合视图里的内容放到这个元素里面。

再回到控制台 ... 先找到刚才添加的那个 div 元素 .... 可以使用 id 定位到这个的元素 ... 然后使用 html 方法,设置一下它里面的内容 ... 内容就是 noteCollectionView 的 el 属性 ...

jQuery('#note_list').html(noteCollectionView.el)

下面,我们再新建一个模型 ...

var note5 = new Note({id: 5, title: '今天天气不错'})

然后,把它添加到集合里面 ...

noteCollection.add(note5)

在屏幕上显示的模型列表里面,会立即显示出新添加进来的模型 ...

来自  https://ninghao.net/video/1464#info


路由

21)路由 - Router

在应用程序里面,你可能希望用户在访问特定的地址的时候,得到特定的资源,用户可以收藏,分享这些特定资源的地址,而且可以前进或者后退浏览的这些资源。

这就需要我们在应用里面去定义路由。也就是,你事先设计好资源的地址,用户在访问这些地址的时候,应用程序会去执行对应的动作,同时也会发生特定的事件。你可以利用这些动作或者事件,去做一些事情,比如找出正确的资源给用户。

定义路由

下面,我们先去看一下怎么样定义 Backbone 的路由器。

先给要定义的路由器起个名字,这里我们可以叫做 NoteRouter ... Router 就是路由器的意思 ... 然后让它去继承 Backbone 的 Router ..

var NoteRouter = Backbone.Router.extend({});

在这里,可以去设置一下路由器的 routes 属性 ... 属性的值是一个对象 ... 在这个对象里,我们可以去添加应用程序的路由 ... 还有处理这个路由要用到的函数 ... 这里我们先添加一个叫 notes 的路由 ... 处理它的函数可以是 index ... 这些东西都是我们自己定义的名字 ...

routes: {
'notes' : 'index',
}

这样在下面,需要再去定义一下这个 index 函数 .. 可以把它作为这个路由器的一个方法 ... 函数在对象里面就叫作方法 ... 在它里面,可以把之前我们创建的集合视图里的 el 属性,显示到页面上,也就是一个笔记列表 ...

jQuery('#note_list').html(noteCollectionView.el)

接着在控制台上可以再输出点文字 .. 用一个 console.log ... 输出的文字是 笔记列表 ...

index: function() {
console.log('笔记列表');
}

这样我们就为应用定义好了一个路由 ... 名字是 notes ... 处理它的函数叫做 index,index 要做的事就是在控制台上输出 笔记列表这几个字 .. 也就是,当用户访问 notes 这个地址的时候,就会在控制台上输出这几个字 ...

在这个路由器的下面,我们需要再去实例化一下它 ...

var noteRouter = new NoteRouter;

然后我们需要再使用一个 Backbone 的 history ,start ... 它的作用就是告诉 Backbone ,开始监视 hashchange 事件。

Backbone.history.start();

演示

保存 ... 下面到浏览器上去试试 ..

先打开应用的首页 ... 再打开控制台 ... 然后再输入 notes ... 注意 ... Backbone 默认会使用 hash fragments 的地址形式 ... 也就是在地址上先得加上一个 # 号 ... 接着才是具体的在路由器里定义的地址 ...

http://localhost:8888/backbone/#notes

在控制台上,会显示 笔记列表 这个字 ... 这是因为我访问了 notes 这个地址,会触发执行处理它的函数 ... 这个函数做的事,就是在控制台上显示这几个字儿 ...

来自 https://ninghao.net/video/1465#info


22)地址中的参数


在上一个视频里我们定义了一个固定形式的路由,就是 notes ... 很多时候,我们需要在路由的地址里面加上参数 ... 比如,想让用户访问单个笔记内容的时候,你可能需要使用一个 notes 斜线 加上笔记 id 的形式的地址来访问某个笔记的内容 ... 在这种形式的地址里面,笔记的 id 应该是这个路由里面要用到的参数 ...

Backbone 的路由里面,定义一个普通的参数可以使用冒号加参数名字的形式 (:param)... 它可以表示在地址里面,斜线之间的一部分 ...

另外,也可以使用 splat 形式的参数,这可以表示多个部分的地址 ... 下面,我们还是通过几个演示来理解一下地址中的参数。

在这个路由器的 routes 属性里面,用一个逗号分隔一下 .. 另起一行,再去定义一个路由 ... 这个地址的形式可以是 notes 斜线 ... 加上一个冒号 id ...

处理它的函数是 show ...

'notes/:id' : 'show'

在这个路由里面,冒号 id 就是一个参数 ... 在处理它的 show 这个函数里面,可以接受这个 id 作为它的一个参数 ... 这样在函数里面,可以利用这个参数 ... 比如根据笔记的 id 号,从数据库里查询出这条笔记的具体的内容。

在下面,我们再去定义这个 show 函数 .. . 然后把路由里面的 id 参数,作为这个函数的一个参数传递进来 ... .. 为了测试,我们还是先在控制台上输出一行文字 .. console.log ... 笔记 .. 加上 id 号 ...

show: function(id) {
console.log('笔记:' + id);
}

另起一行,下面,我们可以再根据这个 id 号,从集合里找到这个模型,然后用模型的视图渲染一下,再显示到页面上。

得到这个模型,可以使用集合的 get 方法 ... 把 id 号交给这个方法 ...

var note = noteCollection.get(id);

然后再根据这个模型去创建一个视图 ...

var noteView = new NoteView({model: note});

最后再把渲染之后的视图内容显示到页面上。

jQuery('#note_list').html(noteView.render().el)

保存 ... 再去预览一下 ...

输入地址 ... #notes 斜线 ... 再加上笔记的 id 号 ,1,... 在控制台上会显示 笔记 1 ... 同时在页面上,也会显示出这条笔记的内容。

再换一下这个地址上的笔记的 id 号 .. 2 ... 在页面上会显示 id 号是 2 的这条笔记的内容。

处理这个地址的函数会接收到 notes 后面的这个 id 号 ...

再试一下其它的 ... 在 id 号后面再加上一个斜线 .. #notes/3/

这回没有在控制台上显示对应的内容 ... 因为在这个地址的最后,加上了一个斜线 .... Backbone 会区分出来 ... 带斜线和不带斜线的地址会认为是两种形式的地址 ...

在这个最后的斜线后面,再加上一小段东西 ... #notes/3/bookmark

同样,也是不会显示对应的内容 ... 因为这也属于另一种形式的地址 ... 在定义路由的时候,可以加上这小段内容 ... 也就是这个斜线 bookmark ...

来自  https://ninghao.net/video/1466#info


23)地址中的可选部分

在地址里面,我们也可以添加可选的部分,用一组圆括号,把可选的部分括起来 ...

在这个 notes 地址里面,添加一个可选的部分 ... 可以用一组括号,把可选的部分括起来 ... 加上一个斜线 page 斜线 冒号 page ... 在这个可选部分里面,有一个静态的 page 片断 ... 然后还有一个 page 参数 ... 可以用它表示分页的号码 ...

'notes(/page/:page)': 'index',

这样在处理这个地址的 index 函数里面,可以接受这个 page 参数 ...

在这个函数里,定义一个变量 ... 叫 page ... 让它的值,等于 page 参数的值,或者是 1 ,也就是,如果能接受到 page 参数,就让 page 这个变量的值等于这个参数的值 .. 如果接收不到 ... 就让它等于 1

var page = page || 1;

然后再改造一下,要在控制台上显示的文字 ...

console.log('笔记列表,第 ' + page + ' 页');

保存 .  回到浏览器 ...

在地址栏里输入 #notes

在控制台上,会显示,笔记列表,第1页,我们没有在地址栏上指定要访问的页码 ... 处理这个地址的函数里面,page 变量的值就会等于 1 。

在修改一下地址 ..

#pages/page/2

控制台上会显示,笔记列表,第2页。

函数会接收到地址里面的 page 参数的值 .. 也就会在控制台上,把它显示出来 .. .

来自  https://ninghao.net/video/1467#info


24)手工改变地址 - navigate

有时候,我们可能希望手工去改变应用程序的地址,比如,用户在访问一个笔记内容的时候,你可以验证一下用户是不是已经登录了,没有没登录,你可以让应用程序的地址换成登录的地址,要求用户先登录 ...

实现这个功能,可以使用 navigate 方法 ...

下面,我们先去定义一个路由 ... 在这个 routes 属性里面 .

路由的地址是 login ,表示用户登录的地址 ... 然后可以再加上一个可选的部分,标记一下用户登录以后要返回的那个地址 ... 用一个 *from 来作为这个地址里的参数 ... 一个星号加上参数的名字,表示这是一个 splat 类型的参数 .. 它可以表示地址里面的多个部分 ...

也就是如果用户在访问 notes/1 这个笔记的时候,这个 notes/1 就是这个登录以后返回的目的地 .. 这样用户在登录成功以后,可以继续查看他之前想要看的那条笔记 ...

用 login 这个函数去处理它 ...

'login(/from/*from)': 'login'

下面,再去定义这个 login 函数 ... 函数接收 des 作为它的参数 ... 然后在控制台上,输入一行文字 ...

login: function(from) {
console.log('请先登录... 目的地:' + from);
}

下面,我们在这个 show 函数里面,使用一个 navigate 方法 ... 在这里,你可以判断用户是不是已经登录了 ... 没有的话,就是执行这个 navigate 方法 ... 把用户带到登录的页面 ...

不过这里,我们为了简单点,可以直接使用这个方法 ... this.navigate ... this 表示当前的这个路由器对象 ..

这个方法的第一个参数是一个地址 ... 'login/from/notes/' + id

我们要访问的地址是 login 斜线 des 斜线 id 号,这个 id 号就是用户当前要访问的这个笔记的 id 号,这个 id 号可以作为 login 这个路由上面的目的地部分的那个 des 参数的值 ...

默认情况下,这个 navigate 方法,只会改变应用的地址,并不会触发 haschange 事件,也就是,不会去执行跟这个地址对应的函数 ... 如果想要触发 hashchange 事件的话 ...

需要在这个方法的选项参数里,把 trigger ,设置成 true ...

this.navigate('login/from/notes/' + id, {trigger: true});

保存一下 ... 回到浏览器 ...

先刷新一下 ... 然后可以访问 #notes 斜线 ... 随便加上一个笔记的 id 号 ... 125 ... 回车 ...

注意,应用程序的地址会变成 #login/from/notes/125

因为我们在处理这个 #notes/:id 地址的函数里面,使用了一个 navigate 方法,手工的改变了应用程序的地址 ..

在这个方法里面,我们把 trigger 选项的值设置成了 true ...

所以,会去执行处理这个 #login 地址的函数 ...

在控制台上,会显示 请先登录 ... 目的地是 notes/125 ...

来自  https://ninghao.net/video/1468#info



RESTful

25)RESTful - 准备

Backbone 可以从后台数据库里提取出数据然后放到它的模型里面,也可以从数据库里提取数据放到它的集合里面,Backbone 可以更新数据到数据库里面,也可以创建新的数据或者从数据库里删除掉数据。

我们需要给 Backbone 提供了一个后台,下面,我们用 Laravel 框架去搭建一个这样的后台。Backbone 可以向这个后台发送请求,去做指定的事情。

关于 Laravel 这个框架的使用,你可以参考宁皓网的 Laravel 相关的课程。

来自  https://ninghao.net/video/1469#info


26)数据库

这里我们已经安装好了一个 Laravel 框架,首先可以去给 Laravel 创建一个数据库 ... 这里我用的是 Sequel Pro ,你也可以使用 PHPMyAdmin ...

Database ,创建数据库 ... 输入数据库的名字 ... backbone ... 创建一个叫 backbone 的数据库 ...

然后我们要在这个数据库里添加一个数据表 ... 在这个数据表里,可以存储笔记相关的数据 .. 在 Laravel 框架里面,创建数据表,可以去创建一个 Migration ...

Migrate

打开命令行工具 ... 进入到 Laravel 框架所在的目录 ... cd desktop/laravel ... 然后用它的 artisan 命令去创建这个 migration ..

php artisan migrate:make create_notes_table --create=notes

创建一个叫 create_notes_table 的 migration ...

打开 app 目录下面的 database ... migrations . .. 再打开刚才创建的 migration ...

在这里我们去添加 notes 这个表里的结构 ... 这里已经有了一个 id 栏 ,还有一个 timestamps ... 它可以创建两个字段,一个叫 created_at,还有一个叫 updated_at ...

下面我们再添加一个 title 字段 .. $table->string('title');

保存 ...

回到命令行工具,去执行这个 migration ...

php artisan migrate

成功以后,再去给这个 notes 数据表,添加点演示的数据,可以去创建一个 seeder ..

seeder

打开 app/database ... seeds 这个目录 ... 新建一个 php 文件,可以复制一下这里的 DatabaseSeeder ... 重命名为 NotesTableSeeder.php ... 打开它 ...

<?php

class NotesTableSeeder extends Seeder
{
public function run()
{
$data = array(
array('id' => '1', 'title' => '西红柿炒鸡蛋的作法' ),
array('id' => '2', 'title' => '周六参加朋友的婚礼' ),
array('id' => '3', 'title' => '晚上回家洗尿布' ),
);

DB::table('notes')->insert($data);
}
}

创建一个叫 NotesTableSeeder 的类 ... 让它去继承 seeder ... 在这个类里添加一个 run 方法 ... 然后再去准备一些演示数据 ...

最后把这些数据插入到 notes 这个数据表里 ... 再打开 DatabaseSeeder.php .. 添加一行代码 ...

$this->call('NotesTableSeeder');

下面再去执行一下刚才创建的 Seeder ... 回到命令行工具 ...

php artisan db:seed

打开数据库工具 ... 再打开 backbone 这个数据库 ... notes 数据表 ... 在这个表里,已经有了几条演示的数据 ...

模型

再去给这个 notes 数据表创建一个模型 ... 打开 app ... models ... 新建一个 php 文件 .. . 命名为 Note.php ... 这个名字是数据表的单数形式 ... 数据表叫 notes ,跟它对应的模型的名字就可以是 note ...

打开这个文件 .. 然后去创建一个叫 Note 的 类 ... 去继承 Eloquent ...

class Note extends Eloquent {
public $timestamps = false;
}

来自  https://ninghao.net/video/1470


27)控制器

下面,我们需要去创建一个控制器 ... 在命令行工具下面,输入

php artisan controller:make NotesController

打开 app ... controllers ... 在这里,可以找到刚才创建的控制器 ... 在后面的视频里,我们还会再回来去修改这个控制器 ...

路由

再去添加一条路由 ... 打开 routs.php ...

这个路由用的是 resource 类型的控制器来处理 ... 路由的地址是 notes ... 对应的控制器是 NotesController

Route::resource('api/notes', 'NotesController');

Backbone

最后,我们可以找到之前创建的 Backbone 应用 ... 把它放在 laravel 的 public 这个目录的下面...

运行

再使用命令,去启动一个 web 服务 ...

php artisan serve ...

打开浏览器 .. 输入地址 http://localhost:8000

这里显示的就是 Laravel 框架的首页 ...

后面再加上一个 backbone/index.html .... 会打开 Backbone 应用的首页 ... 也就是在 backbone 这个目录下面的 index.html ...

来自 https://ninghao.net/video/1471#info



28)从数据库中提取数据到集合里


使用 Backbone Collection ,也就是 Backbone 里面的集合的 fetch() 方法,可以从服务端那里,提取出数据的模型,这些模型会自动放到这个集合里面。

下面,我们一起来看一下 ...

首页,需要先去配置一下,让服务端可以返回集合需要的数据。先打开之前我们在 Laravel 里面创建的 Note 这个控制器 ...

在 RESTful 类型的控制器里面,数据的列表,用的是 index 方法返回的,跟这个控制器对应的路由是 api/notes,所以,默认在请求这个地址的时候,就会返回列表数据,也就是笔记模型的列表。

在这个方法里, 可以使用 Note 模型的 all 方法,得到所有的笔记模型。关于 Laravel 的数据相关的操作,你可以参考,宁皓网的 《Laravel 数据库》这个课程。

return Note::all();

保存 ... 下面,我们去试一下 ... 你可以直接在浏览器上打开 api/notes 这个地址 ... 或者,我们可以使用一些 REST 调试工具 .. 这里我用的是 Postman ... 你可以在 Chrome 浏览器的商店里找到这个扩展。

在这里输入要请求的地址 ... http://localhost:8000/api/notes ... 请求的方法选择 GET ... 点一下 Send 发送 ... 在下面,body 这个选项卡里的东西就是返回来的主体内容 ... 这里可以使用 Pretty 的方式预览一下得到的主体内容 ...

得到的就是 JSON 格式的数据 ... 每一小块,都有 id ,title,created_at ,还有 updated_at 这些属性 ...

Backbone

再打开在 Laravel 框架下面的 Backbone ... 打开 app.js ...

想让 Backbone 可以提取服务端的数据到集合里面,我们需要在集合里,指定一下提供这些数据的地址 ...

设置一下 url 属性 ... 属性的值,就是刚才你看到的,返回数据列表的那个地址 ... 也就是 /api/notes 这个地址 ..

url: '/api/notes'

保存 .. 再去浏览器上试试 ...

预览

打开 Backbone 应用的首页 ... 再打开控制台 ... 我们可以先去新建一个集合 ...

var noteCollection = new NoteCollection()

然后,再去调用这个集合的 fetch 方法 .. 因为在 NoteCollection 集合里面,已经定义好了提供数据的地址 ... 执行这个方法,就会使用 Ajax 来发送请求到这个地址上 ...

noteCollection.fetch()

服务端会根据请求返回相应的数据 ... 打开这个返回来的对象 ... 在 responseJSON 这里,你会找到,请求并且返回来的数据对象 ...

我们可以再打开 Network 这个选项卡看一下 ... 点击这个筛选的小图标 ... 然后选择 XHR,只查看 Ajax 的请求...

打开 notes 这个请求 ... 然后点击 Header 这个选项卡 ... 在这里,我们可以看到,这个 Ajax 的请求的地址是 /api/notes ...

Request Method ,请求的方法是 GET ... 再打开 Response 选项卡 ... 这里就是服务端给我们返回来的数据 ...

在 Preview 这里,可以预览一下 ... 返回来的就是 JSON 类型的数据 ...

再回到 Console ...

现在,我们可以先查看一下这个 noteCollection 集合 ...

noteCollection

打开 models 属性 ... 这里,你会看到,在这个集合里面,已经有了三个模型 ... 也就是发送请求,从服务端那里请求回来的数据模型 ...

要得到集合里面的模型 .. 可以使用 get 方法 ... 指定一下模型的 id 号 ...

noteCollection.get(1)

返回的就是 id 号是 1 这个模型 .. 再访问一下它的 attributes 属性 ...

noteCollection.get(1).attributes

来自  https://ninghao.net/video/1472


29)提取模型 - fetch

Backbone 的 Model 里面也有一个 fetch() 方法,可以从服务端那里提取出指定的模型。 先去配置一下服务端 ..

在 NoteController 这个控制器里,找到 show 这个方法 ... 在这个方法里,我们需要根据请求的 id 号,返回对应的数据模型 ...

可以使用 Note 这个模型的 find 方法 .. 然后把请求的 id 号传递给这个方法 ... 再返回得到的数据 ...

public function show($id)
{
return Note::find($id);
}

保存 ... 再用 Postman 工具测试一下 ... 请求个笔记的内容 ... 地址应该是 api/notes 后面加上笔记的 id 号 ... 方法同样是 GET .... 点击 Send ... 返回的,就是在数据库里面 id 号是 1 的笔记内容 ... 数据的格式使用的是 JSON ..

Backbone

再回到 Backbone 的 app.js ... 单独去请求一个模型,需要指定一下 urlRoot 属性 ... 设置一下模型的根目录 ...

urlRoot: '/api/notes'

这样的话,id 号是 1 的笔记的地址,就应该是 /api/notes/1 ...

保存 ...

回到浏览器 ..

预览

假设现在我们要从数据库里提取出 id 号是 1 的笔记 ...

先去新建一个 Note 模型 ... 然后指定一个这个模型的 id 号 ...

var note = new Note({id: 1})

回车 ...

再去调用这个 note 模型的 fetch 方法 ...

note.fetch()

再查看一下这个模型的现在的属性 ...

note.attributes

这里显示的是,就是从服务端那里面得到的这个 id 号是 1 的笔记内容 ...

可以再打开 Network 选项卡 .. 打开这个名字是 1 的请求 . Header ...

这个 Ajax 请求,Request URL ,请求的地址是 /api/notes/1 ... 请求的方法是 GET

再看一下 Preview ...

响应回来的就是 JSON 类型的数据,数据的内容就是 id 号1 的笔记内容 ...

来自  https://ninghao.net/video/1473#info


30)添加数据 - save


新建一个 Backbone 模型,设置一下它的属性,还有对应的值,然后再调用模型的 save 方法,可以把模型添加到服务端的数据库里面。

我们需要先去配置一下服务端的代码,可以让处理这个添加数据的请求。 打开 Laravel 的 NoteController 这个控制器 ...

找到 store 这个方法 .. 如果使用 Post 方法,请求跟这个控制器对应的地址,也就是 api/notes 这个地址的时候,会用 store 这个方法处理这个请求 ...

在这个方法里,首先,我们要创建一个新的 Note 模型,这个模型是 Laravel 里的模型 .. .

$note = new Note;

然后,我们要去设置一下这个模型的属性,还有对应的值 ... 再把它保存到数据库里面 ...

$note->title = Input::get('title');

这行代码的意思就是,把 $note 这个模型的 title 属性的值,设置成请求发送过来的 title 属性的值 ... 也就是来自 Backbone 这个模型里面的 title 属性的值 ...

再调用这个模型的 save() 方法 ...

$note->save()

这样 Laravel 会把这个模型保存到数据库里面 ...

Backbone

下面,我们再到浏览器上去试试 .. 先去新建一个在 Backbone 上面,表示笔记的 Note 这个模型 .. 可以直接去设置一下这个模型里的属性还有值 ...

var note = new Note({title: '今天天气挺好的'})

这样 note 这个模型的 title 属性,就是 今天天气挺好的 ...

下面,我们可以调用模型的 save 方法,把它保存到服务端的数据库里面 ...

note.save()

这个方法会用 Ajax 的方式去发出请求 ... 打开 Network 选项卡 ... 你会看到,刚刚有一个 notes 请求 ...

在 Headers 这里,你会看到请求的地址是 api/notes ... 请求的方法是 POST

这个请求,在 Laravel 里的 NoteController 这个控制器上面,用 store() 这个方法去处理 ... 这个方法做的事就是,根据请求发送过来的数据,新建一个模型,再把它保存到数据库里面。

我们可以打开数据库去看一下 ...

你可以使用 phpMyadmin ,这里我用的是 Sequel Pro ... 在服务端的数据库里面 ... notes 这个表里,会多出一条记录 ...

也就是,刚才我们保存进来的那个模型 ... 标题是 今天天气挺好的 ...

来自 https://ninghao.net/video/1474#info


31)把模型添加到集合里再更新到数据库 - create

新建一个模型,再把这个模型保存到数据库里面,再把它添加到某个集合里。这些动作,Backbone 提供了一个简便的方法,可以使用集合的 create 方法。

下面,我们一起去试试这个方法 ...

打开浏览器 ... 先去新建一个集合 ..

var noteCollection = new NoteCollection

再用 fetch 方法,从服务端那里提取模型到这个集合里面 ..

noteCollection.fetch()

可以先查看一下这个集合 ...

noteCollection .

现在,这里,一共有 x 个模型 ... 下面, 我们再去调用这个集合的 create 方法 .. 在这个方法里,可以直接去设置一下要创建的模型里面的属性,还有对应的值 ...

noteCollection.create({title: '下礼拜六是老爸生日'})

回车 ... 会立即返回这个新创建的模型 ...

再查看一下 noteCollection 这个集合 ...

noteCollection

在 models 属性里面,我们可以找到刚才添加进来的模型 ...

再打开数据库看一下 ...

刚才用 create 方法创建的模型,也添加到了数据库里面 ...

这个 create 方法,还有一些选项 ... 比如,我们可以把 wait 选项设置成 true .. 这样,会在服务端做出响应以后,再把模型添加到集合里面 ...

先回到浏览器 ... 然后打开刚才添加到集合里面的那个模型 ... 注意,这个模型里面,没有 id 属性 ..

这个属性是模型在数据库里面的 id 号 ... 因为我们在把模型保存到数据库之前,已经把模型添加到了集合里面,所以,这里就不会有 id 号。

解决的办法就是,把 create 方法的 wait 选项,设置成 true ... 等待服务端的响应 ...

然后在服务端,我们可以在把模型保存到数据库之后,返回这个模型 ... 这样,再把这个模型添加到集合里的时候,模型就拥有了 id 属性了 ...

先打开 NoteController ... 在 store 这个方法里 .. 返回保存之后的模型 ...

return $note;

保存 ... 再回到浏览器 ...

下面,再用一个 create 方法 ... 这回给它一个选项参数 ... 把 wait 选项的值,设置成 true

noteCollection.create({title: '下礼拜六是老爸生日'}, {wait: true})

打开这个返回来的模型 ...

你会看到,现在这个模型里面,就会包含这个 id 属性了 ...

来自   https://ninghao.net/video/1475#info


32)更新数据

在 Backbone 的应用里面,找出指定 id 号的模型,然后修改它的属性值,再把这个模型保存到服务端 ... 服务端接收到请求,找出要修改的模型,重新设置模型的属性值,再把模型保存到数据库里面。

我们先打开 NoteController 这个控制器 ...

处理更新请求的方法是 update ... 这个方法接受一个 id 参数 ... 我们可以先用这个 id 号,从数据库里面,找出这个模型 ...

$note = Note::find($id);

然后,再设置一下它的属性的新的值 ...

$note->title = Input::get('title');

这里的 Input::get('title'),得到的就是发送过来的请求里面的模型的 title 属性的值 ...

这行代码的意思就是,把重新设置一下数据库里面的这个笔记的 title 的值 ... 然后再调用模型的 save 方法,去把它保存到数据库里面 ...

$note->save();

这样我们就准备好了,更新数据的服务端的配置 ...

Backbone

下面,再去浏览器上试试 .. 打开 Backbone 应用的首页 ...

在控制台上,先去找到要更新的模型 .. . 新建一个模型 ... 指定一下模型的 id 号 ... 再去数据库里面提取出这个模型的内容 ... 再查看一下这个模型的属性...

var note = new Note({id: 1})
note.fetch()
note.attributes

然后,我们可以重新去设置一下要修改的属性的值 ... 比如我们要改一下 title 属性的值 ... 设置属性,可以使用 set 方法 ... 这里我们把原来的 西红柿炒鸡蛋的作法,改成 锅包肉的作法 ..

note.set('title', '锅包肉的作法')

最后,再把这个修改保存到服务端那里 ... 用的是模型的 save 方法 ...

note.save()

打开 Network 选项卡 ... 在这里,你会看到一个用 PUT 方法发出的 Ajax 请求 ... 请求的地址是 /api/notes/1

请求的方法是 PUT

再打开数据库 ....

注意 id 号是 1 的这条笔记的内容 ... 刷新 ... 你会发现 ... 笔记的标题 ... 已经变成了 锅包肉的作法

来自  https://ninghao.net/video/1476#info

33)删除数据 - destroy

在 Backbone 的应用里,找到要删除的模型,然后调用模型的 destroy 方法,可以使用 Ajax 向服务端发生一个删除请求,请求的方法是 DELETE,请求的地址应该是这个模型的地址 ..

服务端接收到这个请求,在控制器里,会用 destroy 方法去处理这个请求。在这个方法里面,可以直接使用模型的 destroy 方法,根据请求的模型的 id ,把它从数据库里面删除掉 ...

删除成功以后, Backbone 会触发一个 destroy 事件,你可以挂载(应该是监听吧)这个事件,去做一些事情。

先打开 NoteController 控制器 ... 找到 destroy 方法 ...

在这里,使用模型的 destroy 方法 ... 方法里面指定一下要删除的笔记的 id 号 ... 这个 id 号,会随着请求发送过来 ...

public function destroy($id)
{
Note::destroy($id);
}

保存 ..

再去浏览器上试试 ..

先去新建一个模型 ... 指定一下模型的 id 号 ..

var note = new Note({id: 1})

调用这个模型的 destroy 方法 ..

note.destroy()

这样会用 Ajax ,向服务端发生删除的请求 .. .

打开 Network 这个选项卡 ...

你会看到一个用 DELETE 方法发出的请求 .. 请求的地址是 /api/notes/1 ,方法是 DELETE ...

再打开数据库 ...

注意这个 id 号是 1 的这条笔记 ... 刷新一下 ...

在数据库里面,已经删除掉了这条笔记 ...


来自  https://ninghao.net/video/1477#info

普通分类: