Backbone.js路由导航 #

一、navigate方法 #

1.1 基本用法 #

javascript
var router = new AppRouter();

router.navigate('users', { trigger: true });

router.navigate('users/1', { trigger: true });

1.2 navigate选项 #

javascript
router.navigate('users', {
    trigger: true,
    replace: true
});
选项 默认值 说明
trigger false 是否触发路由处理函数
replace false 是否替换历史记录

1.3 触发路由 #

javascript
router.navigate('about');

router.navigate('about', { trigger: true });

1.4 替换历史记录 #

javascript
router.navigate('login', { replace: true });

router.navigate('dashboard', { trigger: true, replace: true });

1.5 返回值 #

javascript
var result = router.navigate('users', { trigger: true });
console.log(result === router);

二、链接处理 #

2.1 Hash链接 #

html
<a href="#users">用户列表</a>
<a href="#users/1">用户详情</a>
<a href="#about">关于</a>

2.2 拦截链接点击 #

javascript
$(document).on('click', 'a[href^="#"]', function(e) {
    e.preventDefault();
    var href = $(this).attr('href').substring(1);
    router.navigate(href, { trigger: true });
});

2.3 pushState链接 #

javascript
Backbone.history.start({
    pushState: true,
    root: '/app/'
});

$(document).on('click', 'a[href^="/app/"]', function(e) {
    e.preventDefault();
    var href = $(this).attr('href').replace('/app/', '');
    router.navigate(href, { trigger: true });
});

2.4 排除外部链接 #

javascript
$(document).on('click', 'a', function(e) {
    var $link = $(this);
    var href = $link.attr('href');
    
    if (href.indexOf('://') !== -1 || href.indexOf('mailto:') === 0) {
        return;
    }
    
    if (href.indexOf('/app/') === 0) {
        e.preventDefault();
        router.navigate(href.replace('/app/', ''), { trigger: true });
    }
});

2.5 data属性导航 #

html
<button data-route="users">用户列表</button>
<button data-route="users/1">用户详情</button>
javascript
$(document).on('click', '[data-route]', function(e) {
    e.preventDefault();
    var route = $(this).data('route');
    router.navigate(route, { trigger: true });
});

三、导航控制 #

3.1 返回上一页 #

javascript
window.history.back();

window.history.go(-1);

3.2 前进 #

javascript
window.history.forward();

window.history.go(1);

3.3 获取当前路由 #

javascript
var fragment = Backbone.history.getFragment();
console.log(fragment);

3.4 检查当前路由 #

javascript
var AppRouter = Backbone.Router.extend({
    routes: {
        'users': 'users',
        'posts': 'posts'
    },
    
    isCurrentRoute: function(route) {
        return Backbone.history.getFragment() === route;
    },
    
    users: function() {
        if (this.isCurrentRoute('users')) {
            console.log('当前是用户页面');
        }
    }
});

3.5 导航前检查 #

javascript
var AppRouter = Backbone.Router.extend({
    navigate: function(fragment, options) {
        if (this.hasUnsavedChanges()) {
            if (confirm('有未保存的更改,确定要离开吗?')) {
                return Backbone.Router.prototype.navigate.call(this, fragment, options);
            }
            return this;
        }
        return Backbone.Router.prototype.navigate.call(this, fragment, options);
    },
    
    hasUnsavedChanges: function() {
        return this.currentView && this.currentView.hasChanges;
    }
});

四、导航事件 #

4.1 route事件 #

javascript
router.on('route', function(name, args) {
    console.log('路由名称:', name);
    console.log('路由参数:', args);
});

4.2 特定路由事件 #

javascript
router.on('route:users', function() {
    console.log('进入用户页面');
});

router.on('route:userDetail', function(id) {
    console.log('进入用户详情:', id);
});

4.3 导航前事件 #

javascript
var AppRouter = Backbone.Router.extend({
    initialize: function() {
        this.on('route', this.onRouteChange, this);
    },
    
    onRouteChange: function(name, args) {
        this.updateNavigation(name);
        this.trackPageView(name);
    },
    
    updateNavigation: function(route) {
        $('.nav-item').removeClass('active');
        $('.nav-item[data-route="' + route + '"]').addClass('active');
    },
    
    trackPageView: function(route) {
        if (window.ga) {
            ga('send', 'pageview', '/' + route);
        }
    }
});

