`

Backbone入门指南(五):Collection (数据模型集合)

阅读更多

本文转自:http://yujianshenbing.iteye.com/

 

8. Collection (数据模型集合)

  如果将一个Model对象比喻成数据库中的一条记录,那么Collection就是一张数据表。它表示为一个模型集合类,用于存储和管理一系列相同类型的模型对象。

8.1 创建集合

  集合用于组织和管理多个模型,但它并不是必须的,如果你的某个模型对象是唯一的(单例),那么你没必要将它放到集合中。

  我们来看一个创建集合的例子:

 

Js代码   收藏代码
  1. // 定义模型类  
  2. var Book = Backbone.Model.extend({  
  3.     defaults : {  
  4.         name : ''  
  5.     }  
  6. });  
  7.   
  8. // 定义集合类  
  9. var BookList = Backbone.Collection.extend({  
  10.     model : Book  
  11. });  
  12.   
  13. // 创建一系列模型对象  
  14. var book1 = new Book({  
  15.     name : 'Effective Java中文版(第2版)'  
  16. });  
  17. var book2 = new Book({  
  18.     name : 'JAVA核心技术卷II:高级特性(原书第8版)'  
  19. });  
  20. var book3 = new Book({  
  21.     name : '精通Hibernate:Java对象持久化技术详解(第2版)'  
  22. });  
  23.   
  24. // 创建集合对象  
  25. var books = new BookList([book1, book2, book3]);  

 

  在这个例子中,我们定义了模型类Book和集合类BookList,然后创建了3个模型对象,并将它们放到一个集合对象中。(你可以在控制台输出books.models属性,用来查看集合中包含的模型对象列表)

  我们为了创建3个Book模型对象,对Book类显式实例化了3次,其实Model本身已经提供了更简单的方法来复制一个模型,例如:

Js代码   收藏代码
  1. var book1 = new Book({  
  2.     name : 'Effective Java中文版(第2版)'  
  3. });  
  4.   
  5. var book2 = book1.clone();  
  6. book2.set('name''JAVA核心技术卷II:高级特性(原书第8版)');  
  7.   
  8. var book3 = book1.clone();  
  9. book3.set('name''精通Hibernate:Java对象持久化技术详解(第2版)');  

 

  在段代码中,我们使用模型的clone()方法来复制一个和当前对象相同(包括数据)的新对象,这可以简化我们创建模型的流程。

 

  在实例化集合对象时,除了可以向构造函数中添加已经创建好的模型列表(就像上面的例子那样),我们还可以直接传递模型数据,集合会自动将这些数据转换为模型对象,例如:

 

Js代码   收藏代码
  1. // 定义模型类  
  2. var Book = Backbone.Model.extend({  
  3.     defaults : {  
  4.         name : ''  
  5.     }  
  6. });  
  7.   
  8. // 定义集合类  
  9. var BookList = Backbone.Collection.extend({  
  10.     model : Book  
  11. });  
  12.   
  13. var models = [{  
  14.     name : 'Effective Java中文版(第2版)'  
  15. }, {  
  16.     name : 'JAVA核心技术卷II:高级特性(原书第8版)'  
  17. }, {  
  18.     name : '精通Hibernate:Java对象持久化技术详解(第2版)'  
  19. }];  
  20.   
  21. // 创建集合对象  
  22. var books = new BookList(models);  

 

 

  运行这个例子,并在控制台输出books.models属性,你可以看到集合中存储的是Book模型类的实例,而并非我们在models数组中声明的原始数据。

  这是因为我们在声明BookList集合类的时候,就已经设置了model属性,该属性指向集合中存储的模型对象的构造函数,当我们传递原始数据时,集合会自动创建model中定义的模型类,并将原始数据传递给它。

  (如果你在定义集合类的时候没有设置model,那么集合会默认将原始数据转换为Backbone.Model类的实例)

 

  我们之所以要使用extend来继承Backbone.Collection类,是因为我们希望定义一个自己的集合类,并向其中扩展更多的自定义方法。如果你的集合类仅仅是用于简单地存储和管理模型对象,且Backbone.Collection类所提供的方法已经可以满足你的要求,那么你可以直接实例化一个Backbone.Collection,同时也可以像上面一样实现原始数据和模型对象的自动转换,例如:

 

Js代码   收藏代码
  1. // 定义模型类  
  2. var Book = Backbone.Model.extend({  
  3.     defaults : {  
  4.         name : ''  
  5.     }  
  6. });  
  7.   
  8. var models = [{  
  9.     name : 'Effective Java中文版(第2版)'  
  10. }, {  
  11.     name : 'JAVA核心技术卷II:高级特性(原书第8版)'  
  12. }, {  
  13.     name : '精通Hibernate:Java对象持久化技术详解(第2版)'  
  14. }];  
  15.   
  16. // 创建集合对象  
  17. var books = new Backbone.Collection(models, {  
  18.     model : Book  
  19. });  

 

 

  在本例中,我们没有通过extend定义自己的集合类,而是直接实例化Collection类。我们依然传入了原始数据,但同时我们在构造函数的第2个参数(配置对象)中设置了model属性,Collection通过它就能知道要将原始数据转换为哪个模型类的实例。

8.2 向集合中添加模型

  集合提供了3个方法允许我们动态地向集合中动态插入模型:

 

  • add():向集合中的指定位置插入模型,如果没有指定位置,默认追加到集合尾部
  • push():将模型追加到集合尾部(与add方法的实现相同)
  • unshift():将模型插入到集合头部

 

  这些方法很容易理解,但我们还是通过一个例子来说明:

 

Js代码   收藏代码
  1. // 定义模型类  
  2. var Book = Backbone.Model.extend({  
  3.     defaults : {  
  4.         name : '',  
  5.         price : 0  
  6.     }  
  7. });  
  8.   
  9. // 创建集合对象  
  10. var books = new Backbone.Collection(null, {  
  11.     model : Book  
  12. });  
  13.   
  14. books.add({  
  15.     name : '构建高性能Web站点',  
  16.     price : 56.30  
  17. });  
  18.   
  19. books.push({  
  20.     name : '深入分析Java Web技术内幕',  
  21.     price : 51.80  
  22. });  
  23.   
  24. books.unshift({  
  25.     name : '编写高质量代码:Web前端开发修炼之道',  
  26.     price : 36.80  
  27. });  
  28.   
  29. books.push({  
  30.     name : '基于MVC的JavaScript Web富应用开发',  
  31.     price : 42.50  
  32. }, {  
  33.     at : 1  
  34. });  
  35.   
  36. books.unshift({  
  37.     name : 'RESTful Web Services Cookbook中文版',  
  38.     price : 44.30  
  39.   
  40. }, {  
  41.     at : 2  
  42. });  
  43.   
  44. // 在控制台输出集合中的模型列表  
  45. console.dir(books.models);  

 

 

  在例子中,我们通过3个方法向集合中添加了多个模型,最后,我们在控制台输出了集合中的模型列表。请仔细观察和分析我们调用的方法,以及最终列表中模型的排列顺序:

  这些方法的作用和上面介绍的一样,用于将模型添加到集合中不同的位置,但当我们设置了at配置之后,它们就变得完全一样了,因为它们会忽略自身的规则,将模型插入到at所指向的位置。

  当数据被成功添加到集合中时,集合会触发add事件,执行所有监听add事件的方法。除非我们在调用add()方法时设置了silent配置项,则会忽略事件的触发。

8.3 操作集合中的模型

  在Underscore中,提供了许多对对象和数组集合进行操作的方法,这些方法已经被Backbone添加到Collection类的原型中。这意味着你可以使用Underscore中的集合方法来操作Collection集合中的数据,例如each()、map()、find()等方法。

  但有一些方法我们还是要单独介绍它们,因为Collection对这些方法进行了重写,它们和Underscore中的同名方法不完全相同。(这也是为什么我要在上面单独介绍模型的添加方法)

  删除模型:

  集合类提供了3个方法用于从集合中移除模型对象,分别是:

 

  • remove():从集合中移除一个或多个指定的模型对象
  • pop():移除集合尾部的一个模型对象
  • shift():移除集合头部的一个模型对象

 

  这些方法与添加的方法是对应的,而且当模型被移除成功后,会触发集合对象的remove事件,除非你在移除时使用了silent配置。

  这些方法很容易理解,但还是让我们通过一个简单的例子来说明:

 

Js代码   收藏代码
  1. // 定义模型类  
  2. var Book = Backbone.Model.extend({  
  3.     defaults : {  
  4.         name : '',  
  5.         price : 0  
  6.     }  
  7. });  
  8.   
  9. // 定义初始化数据  
  10. var data = [{  
  11.     name : '构建高性能Web站点',  
  12.     price : 56.30  
  13. }, {  
  14.     name : '深入分析Java Web技术内幕',  
  15.     price : 51.80  
  16. }, {  
  17.     name : '编写高质量代码:Web前端开发修炼之道',  
  18.     price : 36.80  
  19. }, {  
  20.     name : '基于MVC的JavaScript Web富应用开发',  
  21.     price : 42.50  
  22. }, {  
  23.     name : 'RESTful Web Services Cookbook中文版',  
  24.     price : 44.30  
  25.   
  26. }]  
  27.   
  28. // 创建集合对象  
  29. var books = new Backbone.Collection(data, {  
  30.     model : Book  
  31. });  
  32.   
  33. books.remove(books.models[2]);  
  34. books.pop();  
  35. books.shift();  
  36.   
  37. // 在控制台输出集合中的模型列表  
  38. console.dir(books.models);  

 

 

  在本例中,我们分别调用了remove()方法移除了集合中第2个模型,调用pop()方法移除了最后一个模型,调用shift()方法移除了第一个模型。最后我们在控制台输出集合中剩下的模型列表,请查看控制台输出结果,它和你想象的结果是一致的。

 

  在集合中查找模型:

Collection定义了一系列用于快速从集合中查找我们想要的模型的方法,包括:

 

  • get():根据模型的唯一标识(id)查找模型对象
  • getByCid():根据模型的cid查找模型对象
  • at():查找集合中指定位置的模型对象
  • where():根据数据对集合的模型进行筛选

 

  前面前面一片介绍数据模型时我们提到,每个模型对象都有一个唯一标识(id),它与数据库中记录的id保持同步。实际上,每个模型对象内部还会自动创建一个cid,它用来标识每一个模型(请注意将id和cid区分开,它们没有任何关系)。

  集合对象提供了两个方法用于根据id和cid来查找模型对象,分别是get()方法和getByCid()方法,例如:

 

Js代码   收藏代码
  1. // 定义模型类  
  2. var Book = Backbone.Model.extend({  
  3.     defaults : {  
  4.         name : '',  
  5.         price : 0  
  6.     }  
  7. });  
  8.   
  9. // 定义初始化数据  
  10. var data = [{  
  11.     id : 1001,  
  12.     name : '构建高性能Web站点',  
  13.     price : 56.30  
  14. }, {  
  15.     id : 1002,  
  16.     name : '深入分析Java Web技术内幕',  
  17.     price : 51.80  
  18. }, {  
  19.     id : 1003,  
  20.     name : '编写高质量代码:Web前端开发修炼之道',  
  21.     price : 36.80  
  22. }, {  
  23.     id : 1004,  
  24.     name : '基于MVC的JavaScript Web富应用开发',  
  25.     price : 42.50  
  26. }, {  
  27.     id : 1005,  
  28.     name : 'RESTful Web Services Cookbook中文版',  
  29.     price : 44.30  
  30. }]  
  31.   
  32. // 创建集合对象  
  33. var books = new Backbone.Collection(data, {  
  34.     model : Book  
  35. });  
  36.   
  37. // 根据id和cid查找模型对象  
  38. var book1 = books.get(1001);  
  39. var book2 = books.getByCid('c2');  
  40.   
  41. // 在控制台输出模型  
  42. console.dir(book1);  
  43. console.dir(book2);  

 

 

  本例中,我们从集合中根据模型的id和cid查找出2个模型对象,但实际开发中我们不会直接在代码中写出模型的id和cid。

 

  • id应该是从服务器接口进行同步获取到的。
  • cid应该是在之前已经记录下某个模型的cid,再根据它从集合中查找的。

 

 

  at()方法根据我们给定的索引,从集合中查找对应位置的模型,我们在上面的例子中追加以下代码:

 

Js代码   收藏代码
  1. // 根据索引查找模型对象  
  2. var book3 = books.at(1);  
  3.   
  4. // 在控制台输出模型  
  5. console.dir(book3);  
  6.   
  7.   最后,我们还可以通过where()方法,实现相对复杂的查找规则,例如:  
  8. // 根据price从集合中查找模型  
  9. var book4 = books.where({  
  10.     price : 51.80  
  11. });  
  12.   
  13. // 在控制台输出模型  
  14. console.dir(book4);  

 

 

  请查看控制台输出的结果:where()方法用于给定一个或多个数据,查找并返回集合中匹配数据的模型。该方法返回一个数组,因此能够包含一个或多个结果。

 

  当我们调用get()、getByCid()和at()方法没有找到到匹配对象时,会返回undefined,而where()方法在没有找到匹配对象时会返回一个空数组。你可以使用Underscore中的isEmpty()方法检查返回值是否为空,因为它能检查到空数组和空对象。

8.4 自动排序

  我们常常使用数组的sort()方法对元素进行排序,Underscore也提供了sortBy()方法实现更为复杂的集合排序。但在Backbone的集合对象中,为我们提供了集合元素的实时排序,当任何模型对象被插入到集合中时,都会按照预定的排序规则放到对应的位置。

 

Js代码   收藏代码
  1. // 定义模型类  
  2. var Book = Backbone.Model.extend({  
  3.     defaults : {  
  4.         name : '',  
  5.         price : 0  
  6.     }  
  7. });  
  8.   
  9. // 创建集合对象  
  10. var books = new Backbone.Collection(null, {  
  11.     model : Book,  
  12.     comparator : function(m1, m2) {  
  13.         var price1 = m1.get('price');  
  14.         var price2 = m2.get('price');  
  15.   
  16.         if(price1 > price2) {  
  17.             return 1;  
  18.         } else {  
  19.             return 0;  
  20.         }  
  21.     }  
  22. });  
  23.   
  24. books.add({  
  25.     name : '构建高性能Web站点',  
  26.     price : 56.30  
  27. });  
  28.   
  29. books.push({  
  30.     name : '深入分析Java Web技术内幕',  
  31.     price : 51.80  
  32. });  
  33.   
  34. books.unshift({  
  35.     name : '编写高质量代码:Web前端开发修炼之道',  
  36.     price : 36.80  
  37. });  
  38.   
  39. books.push({  
  40.     name : '基于MVC的JavaScript Web富应用开发',  
  41.     price : 42.50  
  42. }, {  
  43.     at : 1  
  44. });  
  45.   
  46. books.unshift({  
  47.     name : 'RESTful Web Services Cookbook中文版',  
  48.     price : 44.30  
  49.   
  50. }, {  
  51.     at : 2  
  52. });  
  53.   
  54. // 在控制台输出集合中的模型列表  
  55. console.dir(books.models);  

 

 

  这个例子和我们前面介绍添加方法时的例子相同,但集合中存储的模型顺序却不一样,因为我们在创建集合对象时设置了comparator方法。我们不需要手动调用该方法,因为它会在新模型被添加到集合中时自动被调用,并按照方法中定义的规则对集合中的数据进行重新排序。

  comparator方法接收两个参数,表示临近的两个模型对象,你需要通过返回值表示它们的排序规则,这和JavaScript中原生的sort()方法是一样的。

  当我们设置了comparator方法后,所有关于元素位置的方法和参数都会失效,例如push()、unshift()方法和at参数等。

 

  需要注意的是:comparator方法在很多时候都是非常有用的(例如显示动态数据列表时),因为它能保证我们获取到的数据始终都是按规则排列的,但在集合中的数据量太多时,它可能会耗费很多的资源和事件来实时确保数据的排序规则。这时,你可以手动调用集合对象的sort()方法在需要的进行手动排序。

8.5 从服务器获取集合数据

 

  • Collection也提供了两个与服务器进行交互的方法:
  • fetch():用于从服务器接口获取集合的初始化数据,覆盖或追加到集合列表中
  • create():在集合中创建一个新的模型,并将其同步到服务器

 

  我们先来看一个fetch()方法例子:

 

Js代码   收藏代码
  1. // 定义模型类  
  2. var Book = Backbone.Model.extend({  
  3.     defaults : {  
  4.         name : '',  
  5.         price : 0  
  6.     }  
  7. });  
  8.   
  9. // 定义集合类  
  10. var BookList = Backbone.Collection.extend({  
  11.     model : Book,  
  12.     url : '/service'  
  13. });  
  14.   
  15. // 创建集合对象, 并从服务器同步初始化数据  
  16. var books = new BookList();  
  17. books.fetch({  
  18.     success: function(collection, resp) {  
  19.         // 同步成功后在控制台输出集合中的模型列表  
  20.         console.dir(collection.models);  
  21.     }  
  22. });  

 

 

  我们前面讨论过模型的数据同步,需要与服务器同步数据,需要设置一个url或urlPath指定服务器接口地址。同步集合数据时也不例外,本例中我们设置服务器接口地址为/service,接口返回数据为:

 

Js代码   收藏代码
  1. [{  
  2.     "id" : "1001",  
  3.     "name" : "构建高性能Web站点",  
  4.     "price" : "56.30"  
  5. }, {  
  6.     "id" : "1002",  
  7.     "name" : "深入分析Java Web技术内幕",  
  8.     "price" : "51.80"  
  9. }, {  
  10.     "id" : "1003",  
  11.     "name" : "编写高质量代码:Web前端开发修炼之道",  
  12.     "price" : "36.80"  
  13. }, {  
  14.     "id" : "1004",  
  15.     "name" : "基于MVC的JavaScript Web富应用开发",  
  16.     "price" : "42.50"  
  17. }, {  
  18.     "id" : "1005",  
  19.     "name" : "RESTful Web Services Cookbook中文版",  
  20.     "price" : "44.30"  
  21. }]  

 

 

  我们在实例化集合对象之后,调用fetch()与服务器接口进行数据同步,并在同步成功后将集合中的数据列表输出在控制台。请运行例子中的代码,你能看到控制台中输出的结果,它包含5个模型对象,正是我们服务器接口返回的这些数据。

  在调用fetch()方法同步集合数据时,默认会以覆盖的方式进行,这意味着集合在同步之前的数据将丢失。我们可以在调用fetch()方法时传递add参数来通知集合进行添加,而不是覆盖,例如:

 

Js代码   收藏代码
  1. var books = new BookList();  
  2. books.add({  
  3.     id : 1000,  
  4.     name : 'Thinking in Java',  
  5.     price : 395.70  
  6. });  
  7.   
  8. books.fetch({  
  9.     add: true,  
  10.     success : function(collection, resp) {  
  11.         // 同步成功后在控制台输出集合中的模型列表  
  12.         console.dir(collection.models);  
  13.     }  
  14. });  

 

 

  我们修改了例子中的代码,在实例化集合对象后,我们向集合中添加了一条数据,然后从服务器同步了5条数据(请注意在调用fetch()方法时我们设置了add参数为true)。在控制台输出的结果中,之前的数据并没有被覆盖掉。

 

  数据在成功同步到集合中之后,会触发reset事件,我们可以通过监听该事件从而进行下一步操作(比如将集合中的数据显示到页面中)。

  集合的数据同步与模型的数据同步有许多相似之处(例如你可以重载parse()方法来对服务器返回的数据进行解析,使其能顺利被添加到集合中),这里就不再重复讨论。

 

  集合提供的另一个create()方法,是根据集合的model所指向的模型类,创建一个模型对象,并把该对象添加到集合中,最后将数据同步到服务器接口。

  我们通过例子来说明create()方法的使用:

 

Js代码   收藏代码
  1. var books = new BookList();  
  2. // 创建一个模型  
  3. books.create({  
  4.     name : 'Thinking in Java',  
  5.     price : 395.70  
  6. }, {  
  7.     success : function(model, resp) {  
  8.         // 添加成功后, 在控制台输出集合中的模型列表  
  9.         console.dir(books.models);  
  10.     }  
  11. });  

 

 

  请将这段代码替换到前面的例子中,并查看运行效果。

  (通过抓包我们能看到Request Method为POST,如果创建的模型中包含id,则Request   Method为PUT,这与我们之前讲模型的save()方法是相同的。)

  集合对象默认会先将模型添加到集合中,再提交到服务器接口,无论接口返回是否成功,新建的模型对象都会被添加到集合中。我们可以通过传递wait配置,来控制只有在服务器返回成功之后(响应状态码为200),才将模型对象添加到集合中。

  在Backbone内部,create()方法是通过add()方法将新创建的模型添加到集合中的,因此我们一般通过监听add事件,来对新模型进行下一步操作。

8.6 将数据批量同步到服务器

  上一节我们讨论过,Backbone中集合提供了数据同步和创建的方法与服务器进行交互,但实际上这可能并不能满足我们的需求。例如:当我们需要对数据进行批量地添加、修改和删除操作时,就需要在Collection的基础上扩展自己的方法。

  在下面的例子中,我扩展了对集合中的模型数据批量同步的方法:

 

Js代码   收藏代码
  1. // 定义模型类  
  2. var Book = Backbone.Model.extend({  
  3.     defaults : {  
  4.         name : '',  
  5.         price : 0  
  6.     }  
  7. });  
  8.   
  9. // 定义BookList类  
  10. var BookList = Backbone.Collection.extend({  
  11.     model : Book,  
  12.     url : '/service',  
  13.     // 将集合中所有的模型id连接为一个字符串并返回  
  14.     getIds : function() {  
  15.         return _(this.models).map(function(model) {  
  16.             return model.id;  
  17.         }).join(',');  
  18.     },  
  19.     // 将集合中所有模型提交到服务器接口  
  20.     createAll : function(options) {  
  21.         return Backbone.sync.call(this'create'this, options);  
  22.     },  
  23.     // 修改集合中的所有模型数据  
  24.     updateAll : function(options) {  
  25.         return Backbone.sync.call(this'update'this, options);  
  26.     },  
  27.     // 删除集合中所有的模型  
  28.     deleteAll : function(options) {  
  29.         var result = Backbone.sync.call(this'delete'this, _.extend({  
  30.             url : this.url + '/' + this.getIds()  
  31.         }, options));  
  32.         this.remove(this.models);  
  33.         return result;  
  34.     }  
  35. });  
  36.   
  37. // 创建集合对象  
  38. var books = new BookList();  
  39.   
  40. // 当集合触发reset事件时, 对数据进行批量同步  
  41. books.on('reset'function() {  
  42.     books.createAll();  
  43.     books.updateAll();  
  44.     books.deleteAll();  
  45. });  
  46.   
  47. // 从服务器接口同步默认数据  
  48. books.fetch();  

 

 

  来分析这个例子:

  我们定义了BookList集合类,并扩展了createAll()、updateAll()和deleteAll()方法(稍后我们再讨论这3些方法的作用)。

  然后我们实例化了一个BookList对象books,并监听了reset事件,reset事件会在从服务器同步数据成功之后被触发。

  接着我们调用fetch()方法从服务器接口获取默认数据(默认数据跟前面例子中返回的数据一致),获取成功后,reset事件的监听函数将被执行。

  我们可以在reset事件的监听函数中做许多的事情(例如写入业务逻辑),但这里为了更直观地演示,我直接调用books的自定义方法进行批量同步。

 

  首先调用的是createAll()方法,它将把当前集合中的所有数据同步到服务器接口,以Request   Method为POST方式告诉服务器接口创建并保存这些数据。

  在createAll()方法中,我们调用Backbone.sync()方法发送异步请求,请注意sync()方法的第2个参数,它是一个模型或集合对象,当操作为create或update时,在sync()方法内部会调用该对象的toJSON()方法,并将toJSON()方法的返回值作为Request   Payload请求数据发送到服务器接口。

  你可以通过抓包并分析请求信息,来更好地理解它。

  (toJSON()方法默认会返回模型或集合的数据对象,你可以通过重载该方法来自定义需要发送的请求数据)

 

  我们假设集合中的数据已经被用户批量修改过,所以我们通过updateAll()方法将最新的数据提交到服务器接口。

  updateAll()方法与createAll()方法几乎相同,它们的区别在于updateAll()方法在修改数据时传递给sync()方法的操作名为update而不是create,而发送给服务器的Request Method为PUT而不是POST。

 

  最后我们通过deleteAll()方法,通知服务器删除集合中的模型,并从本地集合对象中删除这些数据。

  deleteAll()方法与createAll()和updateAll()方法有些不同,因为deleteAll()方法发送给服务器的Request   Method为DELETE方式,这种方式下不能直接调用toJSON()方法将数据发送给接口,因此我们需要手动组装和发送数据。

  在本例中,我们定义了getIds()方法用于将集合中的所有模型的id连接起来,在deleteAll()方法中,我们调用sync()方法发送了Request Method为DELETE的请求,并在URL中将集合中的所有模型id传递给接口进行删除。

分享到:
评论

相关推荐

    backbone 入门指南

    ### Backbone.js入门指南知识点概述 #### 一、为什么需要Backbone.js? Backbone.js是一个轻量级的JavaScript库,它提供了MVC(Model-View-Controller)架构模式的基础实现,帮助开发者更好地组织复杂的Web应用...

    backbone-gulp-starter:使用gulp和骨干网的最小入门项目

    `Backbone.js`的核心概念包括模型(Model)、视图(View)、集合(Collection)和路由器(Router)。它允许开发者用JavaScript对象来组织数据和业务逻辑,同时提供了一种方式将这些数据绑定到DOM元素,实现视图的...

    marionette_book:木偶+骨干入门

    Backbone.js是一个轻量级的MVC(模型-视图-控制器)框架,它为JavaScript应用提供了数据模型、集合、视图和路由器等核心概念。在“初始设置”中,你可能会学习如何安装Backbone.js,创建第一个Backbone应用,以及...

    用OpenGL开发的机械臂运动仿真程序,并且实现机械手臂向四个方向的旋转.rar

    OpenGL是一种强大的图形库,用于创建2D和3D图形,广泛应用于游戏开发、科学可视化、工程设计等领域。在这个项目中,我们看到一个基于OpenGL的机械臂运动仿真程序,它能够实现机械臂在四个方向上的旋转。这样的模拟对于理解机械臂的工作原理、机器人控制算法以及进行虚拟环境中的机械臂运动测试具有重要意义。 我们需要了解OpenGL的基础知识。OpenGL是一个跨语言、跨平台的编程接口,用于渲染2D和3D矢量图形。它提供了大量的函数来处理图形的绘制,包括几何形状的定义、颜色设置、光照处理、纹理映射等。开发者通过OpenGL库调用这些函数,构建出复杂的图形场景。 在这个机械臂仿真程序中,C#被用来作为编程语言。C#通常与Windows平台上的.NET Framework配合使用,提供了一种面向对象的、类型安全的语言,支持现代编程特性如LINQ、异步编程等。结合OpenGL,C#可以构建高性能的图形应用。 机械臂的运动仿真涉及到几个关键的计算和控制概念: 1. **关节角度**:机械臂的每个部分(或关节)都有一个或多个自由度,表示为关节角度。这些角度决定了机械臂各部分的位置和方向。 2. **正向运动学**:根据关节角度计算机械臂末端执行器(如抓手)在空间中的位置和方向。这涉及将各个关节的角度转换为欧拉角或四元数,然后转化为笛卡尔坐标系的X、Y、Z位置和旋转。 3. **反向运动学**:给定末端执行器的目标位置和方向,计算出各关节所需的理想角度。这是一个逆向问题,通常需要解决非线性方程组。 4. **运动规划**:确定从当前状态到目标状态的路径,确保机械臂在运动过程中避免碰撞和其他约束。 5. **OpenGL的使用**:在OpenGL中,我们首先创建几何模型来表示机械臂的各个部分。然后,使用矩阵变换(如旋转、平移和缩放)来更新关节角度对模型的影响。这些变换组合起来,形成机械臂的动态运动。 6. **四向旋转**:机械臂可能有四个独立的旋转轴,允许它在X、Y、Z三个轴上旋转,以及额外的绕自身轴线的旋转。每个轴的旋转都由对应的关节角度控制。 7. **交互控制**:用户可能可以通过输入设备(如鼠标或键盘)调整关节角度,实时观察机械臂的运动。这需要将用户输入转换为关节角度,并应用到运动学模型中。 8. **图形渲染**:OpenGL提供了多种渲染技术,如深度测试、光照模型、纹理映射等,可以用于提高机械臂模拟的真实感。例如,可以添加材质和纹理来模拟金属表面,或者使用光照来增强立体感。 这个项目结合了OpenGL的图形渲染能力与C#的编程灵活性,构建了一个可以直观展示机械臂运动的仿真环境。通过理解并实现这些关键概念,开发者不仅能够学习到图形编程技巧,还能深入理解机器人学的基本原理。

    android11 udpate-engine 系统升级模块源码

    android11 udpate-engine 系统升级模块源码下载

    MATLAB环境下SVM二分类算法的实现与参数优化

    内容概要:本文详细介绍了如何在MATLAB环境中实现SVM二分类算法,涵盖数据预处理、参数寻优及结果可视化的全过程。首先进行数据归一化处理,确保各特征在同一量纲下参与模型训练。接着采用网格搜索法对SVM的关键参数c(惩罚系数)和g(核参数)进行自动化寻优,利用5折交叉验证评估每组参数的表现。最后通过等高线图和3D曲面图直观展示参数与准确率之间的关系,并完成最终模型的训练与预测。 适合人群:具有一定MATLAB编程基础的研究人员和技术爱好者,尤其是从事机器学习、数据分析领域的从业者。 使用场景及目标:适用于需要快速搭建SVM二分类模型并进行参数调优的项目。主要目标是在短时间内获得较高准确度的分类结果,同时掌握SVM的工作原理及其在MATLAB中的具体应用方法。 其他说明:文中提供了完整的代码示例,便于读者直接上手实践。此外还提到了一些常见的注意事项,如数据格式要求、类别不平衡处理以及特征工程的重要性等。

    ffmpeg liblame pcm转mp3教程.zip

    ffmpeg

    江科大CAN入门教程,万字长文理解

    江科大CAN入门教程,万字长文理解

    移动电源设计方案详解:基于新唐N79E814单片机的双路输出PCB设计与实现

    内容概要:本文详细介绍了基于新唐N79E814单片机的移动电源设计方案,涵盖硬件架构、PCB原理图、电路设计、代码实现等方面。移动电源主要由电池、充电电路和输出电路构成,文中重点讲解了5V1A和5V2.1A两路输出的设计思路,包括同步整流、PWM控制、充电管理等关键技术。同时,文章还探讨了PCB布局、烧录注意事项、效率优化等内容,并提供了具体的代码示例和调试建议。 适合人群:具有一定电子技术和单片机开发基础的工程师和技术爱好者。 使用场景及目标:适用于希望深入了解移动电源设计原理和实现方法的人群,旨在帮助读者掌握从原理图绘制到实际产品制作的全过程,提升电路设计和调试能力。 其他说明:文章不仅提供了理论知识,还包括大量实践经验分享,如常见的调试陷阱和解决方法,有助于读者在实践中少走弯路。

    动漫角色分割-基于深度学习实现的高精度动漫角色分割算法-附项目源码-优质项目实战.zip

    动漫角色分割_基于深度学习实现的高精度动漫角色分割算法_附项目源码_优质项目实战

    一款Java通过javacv实现的支持各种音视频播放的播放器项目源码

    javacv实现的支持多种音视频播放的播放器,比如MP4、avi、mkv、flv、MP3、ogg、wav、au等多种音视频格式,非常好用。

    浏览器插件+JS+自动登录+demo

    开发调试demo,简单的自动登录功能,插件开发入门参考

    【计算机管理与注册表编辑】Windows系统管理员工具与用户账户管理:本地用户和组、远程桌面配置及SAM权限设置,具体教学与批处理可私信我

    内容概要:本文详细介绍了通过修改Windows注册表来启用和配置被禁用的用户账户(如WDAGUtilityAccount)的过程。首先,通过计算机管理界面查看被禁用的用户账户,并进入注册表编辑器定位到HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users路径下的相应用户条目。接着,通过对特定用户的二进制数据进行编辑,包括复制和修改关键字段,实现对被禁用账户的克隆与重新启用。最后,验证账户状态的变化,并通过远程桌面连接测试新配置的有效性。 适合人群:具备一定Windows系统管理基础的技术人员,尤其是负责企业内部网络和用户账户管理的IT管理员。 使用场景及目标:①当需要恢复或重新配置被禁用的用户账户时;②在进行系统故障排除或安全审计时,了解如何通过注册表直接操作用户账户;③确保特定用户能够正常登录并访问远程桌面服务。 阅读建议:本文涉及较为底层的系统操作,建议读者在实际操作前充分备份系统和注册表,避免误操作导致系统不稳定。同时,对于不熟悉注册表编辑的用户,应先在测试环境中练习,确保掌握相关技能后再应用于生产环境。此外,建议结合官方文档或其他权威资料,加深对Windows用户账户管理机制的理解。

    新冠抗原自测平台 2025免费JAVA微信小程序毕设

    2025免费微信小程序毕业设计成品,包括源码+数据库+往届论文资料,附带启动教程和安装包。 启动教程:https://www.bilibili.com/video/BV1BfB2YYEnS 讲解视频:https://www.bilibili.com/video/BV1BVKMeZEYr 技术栈:Uniapp+Vue.js+SpringBoot+MySQL。 开发工具:Idea+VSCode+微信开发者工具。

    基于S7-1200 PLC的两部六层电梯控制系统设计与梯形图编程详解

    内容概要:本文详细介绍了基于西门子S7-1200 PLC的两部六层电梯控制系统的设计与实现。主要内容涵盖前期准备工作,如选择合适的PLC型号和配置硬件;核心逻辑部分深入讲解了梯形图编程的具体实现方法,包括楼层呼叫逻辑、电梯运行方向控制以及两部电梯之间的协同工作;此外,文章还探讨了仿真测试的方法及其重要性,提供了许多实用技巧和注意事项。通过具体实例展示了如何利用博途V15软件进行电梯系统的开发,并分享了一些实际操作中的经验和常见问题解决方案。 适合人群:从事工业自动化领域的工程师和技术人员,特别是那些对PLC编程有兴趣或者正在参与类似项目的从业者。 使用场景及目标:适用于需要理解和掌握S7-1200 PLC编程技能的人群,尤其是希望通过实际案例加深对梯形图编程理解的学习者。目标是在实践中提高编程能力,能够独立完成类似的工程项目。 其他说明:文中不仅包含了详细的理论解释,还有丰富的代码片段供读者参考。对于初学者而言,建议先从单部电梯开始练习,逐步过渡到复杂的双梯联调。同时,作者强调了仿真测试的重要性,指出这是验证程序正确性和优化性能的关键步骤。

    农产品自主供销系统 2025免费JAVA微信小程序毕设

    2025免费微信小程序毕业设计成品,包括源码+数据库+往届论文资料,附带启动教程和安装包。 启动教程:https://www.bilibili.com/video/BV1BfB2YYEnS 讲解视频:https://www.bilibili.com/video/BV1BVKMeZEYr 技术栈:Uniapp+Vue.js+SpringBoot+MySQL。 开发工具:Idea+VSCode+微信开发者工具。

    大学英语四级听力练习音频MP3

    内容概要:该资源为大学英语四级听力练习音频 MP3,包含丰富多样的听力素材。涵盖四级考试常见的各类场景,如校园生活(课程学习、社团活动等)、日常社交(聚会、聊天等)、工作求职(面试、职场事务等)、旅行交通(出行方式、景点介绍等)、饮食健康(餐厅点餐、健康养生等)。音频内容依照四级听力考试题型和难度精心录制,有短对话、长对话、短文听力等形式,且语速、口音等符合四级考试要求,助力考生熟悉考试形式与节奏。 适合人群:正在备考大学英语四级考试,希望提升听力水平的学生;英语基础中等,需要通过针对性练习来适应四级听力难度、提升听力理解能力的学习者;对英语听力学习有需求,想通过大量练习积累场景词汇、熟悉英语表达习惯的人群。 能学到什么:①熟悉四级听力考试的各类场景词汇,增强词汇储备并提升在听力语境中的反应速度;②掌握不同场景下的英语常用表达和句式,提升英语语言运用能力;③锻炼听力理解技巧,如抓取关键词、推断隐含意思、梳理篇章逻辑等;④适应四级听力考试的语速、口音和题型设置,增强应试能力和自信心。 阅读建议:制定系统的练习计划,定期定量进行听力练习,如每天安排 30 - 60 分钟;第一遍泛听,了解大致内容和主题;第二遍精听,逐句听写或分析不懂的词汇和句子;对照听力原文,明确错误和没听懂的地方,积累生词和表达;定期进行模拟测试,利用该音频模拟考试环境,检验学习效果并调整学习策略。

    2000-2017年各省天然气消费量数据

    2000-2017年各省天然气消费量数据 1、时间:2000-2017年 2、来源:国家统计j、能源nj 3、指标:行政区划代码、城市、年份、天然气消费量 4、范围:31省

    西门子PLC1200与库卡机器人协同控制系统的多设备集成方案

    内容概要:本文详细介绍了基于西门子PLC1200的自动化控制系统,涵盖了PLC与库卡机器人通过Profinet通讯、PTO模式控制松下伺服、36路模拟量处理(包括压力检测、位置检测及压力输出)、以及26个温控器通过485总线通讯的关键技术和实现方法。此外,还包括了昆仑通态触摸屏的人机交互界面设计,提供了详细的硬件组态、软件编程指导和设备操作说明。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些负责多设备协同控制项目的设计和实施的专业人士。 使用场景及目标:适用于需要整合多种设备(如PLC、机器人、伺服系统、温控器等)的复杂自动化生产线。主要目标是提高生产效率、增强系统的稳定性和可靠性,同时降低维护成本。 其他说明:文中不仅提供了具体的编程实例和硬件配置指南,还分享了许多实际调试过程中积累的经验教训,有助于读者在实际应用中少走弯路。

    汽车电子基于AUTOSAR的BSW层功能详解:服务、驱动、接口与管理器模块设计及应用了文档的主要内容

    内容概要:本文深入探讨了AUTOSAR BSW(Basic Software)层所提供的各类服务、驱动、接口和管理器模块及其功能。BSW提供的服务包括I/O、Memory、Crypto、Communication、Off-board Communication和System等,涵盖了标准化的访问方式以确保不同硬件和系统的兼容性与安全性。BSW里的驱动分为内部驱动和外部驱动,分别用于控制和访问微控制器内部和外部的设备,确保硬件功能的正常运作。BSW里的接口(xx_IF)对下层模块进行抽象和封装,提供标准API接口,使上层应用无需关注底层硬件细节。BSW里的管理器(xxxM)则为多个客户端提供特定服务,能够修改或适配调整一些数据,以满足复杂需求。此外,文中还简要介绍了AUTOSAR里的库文件,它们是无状态的函数集合,可被多个模块调用以实现特定功能。 适合人群:对汽车电子软件架构有一定了解,尤其是对AUTOSAR标准感兴趣的工程师和技术人员。 使用场景及目标:①理解BSW层提供的各类服务及其应用场景;②掌握BSW中驱动、接口和管理器模块的设计原理和功能;③了解库文件的作用及其在AUTOSAR架构中的位置。 其他说明:本文详细解释了BSW层各组件的功能和作用,帮助读者更好地理解AUTOSAR架构的设计思想和实现方法。建议读者结合实际项目经验,深入研究各模块的具体实现和应用场景。

Global site tag (gtag.js) - Google Analytics