Backbone.js : 현재 경로 가져 오기


137

Backbone을 사용하면 현재 경로의 이름을 얻을 수 있습니까? 경로 변경 이벤트에 바인딩하는 방법을 알고 있지만 변경 사이에 다른 시간에 현재 경로를 결정할 수 있기를 원합니다.


"이름"은 해당 경로가 바인딩되는 기능 또는 URL의 현재 URL 또는 해시 부분을 의미합니까?
John Munsch

1
예, 좀 더 구체적으로 말해야합니다. 함수의 이름을 알고 싶습니다. (location.hash 또는 Backbone.history.fragment를 수행하여 URL의 해시 부분을 얻는 방법을 알고 있습니다.)
Drew Dara-Abrams

답변:


209

응용 프로그램에서 라우터를 인스턴스화 한 경우 다음 줄은 현재 조각을 반환합니다.

Backbone.history.getFragment();

로부터 Backbone.js 문서 :

"[...] 역사 핸들 hashchange 이벤트 또는 pushState에 (프레임 당) 글로벌 라우터의 역할을, 콜백을 적절한 경로를 일치 및 트리거 혹시이 자신을 하나 만들 필요가 없습니다 -. 당신이 참조를 사용한다을 경로가있는 라우터를 사용 하면 자동으로 생성되는 Backbone.history에 연결됩니다 . [...] "

해당 조각에 바인딩 된 함수 이름이 필요한 경우 라우터 범위 내에서 다음과 같이 만들 수 있습니다.

alert( this.routes[Backbone.history.getFragment()] );

또는 라우터 외부에서 다음과 같이하십시오.

alert( myRouter.routes[Backbone.history.getFragment()] );

고마워요 문서에서 Backbone.history.fragment에 대해 언급 한 적이 없습니다. 이것은 새로운 추가 물입니까 아니면 문서화되지 않은 것입니까?
Drew Dara-Abrams

나는 이것이 문서화되지 않았다고 생각합니다. 사실, 처음 본 블로그, 블로그 또는 백본 소스 코드를 기억하지 못합니다.
Robert

25
참고로, 이것은 'foo / : id'또는 'bar * params'와 같은 경로에서는 작동하지 않습니다
wprl

2
비공개 숨겨진 속성 Backbone.history.getFragment()이므로 사용하는 것이 좋습니다 Backbone.history.fragment.
Vad

1
@ Vad 제안에 따라 답변을 수정했습니다. 나는 더 이상 백본을 사용하지 않지만 그의 의견은 나에게 들린다. (이전 답변은 Backbone.history.getFragment () 대신 Backbone.history.fragment)
Robert

57

Robert의 대답 은 흥미롭지 만 안타깝게도 해시가 경로에 정의 된 대로만 작동합니다. 예를 들어 경로 가있는 경우 또는 경로 중 하나 인 user(/:uid)경우 일치하지 않습니다 (둘 다 해당 경로의 가장 명백한 두 가지 유스 케이스입니다). 다시 말해서, 해시가 정확히 (매우 가능성이 낮 다면) 적절한 콜백 이름 만 찾습니다 .Backbone.history.fragment"user""user/1""user(/:uid)"

이 기능이 필요했기 때문에 History 및 Router 객체가 적절한 콜백을 트리거하기 위해 정의 된 경로와 현재 조각을 일치시키기 위해 사용하는 일부 코드를 재사용 Backbone.Router하는 current- 기능으로 확장했습니다 . 내 유스 케이스의 경우 선택적 매개 변수를 사용합니다.이 매개 변수 route를 true로 설정하면 경로에 대해 정의 된 해당 함수 이름이 반환됩니다. 그렇지 않으면에서 현재 해시 조각을 반환합니다 Backbone.History.fragment.

Backbone 라우터를 초기화하고 설정하는 기존 Extend에 코드를 추가 할 수 있습니다.

var Router = new Backbone.Router.extend({

    // Pretty basic stuff
    routes : {
        "home" : "home",
        "user(:/uid)" : "user",
        "test" : "completelyDifferent"
    },

    home : function() {
        // Home route
    },

    user : function(uid) {
        // User route
    },

    // Gets the current route callback function name
    // or current hash fragment
    current : function(route){
        if(route && Backbone.History.started) {
            var Router = this,
                // Get current fragment from Backbone.History
                fragment = Backbone.history.fragment,
                // Get current object of routes and convert to array-pairs
                routes = _.pairs(Router.routes);

            // Loop through array pairs and return
            // array on first truthful match.
            var matched = _.find(routes, function(handler) {
                var route = handler[0];

                // Convert the route to RegExp using the 
                // Backbone Router's internal convert
                // function (if it already isn't a RegExp)
                route = _.isRegExp(route) ? route :  Router._routeToRegExp(route);

                // Test the regexp against the current fragment
                return route.test(fragment);
            });

            // Returns callback name or false if 
            // no matches are found
            return matched ? matched[1] : false;
        } else {
            // Just return current hash fragment in History
            return Backbone.history.fragment
        }
    }
});

