Meteor.js: повторное использование методов и функций в событиях и помощниках

Я новичок в Meteor.js и буду очень признателен за любую помощь, которую кто-либо может дать по следующим двум вопросам. Я делаю приложение для карточек, в котором вы нажимаете стрелку, чтобы показать следующую карточку. Карточки предварительно перемешиваются, и вы проходите всю колоду, нажимая на стрелку.

Router.route ( '/', function () {
    Session.set ('wordArray', _.shuffle( Words.find().fetch() ) );
    Session.set ( 'index', 0 )
    this.render('wordPage');
})

Мой шаблон wordPage выглядит следующим образом:

<template name="wordPage">
    <div class="post">
      <div id = "arrow-right" ></div>
      {{ > wordItem word index }}
    </div>
</template>

Мой wordPage.js выглядит следующим образом:

Template.wordPage.helpers ({
    word: function ( index ) {
        return Session.get ( 'wordArray' ) [ index ] ;
    },

    index: function () { return Session.get ( 'index' ); },
})

WordPage передает слово и индекс в более подробный шаблон с помощью метода, описанного выше.

Template.wordPage.events ( { 
    "click #arrow-right": function ( e ) {
        if ( Session.get ('index') < Session.get ('wordArray').length-1 ) {
            console.log(Session.get('index'));
            Session.set ( 'index', Session.get ( 'index' ) + 1);
        }
    }
} )

Мои два вопроса:

1) Я хотел бы перетасовывать карточки каждый раз, когда загружается страница, и единственный способ понять, как это сделать легко (т. е. без перетасовки всей базы данных MongoDB), — это сохранить всю колоду карточек в массиве через Сеансовая переменная. Как можно реализовать что-то, где я не использую переменную Sessions? Каков наилучший способ перетасовывать колоду каждый раз, когда я захожу в root или где-нибудь нажимаю кнопку перемешивания?

2) Я использую Session.get/Session.set МНОГО в файле wordPage.js. Есть ли способ сохранить эти функции, чтобы они были доступны как в помощниках wordPage, так и в событиях? Я попытался сделать что-то вроде этого:

var word = function ( index ) { return Session.get ( 'wordArray' ) [index]; }

за пределами блока помощников и событий, а затем просто пытается использовать слово (индекс). Но похоже, что это работает, только если я делаю слово глобальной переменной.

Большое спасибо заранее.


person Charles Zhu    schedule 07.05.2015    source источник


Ответы (2)


Когда у вас возникают серьезные проблемы с областью действия (где я могу это определить, как мне это использовать, хорошо, теперь мой код представляет собой беспорядок Session везде, я понятия не имею, как я манипулирую своими данными, и когда я пытаюсь что-то реорганизовать, я хотите спалить мой компьютер) у вас есть простое решение:
пакет.

Пакет позволит вам четко определить ваши данные и аккуратно импортировать их туда, где они вам нужны. Вы можете безболезненно определить уникальные средства доступа (а не Session повсюду). Вы можете раз и навсегда определить, что представляют собой ваши данные, как к ним осуществляется доступ, как они изменяются, удаляются, перемешиваются и т. д.


Вот шаблон для вашего варианта использования.

meteor create --package cards

Удалите тесты. В package.js удалите обратный вызов onTest, он вам пока не понадобится. Вам понадобятся underscore и mongo, поэтому добавьте их в обратный вызов onUse:

api.use('underscore');
api.use('mongo');

Теперь в вашем cards.js свежем файле:

Words = new Meteor.Collection('words'); //Notice the absence of var*
WordsAccessor = {
  get shuffledWords() {
    return _.shuffle( Words.find().fetch() );
  },
  wordFromIndex : function(index) {
    return Words.find().fetch()[index];
  },
  addWords : function(words) {
    words.forEach(function(word) {
      Words.insert(word);
    });
  }
};

Наконец, экспортируйте метод доступа:

api.export('WordsAccessor');

С таким узором вы можете делать практически все, что захотите. Вы можете создать массив слов, чтобы избежать постоянного попадания в минимонго, заполнить коллекцию Words при первом использовании,...


*Отсутствие оператора var означает, что переменная относится к области пакета и может быть экспортирована, а затем импортирована либо глобально с помощью meteor add, либо в другую область пакета с помощью api.use.

person Kyll    schedule 07.05.2015
comment
Большое спасибо. Однако я не могу заставить эти методы работать, и мое приложение не обнаруживает коллекцию слов: 1) Находится ли api.export в нижней части файлаcards.js? 2) Я объявляю Words = new Mongo... в lib/collections, так что должен ли я снова объявлять здесь? 3) Чтобы получить доступ к WordsAccessor, я должен просто ввести WordAccessor.shuffledWords в любом месте приложения, верно? Спасибо еще раз. - person Charles Zhu; 07.05.2015
comment
1) api.export экспортирует переменные по их имени после загрузки всего файла. 2) Да, или объявить его раз и навсегда в пакете (но вы можете столкнуться с проблемами области, если вы не экспортировали глобально Words!), объявить его дважды не так уж плохо в этом случае (это все тот же коллекция за ним). 3) Если вы экспортировали wordsAccessor и импортировали его глобально (с помощью команды meteor add или api.imply в другом пакете), то да, вы можете просто использовать wordsAccessors везде. - person Kyll; 08.05.2015
comment
Попался. Я прочитал немного больше, и тем, кто решился написать этот пост, чтение о том, как Connect.js и Express.js построены поверх Node, может помочь понять, что такое объект API в целом. Спасибо Килл. - person Charles Zhu; 11.05.2015

Просто чтобы улучшить приведенный выше ответ для отсутствующей детали: api.export('WordsAccessor'); нужно поместить в package.js:

Package.onUse(function(api) {...
person B Piltz    schedule 18.04.2016