Backbone.js MVC架构理解 #

一、MVC模式概述 #

1.1 什么是MVC #

MVC(Model-View-Controller)是一种软件架构模式,将应用程序分为三个核心组件:

text
┌─────────────────────────────────────────────────────────┐
│                        MVC模式                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│    ┌─────────┐         ┌───────────┐                   │
│    │  Model  │◄───────►│    View   │                   │
│    │  (模型) │         │   (视图)  │                   │
│    └────┬────┘         └─────┬─────┘                   │
│         │                    │                          │
│         │                    │                          │
│         ▼                    ▼                          │
│    ┌─────────────────────────────────┐                 │
│    │         Controller              │                 │
│    │         (控制器)                │                 │
│    └─────────────────────────────────┘                 │
│                                                         │
└─────────────────────────────────────────────────────────┘

1.2 MVC各组件职责 #

组件 职责 Backbone对应
Model 管理数据、业务逻辑 Backbone.Model
View 展示数据、用户界面 Backbone.View
Controller 处理用户输入、协调Model和View Router + View

1.3 Backbone的MVC变体 #

Backbone.js 实际上采用的是 MVP(Model-View-Presenter)或 MVVM 的变体:

text
Backbone架构
├── Model:数据层
├── Collection:数据集合层
├── View:视图层 + 控制器逻辑
└── Router:路由控制层

二、Backbone组件关系 #

2.1 组件交互图 #

text
                    ┌─────────────────────────────────────┐
                    │              Router                 │
                    │           (路由控制)                │
                    └──────────────┬──────────────────────┘
                                   │
                                   │ 导航
                                   ▼
┌──────────────┐         ┌─────────────────────────┐
│    Model     │◄───────►│         View            │
│   (数据)     │         │  (视图 + 控制器逻辑)    │
└──────────────┘         └───────────┬─────────────┘
       ▲                             │
       │                             │
       │ 数据                        │ DOM事件
       │                             │
       │         ┌───────────────────┴───────────────────┐
       │         │                                       │
       │         ▼                                       ▼
       │  ┌─────────────┐                     ┌─────────────────┐
       │  │  Collection │                     │   DOM Events    │
       │  │  (数据集合) │                     │   (用户交互)    │
       │  └─────────────┘                     └─────────────────┘
       │         │
       │         │
       └─────────┘

2.2 数据流向 #

text
用户操作 → View捕获事件 → 更新Model → Model触发事件 → View更新UI

三、Model(模型) #

3.1 Model的职责 #

javascript
var User = Backbone.Model.extend({
    defaults: {
        name: '',
        email: '',
        age: 0
    },
    
    validate: function(attrs) {
        if (!attrs.name) {
            return '姓名不能为空';
        }
        if (attrs.age < 0) {
            return '年龄不能为负数';
        }
    },
    
    initialize: function() {
        console.log('User模型已创建');
    }
});

Model核心职责:

职责 方法 说明
数据存储 get/set 存取属性值
数据验证 validate 验证数据有效性
数据持久化 save/fetch/destroy 与服务器同步
事件通知 trigger 通知数据变化

3.2 Model的生命周期 #

text
创建 → 初始化 → 设置属性 → 验证 → 保存 → 更新 → 销毁
 │        │         │        │       │       │       │
 └────────┴─────────┴────────┴───────┴───────┴───────┘
                          触发事件

3.3 Model事件流 #

javascript
var user = new User();

user.on('change', function() {
    console.log('属性已变化');
});

user.on('change:name', function(model, value) {
    console.log('姓名已变更为:', value);
});

user.set('name', '张三');

四、Collection(集合) #

4.1 Collection的职责 #

javascript
var Users = Backbone.Collection.extend({
    model: User,
    
    url: '/api/users',
    
    comparator: 'name',
    
    initialize: function() {
        console.log('Users集合已创建');
    }
});

var users = new Users([
    { name: '张三', age: 25 },
    { name: '李四', age: 30 }
]);

Collection核心职责:

职责 方法 说明
模型管理 add/remove/reset 添加、移除、重置模型
查询过滤 find/filter/where 查找和过滤模型
排序 sort/comparator 排序模型
批量操作 fetch/create 批量获取和创建

4.2 Collection与Model的关系 #

