Backbone前端框架核心及源码解析

Backbone前端框架核心及源码解析

Backbone是一款前端框架,它的核心是提供了MVC架构中Model(模型)和Collection(集合),以及View(视图)和Router(路由)的基础实现。Backbone的源码易读易懂,阅读源码可以对JavaScript编程有更深刻的理解。

1. Model和Collection

Model

Model表示前端程序中的业务模型。Model对象提供了数据的接口;保存数据,处理数据,触发对View(视图)的更新。在Backbone中,通过继承Backbone.Model来定义一个Model类,通过以下代码实现:

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

在定义了Model类之后,还要定义Model的实例,创建Model实例时可以通过定义默认的数据值:

var Book = Backbone.Model.extend({
  defaults: {
    title: 'unknown',
    author: 'unknown'
  }
});

var book1 = new Book({ title: 'The Lord of the Rings', author: 'J.R.R. Tolkien' });
console.log(book1.get('title')); // "The Lord of the Rings"
console.log(book1.get('author')); // "J.R.R. Tolkien"

Collection

Collection表示一组Model对象。Collection把Model视为一个整体,可以进行Model的批量操作。在Backbone中,通过继承Backbone.Collection来定义一个Collection类,通过以下代码实现:

var Books = Backbone.Collection.extend({
  model: Book
});

在定义了Collection类之后,还要定义Collection的实例,可以通过add()和remove()方法操作Collection对象:

var books = new Books();

var book1 = new Book({ title: 'The Lord of the Rings', author: 'J.R.R. Tolkien' });
var book2 = new Book({ title: 'The Hobbit', author: 'J.R.R. Tolkien' });
var book3 = new Book({ title: 'Harry Potter and the Philosopher\'s Stone', author: 'J.K. Rowling' });

books.add(book1);
books.add(book2);
books.add(book3);

console.log(books.length); // 3

books.remove(book2);
console.log(books.length); // 2

2. View和Router

View

View表示前端程序中的用户界面。View对象接收Model数据,通过模板引擎将数据渲染成html,然后更新到指定的DOM元素上。在Backbone中,通过继承Backbone.View来定义一个View类,通过以下代码实现:

var BookView = Backbone.View.extend({
  tagName: 'div',
  className: 'book-item',
  template: _.template('<h2><%= title %></h2><p><%= author %></p>'),

  initialize: function () {
    this.listenTo(this.model, 'change', this.render);
  },

  render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
  }
});

在定义了View类之后,还要定义View的实例,通过指定el属性来指定渲染后的html插入到哪个DOM元素内部:

var book1 = new Book({ title: 'The Lord of the Rings', author: 'J.R.R. Tolkien' });
var bookView = new BookView({ model: book1 });
$('#app').append(bookView.el);

Router

Router负责页面的路由控制和处理。Router对象监听URL变化(hashchange事件),响应URL变化,收集路由参数,调用对应的Controller方法。在Backbone中,通过继承Backbone.Router来定义一个Router类,通过以下代码实现:

var AppRouter = Backbone.Router.extend({
  routes: {
    'books/:id': 'showBook'
  },

  showBook: function (id) {
    var book = books.get(id);
    var bookView = new BookView({ model: book });
    $('#app').html(bookView.el);
  }
});

在定义了Router类之后,还要定义Router的实例,启动Backbone的history:

var router = new AppRouter();
Backbone.history.start();

使用hash值#books/123访问页面,Router会捕捉到books/:id的URL,调用对应的showBook方法。showBook方法获取该book的模型数据,使用BookView进行渲染,最后更新到指定的DOM元素上。

3. 示例

示例1:一个简单的待办事项列表

var Todo = Backbone.Model.extend({
  defaults: function () {
    return {
      title: '',
      completed: false
    };
  },

  toggle: function () {
    this.save({
      completed: !this.get('completed')
    });
  }
});

var TodoList = Backbone.Collection.extend({
  model: Todo,

  localStorage: new Backbone.LocalStorage('todos-backbone'),

  completed: function () {
    return this.where({ completed: true });
  },

  remaining: function () {
    return this.where({ completed: false });
  }
});

var Todos = new TodoList();

var TodoView = Backbone.View.extend({
  tagName: 'li',

  template: _.template('<span class="title"><%= title %></span>'),

  events: {
    'click .title': 'toggleCompleted'
  },

  initialize: function () {
    this.listenTo(this.model, 'change', this.render);
  },

  render: function () {
    this.$el.toggleClass('completed', this.model.get('completed'));
    this.$el.html(this.template(this.model.toJSON()));
    return this;
  },

  toggleCompleted: function () {
    this.model.toggle();
  }
});

var AppView = Backbone.View.extend({
  el: '#app',

  statsTemplate: _.template('<span><%= remaining %> items left</span><span><%= completed %> items completed</span>'),

  events: {
    'keypress input': 'addTodo'
  },

  initialize: function () {
    this.$input = this.$('input');
    this.$list = this.$('#todo-list');

    this.listenTo(Todos, 'add', this.addTodoView);
    this.listenTo(Todos, 'reset', this.addAll);
    this.listenTo(Todos, 'change:completed', this.filterOne);
    this.listenTo(Todos, 'filter', this.filterAll);

    Todos.fetch({ reset: true });
  },

  render: function () {
    this.$list.empty();

    Todos.each(function (todo) {
      var view = new TodoView({ model: todo });
      this.$list.append(view.render().el);
    }, this);

    this.renderStats();
  },

  renderStats: function () {
    var completed = Todos.completed().length;
    var remaining = Todos.remaining().length;
    this.$('#todo-stats').html(this.statsTemplate({ completed: completed, remaining: remaining }));
  },

  addTodo: function (e) {
    if (e.keyCode != 13) return;
    if (!this.$input.val().trim()) return;

    Todos.create({ title: this.$input.val().trim() });
    this.$input.val('');
  },

  addTodoView: function (todo) {
    var view = new TodoView({ model: todo });
    this.$list.append(view.render().el);
  },

  addAll: function () {
    Todos.each(this.addTodoView, this);
  },

  filterOne: function (todo) {
    TodoView.hide(todo.get('completed'));
  },

  filterAll: function () {
    Todos.each(this.filterOne, this);
  }
});

