Подтвердить что ты не робот

Использование маршрутизатора Backbone.js для навигации по представлениям, модульным с помощью require.js

Я разделяю свои представления и маршрутизатор на отдельные файлы с требованием. Затем у меня есть файл main.js, который создает экземпляр маршрутизатора, а также отображает мое представление по умолчанию.

Мой маршрутизатор имеет вид ('View/: id') и редактирует ('Edit/: id') в качестве маршрутов. В main.js, когда я создаю экземпляр маршрутизатора, я могу hardcode router.navigate('View/1', true), и навигация работает нормально. В моем файле просмотра, когда я нажимаю ссылку на редактирование, я хочу вызвать router.navigate('View/' + id, true), но я не уверен, как это сделать.

У меня был успех с вызовом Backbone.history.navigate('View/' + id, true), но я не чувствую, что должен полагаться на глобальный объект Backbone.

Я попытался передать ({router: appRouter}) свои представления, чтобы я мог использовать this.options.router.navigate(), однако это не работало для меня.

Если вам интересно, вот куча кода из моего приложения:

Router:

define(['./View', './Edit'], function (View, Edit) {
    return Backbone.Router.extend({
        routes: {
            'View/:id': 'view',
            'Edit/:id': 'edit'
        },

        view: function (id) {
            var model = this.collection.get(id);
            var view = new View({ model: model });
            view.render();
        },

        edit: function (id) {
            var model = this.collection.get(id);
            var edit = new Edit({ model: model });
            edit.render();
        }
    });
});

Вид:

define(function () {
    return Backbone.View.extend({
        template: Handlebars.compile($('#template').html()),

        events: {
            'click .edit': 'edit'
        },

        render: function () {
            //Create and insert the cover letter view
            $(this.el).html(this.template(this.model.toJSON()));
            $('#View').html(this.el);

            return this;
        },

        edit: function () {
            Backbone.history.navigate('Edit/' + this.model.id, true); 
        },
    });
});
4b9b3361

Ответ 1

Как и в случае с любым базовым вопросом, есть много способов справиться с этим. То, как я обратился к нему в моем текущем проекте, состоял в том, чтобы поместить все в глобальное пользовательское пространство имен и использовать его для передачи необходимых ссылок:

var MyNamespace = {};

MyNamespace.init = function() {
    MyNamespace.appView = new MyAppView();
    MyNamespace.router = new MyRouter();
    // etc
}

При необходимости просмотры могут ссылаться на MyNamespace.router. Но похоже, что это не будет работать/не рекомендуется с require.js, так что вот некоторые другие варианты:

  • Никогда не вызывайте маршрутизатор явно - вместо этого измените объект глобального состояния, который слушает роутер. Это на самом деле то, как я делал это в своем текущем проекте - см. этот ответ для более подробной информации.

  • Прикрепите маршрутизатор к виду верхнего уровня, который часто называют AppView, сделать доступным глобально и использовать AppView.router.navigate().

  • Создайте еще один модуль, предоставляющий функцию утилиты navigate, которая вызывает Backbone.history.navigate() внутренне. Это не сильно отличается от того, что вы делаете, но это сделает его несколько более модульным и не позволит вам использовать глобальную ссылку все время. Это также позволяет вам изменить внутреннюю реализацию.

Ответ 2

Если кто-то еще ищет решение этой проблемы, как я, я публикую то, что я делал. Если вы используете шаблонный backbone.js, тогда у вас будет функция initialize() в router.js. Я изменил мою функцию initialize(), чтобы выглядеть следующим образом:

initialize = function () {
  var app_router;
  app_router = new AppRouter();

  // Extend the View class to include a navigation method goTo
  Backbone.View.goTo = function (loc) {
    app_router.navigate(loc, true);
  };

  Backbone.history.start();
};

Из-за особого вкуса наследования backbone.js это позволяет мне вызвать MyView.goTo(location); из любого из моих представлений.

Ответ 3

Вы можете сделать это старомодным способом с помощью window.location.hash:)

window.location.hash = "Edit/1"

Здесь альтернативное решение, если вам не нужны явные маршруты. Когда приложение запускается, создайте объект, который расширяет базовые события

window.EventDispatcher = _.extend({}, Backbone.Events);

Затем в любом месте приложения вы можете слушать события

EventDispatcher.bind("mymodel:edit", this.editHandler, this);

А также из любой точки отправки событие data ниже - это любые параметры, которые вы хотите отправить для поездки

EventDispatcher.trigger("mymodel:edit", data);

Ответ 4

Для меня решение с функцией goTo работало с небольшим изменением

 Backbone.View.prototype.goTo = function (loc) {
      appRouter.navigate(loc, true);
    };

Ответ 5

Я знаю, что этот вопрос старый, но мне интересно, почему вы не используете require.js, чтобы получить маршрутизатор:

define(['./PathToRouter', ], function (router) {
    return Backbone.View.extend({
        template: Handlebars.compile($('#template').html()),

        events: {
            'click .edit': 'edit'
        },

        render: function () {
            //Create and insert the cover letter view
            $(this.el).html(this.template(this.model.toJSON()));
            $('#View').html(this.el);

            return this;
        },

        edit: function () {
            router.navigate('Edit/' + this.model.id, true);
        }
    });
});

