PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/backbone学习笔记.txt

https://github.com/cgg5207/StudyNotes
Plain Text | 612 lines | 509 code | 103 blank | 0 comment | 0 complexity | 539454f56825e75c84d2fff2385fb379 MD5 | raw file
  1. Backbone.Events
  2. #Events
  3. //继承Backbone.Events, 所有对象都有了on 和 trigger, 还可以传参数
  4. var object = {};
  5. _.extend(object, Backbone.Events);
  6. object.on("alert", function(msg) {
  7. alert("Triggered " + msg);
  8. });
  9. object.trigger("alert", "an event");
  10. var dispatcher = _.clone(Backbone.Events); //用这种方式可以把Backbone.Events clone出来,不容易弄乱原来的Class
  11. #on object.on(event, callback, [context])
  12. object.on("change:title change:author", ...) //可以用空格绑定多个event
  13. model.on("change", this.func, this) //要绑定this的话可以在第三个参数放context
  14. 如果绑定了"all"event的话那这个对象在trigger任何事件的时候都会trigger这个event
  15. 还可以这样去绑定多个事件对应多个func
  16. model.on({
  17. "change": change,
  18. "help": help
  19. });
  20. 还有只绑定一次的once
  21. #off object.off([event], [callback], [context])
  22. #listenTo 监听其他对象的事件响应
  23. view.listenTo(model, 'change', view.render);
  24. #stopListening object.stopListening([other], [event], [callback])
  25. #listenToOnce object.listenToOnce(other, event, callback)
  26. #Backbone model 里面的events
  27. "add" (model, collection, options) when a model is added to a collection.
  28. "remove" (model, collection, options) when a model is removed from a collection.
  29. "reset" (collection, options) when the collection's entire contents have been replaced.
  30. "sort" (collection, options) when the collection has been re-sorted.
  31. "change" (model, options) when a model's attributes have changed.
  32. "change:[attribute]" (model, value, options) when a specific attribute has been updated.
  33. "destroy" (model, collection, options) when a model is destroyed.
  34. "request" (model, xhr, options) when a model (or collection) has started a request to the server.
  35. "sync" (model, resp, options) when a model (or collection) has been successfully synced with the server.
  36. "error" (model, xhr, options) when a model's save call fails on the server.
  37. "invalid" (model, error, options) when a model's validation fails on the client.
  38. "route:[name]" (params) Fired by the router when a specific route is matched.
  39. "route" (router, route, params) Fired by history (or router) when any route has been matched.
  40. "all" this special event fires for any triggered event, passing the event name as the first argument.
  41. 如果在model.set() collection.add()这类方法不想trigger到上面的event可以传个{slient: true}的参数
  42. Backbone.Model
  43. example:
  44. var Sidebar = Backbone.Model.extend({
  45. promptColor: function() {
  46. var cssColor = prompt("Please enter a CSS color:");
  47. this.set({color: cssColor});
  48. }
  49. });
  50. window.sidebar = new Sidebar;
  51. sidebar.on('change:color', function(model, color) { //属性改变后的function
  52. $('#sidebar').css({background: color});
  53. });
  54. sidebar.set({color: 'white'});
  55. sidebar.promptColor();
  56. #extend
  57. var Note = Backbone.Model.extend({
  58. initialize: function() { ... },
  59. author: function() { ... },
  60. coordinates: function() { ... },
  61. allowedToEdit: function(account) {
  62. return true;
  63. }
  64. });
  65. var PrivateNote = Note.extend({ //可以继承自己创建的Model
  66. allowedToEdit: function(account) {
  67. return account.owns(this);
  68. }
  69. });
  70. 如果继承的时候要用super覆写方法的话要明确指定方法路径
  71. var Note = Backbone.Model.extend({
  72. set: function(attributes, options) {
  73. Backbone.Model.prototype.set.apply(this, arguments);
  74. }
  75. });
  76. #constructor /intialize
  77. 要设定实例变量直接在new的时候传入即可Model里面的intialize方法就是构造函数
  78. {url: "...."} {urlRoot: "....."}可以自己定义model的restful URL
  79. #get
  80. model.get("fuck") //model里面get属性
  81. #set
  82. model.set({fuck: "fuck you"}) //set 属性
  83. 会trigger model的"change"事件还会trigger详细到 "change:fuck" 这个事件
  84. #escape 类似get(), 但会把属性转义成html可显示的内容例如<>这些符号
  85. #has(attribute) 判断model里面的attribute是不是空或undefined
  86. #unset 会把某个attribute直接移除出model attributes hash, trigger "change"
  87. #clear 全部attribute清掉
  88. #id 默认有的属性如果自己设的attributes里面也包含这个id属性则会把原来id的内容拷过去
  89. #idAttribute方便指定哪一个key属性作为id例如nosql里面的mongoid的id是_id
  90. var Meal = Backbone.Model.extend({
  91. idAttribute: "_id"
  92. });
  93. var cake = new Meal({ _id: 1, name: "Cake" });
  94. alert("Cake id: " + cake.id);
  95. #cid 这个东西跟spine的一样就是model未保存时还在内存或者storage里面时用得client_id
  96. #attributes 返回所有属性的一个hash
  97. #changed 返回最后一个trigger过的changed 的属性hash
  98. #defaults 用于在model创建时设定一堆默认属性和值
  99. var Meal = Backbone.Model.extend({
  100. defaults: {
  101. "appetizer": "caesar salad",
  102. "entree": "ravioli",
  103. "dessert": "cheesecake"
  104. }
  105. });
  106. alert("Dessert will be " + (new Meal).get('dessert'));
  107. #toJSON
  108. var artist = new Backbone.Model({
  109. firstName: "Wassily",
  110. lastName: "Kandinsky"
  111. });
  112. artist.set({birthday: "December 16, 1866"});
  113. alert(JSON.stringify(artist)); //本来只是返回一个json object, 最好用JSON.stringify去变成json string
  114. #sync model.sync(method, model, [options]) //用于持久化同步
  115. #fetch 比spine可定制强很多返回一个jqXHR对象可以接受success或error的callback, 参数是(model, response, options)
  116. #save model.save([attributes], [options])
  117. 如果用ajax成功的话返回一个jqXHR, 失败的话返回false, 如果model isNew,就create, otherwise update
  118. options hash里面可以直接传{success:function(model, xhr, options){}} 这样直接可以第一时间得到返回来的东西
  119. 如果想只想更新了更新的部分可以model.save(attrs,{patch: true}), 这样会有一个PATCH请求动作给HTTP
  120. !! model.save(attrs, {wate: true}),等服务器保存完才把model设值这样可以保证数据绝对同步
  121. 关于事件save成功后会trigger "change", ajax 刚开时的时候会 trigger "request", 这个很有用可以给用户提示 ajax完成后会有个 "sync"事件
  122. 一个例子
  123. Backbone.sync = function(method, model) {
  124. alert(method + ": " + JSON.stringify(model));
  125. model.id = 1;
  126. };
  127. var book = new Backbone.Model({
  128. title: "The Rough Riders",
  129. author: "Theodore Roosevelt"
  130. });
  131. book.save();
  132. book.save({author: "Teddy"});
  133. #destroy
  134. 事件和调用方式基本类似save()
  135. #包含underscore 的几个方法
  136. keys
  137. values
  138. pairs
  139. invert
  140. pick
  141. omit
  142. user.pick('first_name', 'last_name', 'email');
  143. chapters.keys().join(', ');
  144. #validate
  145. 在save之前触发, validate不通过时会trigger "invalid", 然后model.validationError 会得到错误的信息
  146. var Chapter = Backbone.Model.extend({
  147. validate: function(attrs, options) {
  148. if (attrs.end < attrs.start) {
  149. return "can't end before it starts";
  150. }
  151. }
  152. });
  153. var one = new Chapter({
  154. title : "Chapter One: The Beginning"
  155. });
  156. one.on("invalid", function(model, error) {
  157. alert(model.get("title") + " " + error);
  158. });
  159. one.save({
  160. start: 15,
  161. end: 10
  162. });
  163. #validationError 上面写了
  164. #isValid 判断model是不是valid
  165. #url model.url()
  166. 可以用urlRoot去设定或直接在model初始化的时候设个url属性
  167. #urlRoot
  168. 如果你的model不是在collection里头的, 就需要设定一下urlRoot属性
  169. var Book = Backbone.Model.extend({urlRoot : '/books'});
  170. var solaris = new Book({id: "1083-lem-solaris"});
  171. alert(solaris.url());
  172. #parse
  173. 返回一个 raw response对象会在fetch或save的时候调用可以覆写他
  174. #clone
  175. 返回model的克隆
  176. #isNew()
  177. 未在服务器保存的就是true
  178. #hasChanged
  179. 上一次"change"事件后有无发生变化
  180. #previous model.previous(attribute)
  181. "change"事件中可以获取上一次"change"时候的属性
  182. var bill = new Backbone.Model({
  183. name: "Bill Smith"
  184. });
  185. bill.on("change:name", function(model, name) {
  186. alert("Changed name from " + bill.previous("name") + " to " + name);
  187. });
  188. bill.set({name : "Bill Jones"});
  189. #previousAttributes
  190. Backbone.Collection
  191. 在collection下面的所有model "change"的话都会trigger collection的"change", 还有 "add", "remove"等事件, model里面的所有属性事件发生都会在collection里面trigger多一份 documents.on("change:selected", ...)
  192. #extend
  193. #model
  194. 设这个方法可以快速设定下属的model
  195. var Library = Backbone.Collection.extend({
  196. model: Book
  197. });
  198. 还可以多态式添加model
  199. var Library = Backbone.Collection.extend({
  200. model: function(attrs, options) {
  201. if (condition) {
  202. return new PublicDocument(attrs, options);
  203. } else {
  204. return new PrivateDocument(attrs, options);
  205. }
  206. }
  207. });
  208. #初始化可以在初始化的时候就扔进model实例或者只设定model的class
  209. var tabs = new TabSet([tab1, tab2, tab3]);
  210. var spaces = new Backbone.Collection([], {
  211. model: Space,
  212. url: '/spaces'
  213. });
  214. #models 返回所有model的array
  215. #toJSON 返回array JSON
  216. #sync 类似model
  217. #underscore method
  218. forEach (each)
  219. map (collect)
  220. reduce (foldl, inject)
  221. reduceRight (foldr)
  222. find (detect)
  223. filter (select)
  224. reject
  225. every (all)
  226. some (any)
  227. contains (include)
  228. invoke
  229. max
  230. min
  231. sortBy
  232. groupBy
  233. sortedIndex
  234. shuffle
  235. toArray
  236. size
  237. first (head, take)
  238. initial
  239. rest (tail)
  240. last
  241. without
  242. indexOf
  243. lastIndexOf
  244. isEmpty
  245. chain
  246. books.each(function(book) {
  247. book.publish();
  248. });
  249. var titles = books.map(function(book) {
  250. return book.get("title");
  251. });
  252. var publishedBooks = books.filter(function(book) {
  253. return book.get("published") === true;
  254. });
  255. var alphabetical = books.sortBy(function(book) {
  256. return book.author.get("name").toLowerCase();
  257. });
  258. #add collection.add(models, [options])
  259. 如果options传个{at: index} 的话model就会加到响应的位置 这个在排序的情况下十分好用, 一般collection里面已有的model, 再add进来的话就会被忽略但是可以给个{merge: true}就可以实现merge, 更新model的属性
  260. var ships = new Backbone.Collection;
  261. ships.on("add", function(ship) {
  262. alert("Ahoy " + ship.get("name") + "!");
  263. });
  264. ships.add([
  265. {name: "Flying Dutchman"},
  266. {name: "Black Pearl"}
  267. ]);
  268. #remove collection.remove(models, [options])
  269. trigger "remove", 可以给个 slient: true 去不trigger
  270. #reset collection.reset([models], [options])
  271. 重设collection里面的所有model, 会trigger "reset", 在事件响应的options里面options.previousModels可以拿到之前的所有model
  272. 在页面onload的时候把整个accounts的collection重设一下
  273. <script>
  274. var accounts = new Backbone.Collection;
  275. accounts.reset(<%= @accounts.to_json %>);
  276. </script>
  277. #set collection.set(models, [options])
  278. model未在集合里时会create 在的时候会update(merge: true), 会响应响应"remove", "add" , "change"的事件可以细致定义到{remove: false} {add: false} {merge: false}
  279. var vanHalen = new Collection([eddie, alex, stone, roth]);
  280. vanHalen.set([eddie, alex, stone, hagar]);
  281. // Fires a "remove" event for roth, and an "add" event for "hagar".
  282. // // Updates any of stone, alex, and eddie's attributes that may have
  283. // // changed over the years.
  284. #get collection.get(id)
  285. 从id或cid里那model
  286. #at collection.at(index)
  287. 拿到某个位置的model
  288. #push
  289. 在collection最后加model
  290. #unshift
  291. 在头部add一个
  292. #shift
  293. 删除头部的model
  294. #length
  295. #comparator collection.comparator
  296. 主要给sortBy功能提供支持
  297. var Chapter = Backbone.Model;
  298. var chapters = new Backbone.Collection;
  299. chapters.comparator = function(chapter) {
  300. return chapter.get("page");
  301. };
  302. chapters.add(new Chapter({page: 9, title: "The End"}));
  303. chapters.add(new Chapter({page: 5, title: "The Middle"}));
  304. chapters.add(new Chapter({page: 1, title: "The Beginning"}));
  305. alert(chapters.pluck('title'));
  306. #sort
  307. trigger "sort"
  308. #pluck
  309. #where
  310. var friends = new Backbone.Collection([
  311. {name: "Athos", job: "Musketeer"},
  312. {name: "Porthos", job: "Musketeer"},
  313. {name: "Aramis", job: "Musketeer"},
  314. {name: "d'Artagnan", job: "Guard"},
  315. ]);
  316. var musketeers = friends.where({job: "Musketeer"});
  317. alert(musketeers.length);
  318. #findWhere
  319. 和where区别就是只返回匹配到的第一个
  320. #url
  321. var Notes = Backbone.Collection.extend({
  322. url: '/notes'
  323. });
  324. // Or, something more sophisticated:
  325. var Notes = Backbone.Collection.extend({
  326. url: function() {
  327. return this.document.url() + '/notes';
  328. }
  329. });
  330. }
  331. });
  332. #parse 类似model
  333. #clone
  334. #fetch
  335. 这个比model多了就是可以pass jqery.ajax data, 可以分页
  336. documents.fetch({data: {page: 3}})
  337. #create
  338. 响应事件顺序, "add" , "request" , "sync"
  339. var Library = Backbone.Collection.extend({
  340. model: Book
  341. });
  342. var nypl = new Library;
  343. var othello = nypl.create({
  344. title: "Othello",
  345. author: "William Shakespeare"
  346. });
  347. Backbone.Router
  348. 路由都创建成功后记得运行Backbone.history.start() or Backbone.history.start({pushState: true})
  349. 创建example
  350. var Workspace = Backbone.Router.extend({
  351. routes: {
  352. "help": "help", // #help
  353. "search/:query": "search", // #search/kiwis
  354. "search/:query/p:page": "search" // #search/kiwis/p7
  355. },
  356. help: function() {
  357. ...
  358. },
  359. search: function(query, page) {
  360. ...
  361. }
  362. })
  363. #route router.route(route, name, [callback])
  364. #navigate router.navigate(fragment, [options])
  365. 用于更新路由的url, 如果想同时触发路由options传个trigger: true
  366. openPage: function(pageNumber) {
  367. this.document.pages.at(pageNumber).open();
  368. this.navigate("page/" + pageNumber);
  369. }
  370. app.navigate("help/troubleshooting", {trigger: true});
  371. app.navigate("help/troubleshooting", {trigger: true, replace: true});
  372. Backbone.history
  373. backbone的pushState可以帮你自动识别好是否支持pushState浏览器问题 用start()方法去检测浏览器hashchange 事件
  374. $(function(){
  375. new WorkspaceRouter();
  376. new HelpPaneRouter();
  377. Backbone.history.start({pushState: true});
  378. });
  379. Backbone.sync 就只是一个jqueryAjax的包装
  380. #sync sync(method, model, [options])
  381. Backbone.View
  382. var DocumentRow = Backbone.View.extend({
  383. tagName: "li",
  384. className: "document-row",
  385. events: {
  386. "click .icon": "open",
  387. "click .button.edit": "openEditDialog",
  388. "click .button.delete": "destroy"
  389. },
  390. initialize: function() {
  391. this.listenTo(this.model, "change", this.render);
  392. }
  393. render: function() {
  394. ...
  395. }
  396. });
  397. 创建的时候传入的参数会在实例变量 @options里面
  398. # view.el
  399. 类似spine的el, 但是backbone在你初始化时如果指定好tagName, id, className, backbone会自动帮你定义好el
  400. # view.$el
  401. 很方便的el cache可以读回之前的dom避免次次重新运算一次
  402. view.$el.show();
  403. listView.$el.append(itemView.el);
  404. #delegateEvents 主要是用jquery的on
  405. 可以在events上轻松定义
  406. var DocumentView = Backbone.View.extend({
  407. events: {
  408. "dblclick" : "open",
  409. "click .icon.doc" : "select",
  410. "contextmenu .icon.doc" : "showMenu",
  411. "click .show_notes" : "toggleNotes",
  412. "click .title .lock" : "editAccessLevel",
  413. "mouseover .title .date" : "showTooltip"
  414. },
  415. render: function() {
  416. this.$el.html(this.template(this.model.attributes));
  417. return this;
  418. },
  419. open: function() {
  420. window.open(this.model.get("viewer_url"));
  421. },
  422. select: function() {
  423. this.model.set({selected: true});
  424. },
  425. });
  426. Backbone.LocalStoreage
  427. var TodoList = Backbone.Collection.extend({
  428. model: Todo,
  429. localStorage: new Backbone.LocalStorage("todos-backbone")
  430. });
  431. ##### ModelBinder #####
  432. https://github.com/theironcook/Backbone.ModelBinder
  433. 作用是可以方便绑定model的attribute到 html element, 只要html标签里面有name="xxx", 绑定后更新model属性这个标签的内容也会跟着更改
  434. 三个public方法
  435. constructor
  436. bind(model, rootEl, bindings)
  437. unbind();
  438. //////例子1
  439. Welcome, <span name="firstName"></span>
  440. Edit your information:
  441. <input type="text" name="firstName"/>
  442. SomeView = Backbone.View.extend({
  443. render: function(){
  444. this.modelBinder.bind(this.model, this.el);
  445. }
  446. });
  447. 这里绑定好firstName到model input里面改变了 上面的span也会修改
  448. //////////例子2
  449. <input type="text" name="homeAddress"/>
  450. <input type="text" name="workAddress "/>
  451. var bindings = {homeAddress: '[name=homeAddress]', workAddress : '[name=workAddress ]'};
  452. modelBinder.bind(this.model, this.el, bindings);
  453. 第三个参数bindings示例可以同时绑定多个attribute, 当然除了name=xxx这种选择器还可以使用#id这种jquery选择器
  454. 还可以这样
  455. <input type="text" class="myTestClass" name="address"/> myTestAttribute: '[class~=myTestClass]'
  456. bindings参数还可以放个converter,这个converter要求是个function可以让你自定义如何格式化值
  457. var phoneConverter = function(direction, value){
  458. // direction is either ModelToView or ViewToModel
  459. // Return either a formatted value for the view or an un-formatted value for the model
  460. };
  461. var bindings = {phoneNumber: {selector: '[name=phoneNumber]', converter: phoneConverter}}
  462. modelBinder.bind(this.model, this.el, bindings );
  463. A converter function is passed 4 parameters.
  464. Direction - either ModelToView or ViewToModel
  465. Value - the model's attribute value or the view element's value
  466. Attribute Name
  467. Model - this is more useful when you're dealing with calculated attributes
  468. #给每个collection的model加属性
  469. pages = new PagesCollection()
  470. pages.fetch()
  471. pages.invoke("set", {h: 123})
  472. 然后每一个page都可以 page.get("h")
  473. --------------------------
  474. Eckbone.EventBinder();
  475. var model = new MyModel();
  476. var handler = {
  477. doIt: function(){ /* ... */ }
  478. }
  479. // same args list as model.on, but putting the model as the first parameter
  480. binder.bindTo(model, "change:foo", handler.doIt, handler) 第四个参数是callback的context
  481. 所以以后注意路由要这样写, 添加一个appView去决定切换的时候把前一个view close掉
  482. function AppView(){
  483. this.showView(view) {
  484. if (this.currentView){
  485. this.currentView.close();
  486. }
  487. this.currentView = view;
  488. this.currentView.render();
  489. $("#mainContent").html(this.currentView.el);
  490. }
  491. }
  492. MyRouter = Backbone.Router.extend({
  493. routes: {
  494. "": "home",
  495. "post/:id": "showPost"
  496. },
  497. initialize: function(options){
  498. this.appView = options.appView;
  499. },
  500. home: function(){
  501. var homeView = new HomeView();
  502. this.appView.showView(homeView);
  503. },
  504. showPost: function(id){
  505. var post = posts.get(id);
  506. var postView = new PostView({model: post});
  507. this.appView.showView(postView);
  508. }
  509. });