// Example uses:
// Location: /home
// console.log(Router.current()) // Outputs 'home'
// Location: /user/1
// console.log(Router.current(true)) // Outputs 'user'
// Location: /user/2
// console.log(Router.current()) // Outputs 'user/2'
// Location: /test
// console.log(Router.current(true)) // Outputs 'completelyDifferent'

약간의 개선이 이루어질 수있을 것이지만 이것이 시작을위한 좋은 방법입니다. 또한 Route-object를 확장하지 않고도이 기능을 쉽게 만들 수 있습니다. 이 설정이 가장 편리한 방법이기 때문에이 작업을 수행했습니다.

나는 이것을 아직 완전히 테스트하지 않았으므로 남쪽으로 가면 알려주십시오.


2013 년 4 월 25 일 업데이트

함수에 약간의 변경을가 했으므로 해시 또는 경로 콜백 이름을 반환하는 대신 조각, 매개 변수 및 경로가있는 객체를 반환하므로 경로에서와 마찬가지로 현재 경로의 모든 데이터에 액세스 할 수 있습니다. 행사.

아래 변경 사항을 볼 수 있습니다.

current : function() {
    var Router = this,
        fragment = Backbone.history.fragment,
        routes = _.pairs(Router.routes),
        route = null, params = null, matched;

    matched = _.find(routes, function(handler) {
        route = _.isRegExp(handler[0]) ? handler[0] : Router._routeToRegExp(handler[0]);
        return route.test(fragment);
    });

    if(matched) {
        // NEW: Extracts the params using the internal
        // function _extractParameters 
        params = Router._extractParameters(route, fragment);
        route = matched[1];
    }

    return {
        route : route,
        fragment : fragment,
        params : params
    };
}

추가 주석 및 설명은 이전 코드를 참조하십시오.


1
직접 작성하려고했지만 Googled가 먼저 해결책을 찾았습니다. 다행입니다. 당신은 내가 원하는 것을 정확하게 수행 합니다 , 감사합니다!
Dan Abramov

여기의 약간 더 자세한 버전 내가 처음 눈에 이해하기 쉽게 믿는다는.
Dan Abramov

4
와, 고마워! 코드베이스에서 승인을 받았습니다. ; P 우리는 마리오네트를 위해 약간 조정했습니다. 그건 그렇고, 바로 가기로 _.find함수 의 세 번째 매개 변수 (컨텍스트를 설정)를로 설정할 수 this있으므로 Router변수 가 필요 하지 않습니다 (@DanAbramov가 이미 수행했습니다).
Mark

@Mark 좋은 소식입니다. 그러나 마리오네트에서이 기능을 어떻게 사용할 수 있습니까? 문서에는 아무것도 없습니다.
darksoulsong

2
@darksoulsong를 사용하는 경우 Marionette.AppRouter위 기능으로 라우터를 확장하되 대신 대체 Router.appRoutes하십시오 Router.routes.
Mark

11

호출 된 경로 처리기에서 호출 경로 (또는 URL)를 얻으려면 확인하여 얻을 수 있습니다.

Backbone.history.location.href ... 전체 URL
Backbone.history.location.search ...?에서 시작하는 쿼리 문자열?

나는이 답변을 찾기 위해 여기에 왔으므로 내가 찾은 것을 떠나야한다고 생각합니다.


6

라우터의 루트 설정을 사용하는 경우 '실제'조각을 얻기 위해 포함시킬 수도 있습니다.

(Backbone.history.options.root || "") + "/" + Backbone.history.fragment

6

Simon의 대답에 대한 더 장황한 (또는 취향에 따라 더 읽기 쉬운) 버전이 있습니다 .

current: function () {
  var fragment = Backbone.history.fragment,
      routes = _.pairs(this.routes),
      route,
      name,
      found;

  found = _.find(routes, function (namedRoute) {
    route = namedRoute[0];
    name = namedRoute[1];

    if (!_.isRegExp(route)) {
      route = this._routeToRegExp(route);
    }

    return route.test(fragment);
  }, this);

  if (found) {
    return {
      name: name,
      params: this._extractParameters(route, fragment),
      fragment: fragment
    };
  }
}

4

의 소스를 보면 Router라우터가 무언가 변경되었다는 이벤트를 트리거하면 이름이 "route : name"으로 전달됨을 알 수 있습니다.

http://documentcloud.github.com/backbone/docs/backbone.html#section-84

라우터에서 항상 "경로"이벤트를 연결하고 저장하여 현재 경로를 얻을 수 있습니다.


좋아, 이것이 "직접 구축"된 것 같다.
Drew Dara-Abrams

예, 그렇지 않은 경우 route이벤트 trigger 가 표시되지 않습니다 true (권장 및 기본값).
Dan Abramov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.