Ответ 6

Как насчет этого подхода? Поскольку базовый блок реализует шаблон шаблона во всех его 4-х компонентах, с небольшим дизайном, вы можете обеспечить каждому виду простой механизм навигации через маршрутизатор приложений без необходимости делать какие-либо циклические ссылки (это было то, что я видел в других подобных сообщениях, но старайтесь избегать этого).

Компонент маршрутизатора, не сильно отличающийся от других примеров маршрутизатора:

define('Router', ['backbone', ... ],
        function (Backbone, ...) {

            var MyRouter = Backbone.Router.extend({
                routes: {
                    'viewA': 'viewA',
                    'viewB': 'viewB'
                },

                initialize: function () {
                    ...
                };
            },
            viewA: function () {
                ...
            },

            viewB: function () {
                ...
            }
});

return MyRouter;
});

App, создает экземпляр маршрутизатора и запускает первый вид, передающий этот экземпляр:

define('App', ['backbone', ...
], function (Backbone, ...) {

    function initialize() {

        //route creation
        if (!this.routes)
            routes = new Router(this); 
        //backbone history start
        Backbone.history.start();

        //ViewA navigation, bigbang
        if (!this.viewA)
            this.viewA = new ViewA({router: this.routes});
        this.viewA.render();
    }

    return {
        initialize: initialize
    };
});

BaseView, определение базового конструктора для всех видов, а также способ навигации:

define('BaseView', ['jquery', 'underscore',  'backbone', ...
], function ($, _, Backbone, ...) {
    var BaseView;

    BaseView = Backbone.View.extend({
        id: '...',

        constructor: function (options) {
            this.router = options.router;
            this.model = options.model;
            Backbone.View.prototype.constructor.call(this);
        },
        initialize: function () {
            this.template = _.template(tpl);
        },

        events: {

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

            return this;
        },
        //Provides transparent navigation between views throught the backbonejs
        //route mechanism
        navigate: function(pageId)
        {
            this.router.navigate(pageId, {trigger: true});
        }
    });

    return BaseView;
});

Экземпляр View, каждый вид простирается от базового вместо основной и наследует поведение базы:

define('ViewA', ['jquery', 'underscore',  'backbone', 'BaseView'
], function ($, _, Backbone, BaseView) {
    var ViewA;

    ViewA = BaseView.extend({
        id: '...',

        constructor: function (options) {
            this._super("constructor");
        },

        ...
        foo: function()
        {
            ...

            this.navigate("viewB");
        }
    });

    return ViewA;
});

Он работает для меня, а также его можно использовать в других проектах.

Ответ 7

для меня я добавил объект в основное приложение, например;

define(['jquery','underscore','backbone','views/personView','views/peopleView','views/textView'],function($,_,backbone,PersonView,PeopleView,TitleView){

    var Router = Backbone.Router.extend({
           routes:{
               '':'home',
               'edit/:id':'editPerson',
               'new':'editPerson',
               'delete/:id':'deletePerson'
               }
            })

              var initialize = function(){

                 var router  = new Router();

                 window.app = {
                     router:router
                     }

        router.on('route:home',function(){


    })

            //enable routing using '#'[hashtag] navigation
        Backbone.history.start();

            };

            return {
            initialize:initialize
            };

});

и внутри вашего представления вы можете сказать windows.app.router.navigate({'', trigger: true}). Не знаю, является ли глобальное охват хорошей практикой в ​​этом случае, но это сработало для меня.

Ответ 8

У меня есть новое решение для маршрутизации модулей AMD.

RequireJS Router https://github.com/erikringsmuth/requirejs-router

Это относится к ленивой загрузке модулей AMD при навигации по каждой странице. С маршрутизатором Backbone вам нужно, чтобы все ваши взгляды были зависимыми друг от друга. Это загружает все ваши приложения Javascript при загрузке первой страницы. Маршрутизаторы RequireJS Router ленивы загружаются при каждом перемещении.

Пример main.js, используемый для запуска вашего приложения

define([], function() {
  'use strict';

  // Configure require.js paths and shims
  require.config({
    paths: {
      'text': 'bower_components/requirejs-text/text',
      'router': 'bower_components/requirejs-router/router'
    }
  });

  // Load the router and your layout
  require(['router', 'js/layout/layoutView'], function(router, LayoutView) {
    var layoutView = new LayoutView();
    // The layout render method should draw the header, footer, and an empty main-content section
    // then load the content section.
    // render: function() {
    //   this.$el.html(this.template({model: this.model}));
    //   router.loadCurrentRoute();
    // }

    // Configure the router
    router
      .registerRoutes({
        home: {path: '/', moduleId: 'home/homeView'},
        order: {path: '/order', moduleId: 'order/orderView'},
        notFound: {path: '*', moduleId: 'notFound/notFoundView'}
      })
      .on('statechange', function() {
        // Render the layout before loading the current route module
        layoutView.render.call(layoutView);
      })
      .on('routeload', function(module, routeArguments) {
        // Attach the content view to the layoutView main-content section
        layoutView.$('#main-content').replaceWith(new module(routeArguments).render().el);
      })
      .init({
        // We're manually calling loadCurrentRoute() from layoutView.render()
        loadCurrentRouteOnStateChange: false
      });
  );
);