var App = new AppView();

在HTML中添加必要的DOM元素:

<body>
  <div id="app">
    <input type="text" placeholder="What need to be done?">
    <span id="todo-stats"></span>
    <ul id="todo-list"></ul>
  </div>
</body>

示例2:简单路由控制

var HomePageView = Backbone.View.extend({
  el: '#app',

  template: _.template('<h1>Backbone Home Page</h1>'),

  render: function () {
    this.$el.html(this.template());
    return this;
  }
});

var AboutPageView = Backbone.View.extend({
  el: '#app',

  template: _.template('<h1>About Us</h1><p>This is the about us page</p>'),

  render: function () {
    this.$el.html(this.template());
    return this;
  }
});

var AppRouter = Backbone.Router.extend({
  routes: {
    '': 'home',
    'about': 'about'
  },

  home: function () {
    var homePageView = new HomePageView();
    homePageView.render();
  },

  about: function () {
    var aboutPageView = new AboutPageView();
    aboutPageView.render();
  }
});

var router = new AppRouter();
Backbone.history.start();

在HTML中添加必要的DOM元素:

<body>
  <div id="app"></div>
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#about">About Us</a></li>
  </ul>
</body>

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Backbone前端框架核心及源码解析 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • JavaScript ES6 Class类实现原理详解

    下面是关于JavaScript ES6 Class类实现原理的详细攻略。 什么是ES6 Class ES6引入了Class关键字,通过它可以使用类的方式来编写JavaScript代码,使得代码更加可读性强,易于维护和重构。 一个基础的ES6类的定义方式如下: class Person { constructor(name, age) { this.name …

    JavaScript 2023年5月28日
    00
  • Java 面试题和答案 -(上)

    让我详细讲解一下“Java 面试题和答案 -(上)”的完整攻略。 标题 首先,我们需要为文章设置一个标题。根据文章内容,我建议将标题设置为“Java 面试题和答案 -(上)完整攻略”。 内容 接下来,我们可以按照以下步骤来编写文章内容: 介绍Java面试题的重要性以及面试的基本流程。 列举10道常见的Java面试题,此处不仅需要列举问题,也需要对每个问题进行…

    JavaScript 2023年5月28日
    00
  • JavaScript的Proxy对象详解

    JavaScript的Proxy对象详解 什么是Proxy对象 Proxy 是 ES6 新增的语法,它允许你在外部控制对象和函数的访问行为。可以说,Proxy 是以对象为基础的 元编程 ,使得我们可以编写出更加可复用,更加通用的 Javascript 代码。 创建一个Proxy对象 可以使用 new 操作符来创建一个 Proxy 对象,其中第一个参数为需要代…

    JavaScript 2023年5月28日
    00
  • 原生JavaScript编写俄罗斯方块

    编写俄罗斯方块是一个非常有趣和实用的JavaScript项目。以下是一些步骤和示例代码,可以帮助您开始编写自己的俄罗斯方块游戏。 步骤一:创建HTML文件 首先,我们需要创建一个HTML文件,在其中添加一个canvas元素来展示俄罗斯方块游戏。以下是一个示例HTML文件: <!DOCTYPE html> <html> <head…

    JavaScript 2023年6月10日
    00
  • js实例之01支付后的10秒倒计时

    这是一个通过js实现的支付后的页面,点击支付会跳出一个弹窗,提示你是否要确定支付,确定后进入付后界面,该页面有着10秒倒计时,计时结束后便会返回原界面。也可以选择立刻返回,来返回主页面第一个zhifu.html页面<!DOCTYPE html> <html lang=”en”> <head> <meta charse…

    JavaScript 2023年4月18日
    00
  • js中function()使用方法

    下面是对于”js中function()使用方法”的完整攻略。 什么是function()? 在javascript中,function()是定义函数的关键字,通俗点说,就是把一些代码块打包起来,然后给它们命名,可以在后面的代码中可以通过这个名字来调用这一块代码。我们通常称这些代码块为函数,而通过函数调用,我们就能够复用这一段代码,并且在不同的场景下使用。 函…

    JavaScript 2023年5月27日
    00
  • JS获取单击按钮单元格所在行的信息

    获取单元格所在行的信息一般需要以下步骤: 对表格中的按钮进行事件绑定 在事件绑定的回调函数中获取按钮所在的单元格元素td 获取单元格所在的行元素tr 根据需要获取行元素tr中的其他信息 以下是两条示例: 示例一 HTML代码: <table> <thead> <tr> <th>ID</th> &lt…

    JavaScript 2023年6月11日
    00
  • javascript开发随笔二 动态加载js和文件

    我将详细讲解一下“javascript开发随笔二 动态加载js和文件”的完整攻略。 什么是动态加载js和文件? 动态加载指的是在页面运行时动态地加载一些脚本或文件。相比静态加载,在需要的时候才加载脚本或文件,可以有效提高页面的加载速度和响应速度。 如何动态加载js和文件? 动态加载js脚本 要动态加载一个js脚本,可以使用document.createEle…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部