35

ビューとルーターをrequireを使用して別々のファイルに分割しています。次に、ルーターをインスタンス化し、デフォルトのビューをレンダリングするmain.jsファイルがあります。

私のルーターには、ルートとしてビュー('View /:id')と編集('Edit /:id')があります。main.jsで、ルーターをインスタンス化すると、router.navigate('View / 1'、true)をハードコーディングでき、ナビゲーションは正常に機能します。ビューファイルで、編集リンクをクリックしたときに、router.navigate('View /'+ id、true)を呼び出したいのですが、これをどのように行うべきかわかりません。

Backbone.history.navigate('View /'+ id、true)の呼び出しに成功しましたが、グローバルBackboneオブジェクトに依存する必要があるとは思いません。

this.options.router.navigate()を使用できるように、ビューに({router:appRouter})を渡してみましたが、うまくいきませんでした。

気になる方のために、私のアプリのコードをいくつか紹介します。

ルーター:

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); 
        },
    });
});
4

8 に答える 8

32

私のように他の誰かがこの問題の解決策を探している場合に備えて、私がやったことを投稿します。ボイラープレート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();
};

backback.jsの特定の継承のフレーバーにより、これにより、MyView.goTo(location);任意のビュー内から呼び出すことができます。

于 2012-03-02T05:02:05.040 に答える
20

ほとんどすべてのバックボーンの質問と同様に、これを処理する方法はたくさんあります。現在のプロジェクトで私がアプローチした方法は、すべてをグローバルカスタム名前空間に配置し、それを使用して必要な参照を渡すことでした。

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()これはあなたがしていることと大差ありませんが、それはそれを少しモジュール化して、あなたが常にグローバルリファレンスを使うことを妨げるでしょう。これにより、内部実装を変更することもできます。

于 2011-10-13T17:33:12.680 に答える
8

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);
于 2011-10-13T17:11:25.457 に答える
5

私にとって、goTo関数を使用したソリューションはわずかな変更で機能しました

 Backbone.View.prototype.goTo = function (loc) {
      appRouter.navigate(loc, true);
    };
于 2012-04-20T05:45:47.690 に答える
3

この質問は古いことは知っていますが、ルーターを取得するために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);
        }
    });
});
于 2012-10-24T15:49:53.503 に答える
2

このアプローチはどうですか?バックボーンは4つのコンポーネントすべてにテンプレートパターンを実装しているため、少しの設計で、循環参照を作成しなくても、アプリのルーターを介して簡単なナビゲーションメカニズムを各ビューに提供できます(これは他の同様の投稿で見たものですが、それを避けてください)。

ルーターコンポーネント。他のルーターの例と大差ありません。

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

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

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

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

return MyRouter;
});

アプリは、ルーターインスタンスを作成し、このインスタンスを渡す最初のビューを起動します。

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;
});

ビューインスタンス。各ビューはバックボーンではなくベースビューから拡張され、ベースの動作を継承します。

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;
});

それは私のために働きます、そしてまたそれは他のプロジェクトで再利用することができます。

于 2013-01-16T02:32:44.700 に答える
1

私にとっては、そのようにメインアプリケーションにオブジェクトを追加しました。

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})と言うことができます。この場合、グローバルスコープが適切かどうかはわかりませんが、私にとってはうまくいきました。

于 2013-01-16T10:42:52.867 に答える
0

AMDモジュールをルーティングするための新しいソリューションがあります。

RequireJSルーターhttps://github.com/erikringsmuth/requirejs-router

これは、各ページに移動するときにAMDモジュールを遅延ロードするというアプローチを取ります。バックボーンルーターでは、すべてのビューを依存関係として事前に要求する必要があります。これにより、最初のページの読み込み時にすべてのアプリのJavascriptが読み込まれます。RequireJSルーターは、各ルートに移動するときにモジュールを遅延ロードします。

アプリの実行に使用される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's 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's module
        layoutView.render.call(layoutView);
      })
      .on('routeload', function(module, routeArguments) {
        // Attach the content view to the layoutView's main-content section
        layoutView.$('#main-content').replaceWith(new module(routeArguments).render().el);
      })
      .init({
        // We're manually calling loadCurrentRoute() from layoutView.render()
        loadCurrentRouteOnStateChange: false
      });
  );
);
于 2014-02-19T19:54:31.083 に答える