Маршрутизатор Meteor Iron Router не работает на некоторых ссылках

У меня есть такой маршрут:

Router.route('/box', function () {
    this.render('boxCanvasTpl');
},{
    name: 'box',
    layoutTemplate: 'appWrapperLoggedInTpl',
    waitOn: function() {
        console.log("Box route ran ok.");
        return [
            Meteor.subscribe('item_ownership_pub', function() {
                console.log("subscription 'item_ownership_pub' is ready.");
            }),
            Meteor.subscribe('my_items', function() {
                console.log("subscription 'my_items' is ready.");
            })
        ];
    }
});

... и я нажимаю ссылку в шаблоне следующим образом:

<a href="/box?box=123" class="box-num-items">My Link</a>

Я получаю сообщение «Маршрут Box прошел нормально». сообщение, но по какой-то причине страница не переходит по указанному URL-адресу. Я добавил код console.log в функцию, которая запускается при рендеринге boxCanvasTpl, но они не отображаются в консоли браузера. Кажется, что-то промежуточное мешает повторному рендерингу templkate, но я не могу понять это - есть идеи?


person JoeTidee    schedule 13.06.2015    source источник
comment
Будет ли это работать, если вы удалите оба обратных вызова subscribe?   -  person David Weldon    schedule 14.06.2015
comment
Это сложно проверить, поскольку страница, содержащая вышеупомянутую ссылку, является страницей, на которую я пытаюсь перейти. Будет ли это проблемой, т.е. если я нахожусь в /box?box=111 и пытаюсь перейти к /box?box=123 - не будет ли повторный запуск функции onRendered?   -  person JoeTidee    schedule 14.06.2015
comment
Я немного смущен тем, что вы пытаетесь сделать здесь. У вас есть параметры в URL-адресе (?box=123), но у вас нет кода для доступа к этим параметрам URL-адреса с помощью this.params - stackoverflow.com/questions/23050664/ И да, если вы поместите console.log внутри Template.boxCanvasTpl.onRendered() и он не отображается, это означает, что шаблон не был отрендерен (или перерендерен, в вашем случае). Я ненавижу, ненавижу, ненавижу форматирование в комментариях Stack Overflow...   -  person fuzzybabybunny    schedule 14.06.2015
comment
@fuzzybabybunny Я использую Router.current().params.query.box вне маршрутизатора (в моей функции Template.onRendered), но это не имеет отношения к проблеме.   -  person JoeTidee    schedule 14.06.2015
comment
Ах, но это актуально, так как onRendered() не срабатывает и, следовательно, ваши параметры не распознаются.   -  person fuzzybabybunny    schedule 14.06.2015
comment
В этом конкретном вопросе параметры не вызывают проблемы.   -  person JoeTidee    schedule 14.06.2015


Ответы (1)


Есть некоторые свойства Iron Router, о которых вам нужно знать.

Скажем, пользователь в настоящее время уже находится на /boxes и есть шаблон box, который отображается для этого пути. Если ты:

  • нажмите на ссылку <a href="/boxes?box=123">Click Me</a>

or

  • нажмите на ссылку <a href="{{pathFor 'box'}}">Click Me</a>

Iron Router НЕ будет повторно отображать шаблон, поскольку он уже существует на странице. Он также НЕ будет повторно отображать шаблон, если шаблон box является частичным шаблоном, который уже отображается на странице, на которой вы находитесь, и также существует на странице, на которую вы хотите перейти.

Поскольку он не перерисовывается, любой код, который у вас есть внутри Template.box.onRendered, также не будет запускаться снова.

Такое поведение чаще всего встречается в ваших шаблонах layout, header и footer. Для многих пользователей эти шаблоны используются для всех страниц веб-сайта, независимо от пути. Поскольку шаблон макета, верхнего и нижнего колонтитула отображается при первом посещении сайта, они больше никогда не будут отображаться повторно, если пользователь решит перейти к другим частям сайта, используя те же шаблоны, поэтому код внутри Template.layout/header/footer.onRendered не срабатывает.