五、实用示例 #

5.1 导航服务 #

javascript
var NavigationService = {
    router: null,
    
    init: function(router) {
        this.router = router;
    },
    
    go: function(route, options) {
        options = options || {};
        this.router.navigate(route, {
            trigger: options.trigger !== false,
            replace: options.replace || false
        });
    },
    
    goBack: function() {
        window.history.back();
    },
    
    goForward: function() {
        window.history.forward();
    },
    
    replace: function(route) {
        this.go(route, { replace: true });
    },
    
    getCurrentRoute: function() {
        return Backbone.history.getFragment();
    },
    
    isActive: function(route) {
        return this.getCurrentRoute() === route;
    }
};

NavigationService.init(router);

NavigationService.go('users');
NavigationService.goBack();

5.2 面包屑导航 #

javascript
var BreadcrumbService = {
    breadcrumbs: [],
    
    add: function(name, route) {
        this.breadcrumbs.push({ name: name, route: route });
        this.render();
    },
    
    set: function(items) {
        this.breadcrumbs = items;
        this.render();
    },
    
    clear: function() {
        this.breadcrumbs = [];
        this.render();
    },
    
    render: function() {
        var $breadcrumb = $('#breadcrumb');
        $breadcrumb.empty();
        
        this.breadcrumbs.forEach(function(item, index) {
            if (index < this.breadcrumbs.length - 1) {
                $breadcrumb.append(
                    '<li><a href="#' + item.route + '">' + item.name + '</a></li>'
                );
            } else {
                $breadcrumb.append(
                    '<li class="active">' + item.name + '</li>'
                );
            }
        }, this);
    }
};

var AppRouter = Backbone.Router.extend({
    routes: {
        'users': 'users',
        'users/:id': 'userDetail'
    },
    
    users: function() {
        BreadcrumbService.set([
            { name: '首页', route: '' },
            { name: '用户列表', route: 'users' }
        ]);
    },
    
    userDetail: function(id) {
        BreadcrumbService.set([
            { name: '首页', route: '' },
            { name: '用户列表', route: 'users' },
            { name: '用户详情', route: 'users/' + id }
        ]);
    }
});

5.3 导航历史 #

javascript
var NavigationHistory = {
    history: [],
    maxLength: 20,
    
    add: function(route) {
        this.history.push({
            route: route,
            timestamp: Date.now()
        });
        
        if (this.history.length > this.maxLength) {
            this.history.shift();
        }
    },
    
    getLast: function() {
        return this.history[this.history.length - 1];
    },
    
    getPrevious: function() {
        return this.history[this.history.length - 2];
    },
    
    getAll: function() {
        return this.history;
    }
};

var AppRouter = Backbone.Router.extend({
    initialize: function() {
        this.on('route', function(name) {
            NavigationHistory.add(Backbone.history.getFragment());
        });
    }
});

5.4 页面标题管理 #

javascript
var TitleService = {
    baseTitle: 'My App',
    
    set: function(title) {
        if (title) {
            document.title = title + ' - ' + this.baseTitle;
        } else {
            document.title = this.baseTitle;
        }
    }
};

var AppRouter = Backbone.Router.extend({
    routes: {
        '': 'home',
        'users': 'users',
        'users/:id': 'userDetail'
    },
    
    home: function() {
        TitleService.set();
    },
    
    users: function() {
        TitleService.set('用户列表');
    },
    
    userDetail: function(id) {
        var user = new User({ id: id });
        user.fetch().then(function() {
            TitleService.set(user.get('name'));
        });
    }
});

六、总结 #

6.1 导航方法 #

方法 说明
navigate(fragment, options) 导航到指定路由
history.back() 返回上一页
history.forward() 前进
history.go(n) 前进或后退n步

6.2 最佳实践 #

  1. 使用 navigate 方法进行导航
  2. 拦截链接点击实现SPA导航
  3. 处理导航前的确认
  4. 维护导航历史
  5. 更新页面标题
最后更新:2026-03-28