навигация по маршруту с помощью строки запроса

Будет ли Backbone.Router.navigate устанавливать test на true:

var test = false;

var Router = Backbone.Router.extend({
  routes: {
    'posts': 'showPosts'
  },
  showPosts: function () {
    test = true;
  }
});

router = new Router();
Backbone.history.start();

router.navigate('posts?foo=3', {trigger: true});

assert.ok(test);

Например, будет ли фрагмент posts?foo=3 соответствовать маршруту posts по умолчанию, или мне нужно установить для этого другой маршрут, например: posts?*querystring?

Спасибо

PS: я знаю, что существуют backbone-query-parameters, но я хочу знать только для позвоночник.


person abernier    schedule 26.07.2012    source источник
comment
У меня аналогичная проблема stackoverflow.com/questions/ 15254230/   -  person George Norris    schedule 06.03.2013


Ответы (5)


Вам нужно добавить еще один маршрут с ожидаемым параметром:

routes: {
    'posts?foo=:foo' : 'showPosts',
    'posts': 'showPosts'
},
showPosts: function (foo) {
    if(typeof foo != 'undefined'){
       // foo parameters was passed
    }
    test = true;
}

update
Вы можете определить общий маршрут для возврата всей строки запроса, а затем проанализировать ее в обработчике:

routes: {
   'posts': 'showPosts',
   'posts?*queryString' : 'showPosts'
},
showPosts: function (queryString) {
    var params = parseQueryString(queryString);
    if(params.foo){
        // foo parameters was passed
    }
}  
...
// and the function that parses the query string can be something like : 
function parseQueryString(queryString){
    var params = {};
    if(queryString){
        _.each(
            _.map(decodeURI(queryString).split(/&/g),function(el,i){
                var aux = el.split('='), o = {};
                if(aux.length >= 1){
                    var val = undefined;
                    if(aux.length == 2)
                        val = aux[1];
                    o[aux[0]] = val;
                }
                return o;
            }),
            function(o){
                _.extend(params,o);
            }
        );
    }
    return params;
}

обновление 2

Вот демонстрация, чтобы увидеть код в действии.

person gion_13    schedule 26.07.2012
comment
В одном случае вы определяете наиболее конкретный маршрут (posts?foo=:foo) первым, а в другом случае на второй позиции: разве порядок не имеет значения? - person abernier; 26.07.2012
comment
нет, это не влияет на то, как применяются маршруты. Это просто вопрос предпочтений. Кстати, я протестировал и обновил функцию, и теперь она отлично работает. - person gion_13; 26.07.2012
comment
Я вижу, что эта демонстрация работает, но по причинам, которые я до сих пор не могу понять, у меня это не работает. Используя эти конструкции маршрута, queryString всегда не определен. - person kinakuta; 23.08.2013
comment
Я понимаю, в чем проблема - хотя вы можете выполнить маршрут, передав true для навигации, это все еще не работает с историей правильно. Кроме того, необходимость передавать true для навигации не идеальна, поскольку требует, чтобы мой маршрутизатор выполнял навигацию, а не просто выполнял интерпретируемые маршруты. - person kinakuta; 24.08.2013
comment
Этот ответ уходит далеко от первоначального вопроса... Теперь ваш ответ больше похож на то, как анализировать строку запроса... - person abernier; 19.02.2014
comment
Это работает только при запуске Router.navigate('posts?foo=bar',{trigger:true,replace:true}); с заменой: правда. Есть ли способ, чтобы это работало, когда вы переходите непосредственно к URL-адресу? - person Mark Robson; 08.05.2014
comment
Сопоставление всей строки запроса не работает при использовании параметров запроса в кодировке URI (например, foo=Max%20%26%20Moritz), поскольку backbone.js ожидает только фрагменты полного пути и уже вызывает decodeURIComponent для все параметры маршрута. Поэтому последующий анализ строки запроса будет работать некорректно. - person Luis; 22.06.2015

Просто чтобы дополнить предыдущие ответы, вместо определения двух маршрутов с одинаковым обратным вызовом, например:

routes: {
    'posts': 'showPosts',
    'posts?*querystring': 'showPosts'
}

У вас может быть только один маршрут, чтобы код был чище:

routes: {
    'posts(?*querystring)': 'showPosts'
}
person romaia    schedule 14.02.2014
comment
Сопоставление всей строки запроса не работает при использовании параметров запроса в кодировке URI (например, foo=Max%20%26%20Moritz), поскольку backbone.js ожидает только фрагменты полного пути и уже вызывает decodeURIComponent для все параметры маршрута. Поэтому последующий анализ строки запроса будет работать некорректно. - person Luis; 22.06.2015

Основные документы:

Маршруты могут содержать части параметров, :param, которые соответствуют одному компоненту URL между косыми чертами; и splat части *splat, которые могут соответствовать любому количеству компонентов URL.

Если вы все еще хотите сохранить функциональность без сопоставления, вы можете определить два маршрута.

routes: {
  'posts': 'showPosts',
  'posts?*querystring': 'showPosts'
}

showPosts: function(querystring) {
  if (querystring) {
    // here you can parse your querystring, for your case the querystring variable is 
    // 'foo=3'
  }
  //here you'll show posts according to the querystring (or lack thereof)      
}
person jakee    schedule 26.07.2012
comment
Можно ли ?* без названия знака ?*querystring? - person abernier; 26.07.2012
comment
Это должно работать в Backbone 1? Cz он не запускает никаких действий маршрута после того, как я добавил '?*query' - person Daniel Birowsky Popeski; 27.06.2013
comment
Ответ был сделан почти год назад. Но документы или журналы изменений не указывают на какие-либо причины, по которым это не работает. - person jakee; 27.06.2013
comment
У меня такая же проблема. Наличие маршрута с ?*queryString не только не захватывает переменную queryString, но если у меня есть это, а не маршрут без строки запроса, маршрут вообще не интерпретируется. - person kinakuta; 23.08.2013

Вот еще один пример, все еще использующий lodash (подчеркивание). Удалил _.map, добавил немного детализации к переменным и убрал начальный '?' если имеется:

function parseQueryString(queryString)
{
    if (!_.isString(queryString))
        return
    queryString = queryString.substring( queryString.indexOf('?') + 1 )
    var params = {}
    var queryParts = decodeURI(queryString).split(/&/g)
    _.each(queryParts, function(val)
        {
            var parts = val.split('=')
            if (parts.length >= 1)
            {
                var val = undefined
                if (parts.length == 2)
                    val = parts[1]
                params[parts[0]] = val
            }
        })
    return params
}
person blented    schedule 11.06.2013
comment
Спасибо за это, должно было быть больше внимания imo - person azz0r; 11.08.2014

В RFC 3986 «синтаксис для URI» указано, что параметры запроса должны располагаться перед хэш-фрагментом.

В URI решетка # вводит необязательный фрагмент в конце URL-адреса. Общий синтаксис RFC 3986 для URI также допускает необязательную часть запроса, представленную вопросительным знаком ?. В URI с запросом и фрагментом фрагмент следует за запросом.

У меня возникла проблема с обработкой перенаправления, которое я получаю с сервера, т.е. "http://foo.com/main.html?error=errormessage#site". Я хотел бы направить запрос, но не вижу способа написать выражение магистрального маршрута для обработки этого URL-адреса. Пока я просто маршрутизирую хэш и проверяю запрос, анализируя location.search.

person Chris Collins    schedule 13.02.2015