Также обратите внимание: даже если реактивный помощник пробелов изменяет физический вид макета / верхнего / нижнего колонтитула, он не квалифицируется как фактический render, поэтому реактивные обновления шаблона не вызывают обратный вызов onRendered.

Отсутствие повторного рендеринга — это то, что придает Метеору такое «быстрое» ощущение.

ИЗМЕНИТЬ

Попробуйте кодировать в реактивном стиле, управляемом событиями. Старайтесь не думать слишком много о рендере/повторном рендеринге.

  1. Вы идете к /box
  2. Вы нажимаете на ссылку для /box?box=2342
  3. Получите ваши параметры или запрос в Iron Router

https://github.com/iron-meteor/iron-router/blob/devel/Guide.md#route-parameters

  1. В Iron Router используйте данные из параметров или запроса, чтобы установить data context для шаблона.

  2. Захватите материал из контекста данных по мере необходимости внутри обратных вызовов шаблона .onRendered, .events и .helpers.

  3. При необходимости установите переменные сеанса и используйте их в помощниках, чтобы вносить реактивные изменения на страницу без необходимости повторного рендеринга шаблона. Также используйте события для запуска обновлений переменных сеанса, чтобы, опять же, вызвать реактивные изменения на странице.

Попробуй это:

после этого перейдите в /test?BUNNIES=lalalala

проверьте журналы консоли

test.html

<template name="test">

    {{myData}}

</template>

test.js

Template.test.helpers({

  myData: function() {
    console.log("data context accessed from test.helpers: ", this);
    console.log("this.BUNNIES accessed from test.helpers: ", this.BUNNIES);
    return this.BUNNIES;
  }

});

Template.test.onRendered(function() {

  console.log("data context accessed from test.onRendered: ", this.data);

});

Template.test.events({

  'click': function(){
    console.log("data accessed from test.events: ", this);
  }

});

router.js

Router.route('/test', function() {
  console.log("routed!");
  this.render('test');

}, {
  name: 'test',
  data: function(){
    //here I am setting the data context
    // for /test?BUNNIES=1234
    var query = this.params.query;
    console.log("query: ", query);

    return query;
  },
  waitOn: function() {
    console.log("waitOn is running (should see this message once for each subscription)");
    return [
      Meteor.subscribe('item_ownership_pub'),
      Meteor.subscribe('my_items')
    ];
  }
});

более чистый способ написания роутера

Router.route('/test', {
  waitOn: function() {
    console.log("waitOn is running (should see this message once for each subscription");
    return [
      Meteor.subscribe('item_ownership_pub'),
      Meteor.subscribe('my_items')
    ];
  },
  data: function(){
    var query = this.params.query;
    console.log("query: ", query);
    return query;
  },
  action: function(){
    console.log("this will re-render if url params changed");
    this.render();
  }
})
person fuzzybabybunny    schedule 14.06.2015
comment
Спасибо за это - я предполагал, что это так. Если у меня есть функция, которая отображает страницу (используя Blaze.renderWithData и т. д.), как запустить эту функцию из Iron Router? - person JoeTidee; 14.06.2015
comment
Я не могу сделать этот шаблон реактивным, поэтому я просто хочу запустить функцию, которая будет отображать шаблон по требованию. - person JoeTidee; 14.06.2015
comment
Маршрутизатор, как я его настроил, будет повторно отображать шаблон каждый раз при изменении пути. (т.е. от /test?box=1234 до `/test?box=0987`). Решите ли вы использовать реактивные переменные, зависит от вас. - person fuzzybabybunny; 14.06.2015
comment
Я также добавил более чистый способ написания функции маршрутизатора, так как таким образом вы можете визуально определить порядок, в котором работает Iron Router (сначала выполняет ожидание, затем устанавливает данные и, наконец, выполняет действие рендеринга). - person fuzzybabybunny; 14.06.2015