text
Collection (Users)
    │
    ├── Model (User) { name: '张三', age: 25 }
    │
    ├── Model (User) { name: '李四', age: 30 }
    │
    └── Model (User) { name: '王五', age: 28 }

4.3 Collection事件代理 #

javascript
var users = new Users();

users.on('add', function(model) {
    console.log('添加了用户:', model.get('name'));
});

users.on('remove', function(model) {
    console.log('移除了用户:', model.get('name'));
});

users.add({ name: '张三' });
users.remove(users.at(0));

五、View(视图) #

5.1 View的职责 #

javascript
var UserView = Backbone.View.extend({
    tagName: 'div',
    className: 'user-item',
    
    template: _.template(
        '<span class="name"><%= name %></span>' +
        '<span class="age"><%= age %>岁</span>' +
        '<button class="edit">编辑</button>' +
        '<button class="delete">删除</button>'
    ),
    
    events: {
        'click .edit': 'editUser',
        'click .delete': 'deleteUser'
    },
    
    initialize: function() {
        this.listenTo(this.model, 'change', this.render);
        this.listenTo(this.model, 'destroy', this.remove);
    },
    
    render: function() {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    },
    
    editUser: function() {
        console.log('编辑用户:', this.model.get('name'));
    },
    
    deleteUser: function() {
        this.model.destroy();
    }
});

View核心职责:

职责 方法/属性 说明
DOM渲染 render 生成DOM元素
事件处理 events 绑定DOM事件
模型监听 listenTo 监听模型变化
模板渲染 template 渲染HTML模板

5.2 View的双重角色 #

Backbone的View同时承担了视图和控制器的职责:

text
View = View(视图) + Controller(控制器)

视图职责:
├── 渲染HTML
├── 更新UI
└── 显示数据

控制器职责:
├── 处理用户输入
├── 更新模型
└── 协调视图和模型

5.3 View的事件绑定 #

javascript
var UserView = Backbone.View.extend({
    events: {
        'click .btn': 'onClick',
        'mouseenter .item': 'onMouseEnter',
        'mouseleave .item': 'onMouseLeave',
        'keypress input': 'onKeyPress'
    },
    
    onClick: function(e) {
        e.preventDefault();
    },
    
    onMouseEnter: function(e) {
        $(e.currentTarget).addClass('hover');
    },
    
    onMouseLeave: function(e) {
        $(e.currentTarget).removeClass('hover');
    },
    
    onKeyPress: function(e) {
        if (e.which === 13) {
            this.submit();
        }
    }
});

六、Router(路由器) #

6.1 Router的职责 #

javascript
var AppRouter = Backbone.Router.extend({
    routes: {
        '': 'home',
        'users': 'listUsers',
        'users/:id': 'showUser',
        'users/:id/edit': 'editUser',
        '*notFound': 'notFound'
    },
    
    home: function() {
        console.log('首页');
    },
    
    listUsers: function() {
        console.log('用户列表');
    },
    
    showUser: function(id) {
        console.log('显示用户:', id);
    },
    
    editUser: function(id) {
        console.log('编辑用户:', id);
    },
    
    notFound: function() {
        console.log('页面未找到');
    }
});

Router核心职责:

职责 方法 说明
路由定义 routes 定义URL与函数的映射
导航控制 navigate 编程式导航
历史管理 history 管理浏览器历史

6.2 Router在MVC中的角色 #

text
Router作为入口控制器:
┌─────────────────────────────────────────────────────┐
│                                                     │
│  URL变化 → Router匹配 → 创建/更新View → 渲染页面   │
│                                                     │
└─────────────────────────────────────────────────────┘

七、Events(事件系统) #

7.1 Events的作用 #

Events是Backbone的核心,所有组件都继承了Events:

javascript
// Model、Collection、View、Router都继承自Events
Backbone.Model.prototype.on === Backbone.Events.on
Backbone.Collection.prototype.on === Backbone.Events.on
Backbone.View.prototype.on === Backbone.Events.on
Backbone.Router.prototype.on === Backbone.Events.on

7.2 事件驱动架构 #

