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

yizhihongxing

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日

相关文章

  • JS中对数组元素进行增删改移的方法总结

    下面是JS中对数组元素进行增删改移的方法总结的完整攻略: 一、添加元素 1. push() push() 方法向数组的末尾添加一个或多个元素,并返回新的长度。 let arr = [1, 2, 3]; arr.push(4); console.log(arr); // [1, 2, 3, 4] 2. unshift() unshift() 方法向数组的开头添…

    JavaScript 2023年5月27日
    00
  • VUE脚手架框架编写简洁的登录界面的实现

    关于“VUE脚手架框架编写简洁的登录界面”的实现攻略,可以分为以下几个步骤来进行: 1. 创建Vue项目 首先,在命令行中输入以下命令,创建一个Vue项目: vue create my-project 其中my-project为项目名称,你可以自行替换。 创建完成之后,进入项目目录: cd my-project 2. 添加路由及登录页面组件 接下来,我们需要…

    JavaScript 2023年6月11日
    00
  • 教你轻松记住JS正则表达式

    下面是 “教你轻松记住JS正则表达式” 的完整攻略。 一、正则表达式 正则表达式是一种可以用于匹配文本特定模式的表达式,也可称之为正则或RegExp。JavaScript 支持正则表达式,其构造函数即RegExp。 1.1 正则表达式的构造函数 在 JavaScript 中 RegExp 是正则表达式的构造函数,我们可以使用它创建正则表达式,语法如下: va…

    JavaScript 2023年6月10日
    00
  • js和as的稳定传值问题解决

    下面是 “js和as的稳定传值问题解决”的完整攻略。 问题描述 在从JS向AS3进行通讯时,为了保证数据的正确和稳定传递,需要使用ExternalInterface.call 和 ExternalInterface.addCallback 方法进行数据的传递。但是,在使用过程中,发现有些情况下这些方法并不总是稳定的。 解决方法 为了解决传递数据的稳定性问题,…

    JavaScript 2023年6月11日
    00
  • 深入理解vue的使用

    深入理解Vue的使用 Vue是一款轻量级、易上手的JavaScript框架,它具有数据双向绑定、组件化、虚拟DOM等功能,被广泛应用于前端开发中。本攻略旨在深入理解Vue的使用,包含以下几个方面的内容: Vue实例的创建与生命周期 数据双向绑定与计算属性 组件化与动态组件 父子组件通信 插槽的使用 vue-router的使用 Vue实例的创建与生命周期 Vu…

    JavaScript 2023年6月11日
    00
  • JavaScript页面实时显示当前时间实例代码

    下面是JavaScript页面实时显示当前时间的攻略。 前提要求 在编写JavaScript实时显示时间的代码之前,需要了解一些前提知识,包括: HTML基础知识和标记语言 JavaScript基础知识和语法 Date()对象详解 实时显示当前时间代码步骤 以下是实时显示当前时间的实现步骤: 在HTML文件中创建一个用于显示时间的容器,为其设置一个ID,如下…

    JavaScript 2023年5月27日
    00
  • JavaScript中eval和with语句如何影响作用域链的深度探索

    让我详细讲解一下“JavaScript中eval和with语句如何影响作用域链的深度探索”。 什么是作用域链 在深入探索eval和with语句影响作用域链之前,我们需要了解一下什么是作用域链。 作用域链是JavaScript中的一个重要概念,它是一种链式结构,用于描述变量和函数的可见性和访问性。当我们访问一个变量或函数时,JavaScript引擎首先在当前作…

    JavaScript 2023年6月11日
    00
  • js中的setInterval和setTimeout使用实例

    JS中的setInterval和setTimeout使用实例 在JS中,setInterval和setTimeout是两个常用的计时器函数。它们可以根据指定的时间间隔或延迟来进行周期性的或单次的定时操作。下面,我们将详细讲解这两个函数的使用实例。 1. setInterval的使用实例 setInterval函数用于周期性地执行代码,它接收两个参数:第一个参…

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