text
┌─────────────────────────────────────────────────────┐
│                  事件驱动架构                        │
├─────────────────────────────────────────────────────┤
│                                                     │
│   Model ──触发事件──► View ──监听事件──► 更新UI    │
│                                                     │
│   View ──捕获事件──► Model ──更新数据──► 触发事件  │
│                                                     │
│   Collection ──代理事件──► View ──监听──► 更新列表 │
│                                                     │
└─────────────────────────────────────────────────────┘

7.3 事件绑定方式 #

javascript
// 方式1:直接绑定
model.on('change', callback);

// 方式2:监听其他对象
view.listenTo(model, 'change', callback);

// 方式3:绑定多个事件
model.on({
    'change:name': this.onNameChange,
    'change:age': this.onAgeChange,
    'destroy': this.onDestroy
});

八、数据流详解 #

8.1 单向数据流 #

text
用户操作
    │
    ▼
View处理事件
    │
    ▼
更新Model
    │
    ▼
Model触发事件
    │
    ▼
View监听事件
    │
    ▼
更新UI

8.2 完整数据流示例 #

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

var TodoView = Backbone.View.extend({
    events: {
        'click .toggle': 'toggleCompleted'
    },
    
    initialize: function() {
        this.listenTo(this.model, 'change:completed', this.updateUI);
    },
    
    toggleCompleted: function() {
        var completed = this.model.get('completed');
        this.model.set('completed', !completed);
    },
    
    updateUI: function(model, completed) {
        this.$el.toggleClass('completed', completed);
    }
});

8.3 数据流图解 #

text
┌─────────────────────────────────────────────────────────────┐
│                        数据流图解                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用户点击 ──► toggleCompleted() ──► model.set()             │
│                                        │                    │
│                                        ▼                    │
│                              Model触发change:completed      │
│                                        │                    │
│                                        ▼                    │
│                              View监听到事件                 │
│                                        │                    │
│                                        ▼                    │
│                              updateUI()更新DOM              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

九、最佳实践 #

9.1 职责分离原则 #

javascript
// 好的做法:Model只处理数据逻辑
var User = Backbone.Model.extend({
    validate: function(attrs) {
        if (!attrs.email.match(/@/)) {
            return '邮箱格式不正确';
        }
    },
    
    getFullName: function() {
        return this.get('firstName') + ' ' + this.get('lastName');
    }
});

// 好的做法:View只处理UI逻辑
var UserView = Backbone.View.extend({
    render: function() {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    },
    
    events: {
        'click .save': 'saveUser'
    },
    
    saveUser: function() {
        var data = this.$('form').serializeJSON();
        this.model.save(data);
    }
});

9.2 避免在View中直接操作Model数据 #

javascript
// 不好的做法
var BadView = Backbone.View.extend({
    onClick: function() {
        this.model.attributes.name = '新名字';
        this.render();
    }
});

// 好的做法
var GoodView = Backbone.View.extend({
    onClick: function() {
        this.model.set('name', '新名字');
    },
    
    initialize: function() {
        this.listenTo(this.model, 'change', this.render);
    }
});

9.3 使用Collection管理多个Model #

javascript
// 不好的做法:在View中维护数组
var BadView = Backbone.View.extend({
    initialize: function() {
        this.users = [];
    },
    
    addUser: function(user) {
        this.users.push(user);
        this.render();
    }
});

// 好的做法:使用Collection
var GoodView = Backbone.View.extend({
    initialize: function() {
        this.listenTo(this.collection, 'add', this.addOne);
        this.listenTo(this.collection, 'remove', this.removeOne);
    },
    
    addOne: function(user) {
        var view = new UserView({ model: user });
        this.$el.append(view.render().el);
    }
});

十、总结 #

10.1 Backbone MVC特点 #

特点 说明
轻量级 组件简单,职责清晰
灵活性 不强制特定模式
事件驱动 组件间松耦合
单向数据流 数据流向清晰

10.2 核心理解 #

  1. Model:数据管理和业务逻辑
  2. Collection:模型集合管理
  3. View:视图渲染 + 控制器逻辑
  4. Router:路由导航控制
  5. Events:组件通信桥梁

10.3 设计原则 #

  • 保持Model纯净,只处理数据
  • View负责UI渲染和用户交互
  • 使用事件实现组件间通信
  • Collection管理多个Model实例
  • Router控制应用导航
最后更新:2026-03-28