5

我已经查看了很多 Meteor 示例,这些示例展示了如何实现应用程序设置和用户特定设置。我发现的唯一东西是Telesc.pe。它使用一个Settings集合。但是,它只有一个全局(对每个人都一样)应用程序设置。

在该示例的基础上,我创建了自己的settings集合,可在服务器和客户端上使用。

// Server and Client
Settings = new Meteor.Collection('settings');

在每条Settings记录中,都有一个userId等于“默认”或用户 ID 的字段。

{
  ...
  userId: 'Default' // <-- 'Default' or Meteor.userId()
}

我有我的发布功能发布默认(应用程序)设置和用户设置。(旁注:在这个应用程序中,每个人都已登录,不允许访客)

// Server
Meteor.publish('settings', function() {
  return Settings.find({userId: {$in: [this.userId, 'default']}});
});

这里的想法是用户将使用默认设置,直到他们更改设置,从而减少集合中的记录数。

我还尝试抽象出很多乏味的东西,并创建一些助手来为用户获取和设置设置。

// Server and Client

// get user specific settings, fallback to default settings
// (not sure if this is the best way, but it works)
settings = function() {
  return Settings.findOne({userId:Meteor.userId()}) 
      || Settings.findOne({userId:'default'});
};

// Get value of a specific setting
getSetting = function(key) {
  return Session.get('settingsLoaded') ? settings()[key] : undefined;
};

// Set value of a specific setting
setSetting = function(key, value) {
   // bunch of logic here to see if a user specific record exists
   // if so, do update
   // if not, do insert
};

到目前为止,这个实现似乎运行得相当好。我可以通过 m 辅助函数在控制台中设置和获取设置。

// in the console...
setSetting('foo', 'bar');
getSetting('foo') // == 'bar'

当我开始根据某些设置使我的应用程序行为不同时,我遇到的问题就会发生。例如,我有一个名为“phrases”的模板,里面有一个名为“phrases”的变量。我想根据用户的设置更改它们的排序方式。

Template.phrases.phrases = function () {
  var sort = {};

  var sortKey = getSetting('sortPhrasesBy'); // if I console.log this it is ALWAYS equal to 'title', 'body', or 'date', which is what I want.
  sort[sortKey] = 1;

  // returns cursor with all phrases, sorted
  return Phrases.find({}, {sort:sort});
};

除了我不断收到Deps异常,我不知道出了什么问题。

Exception from Deps recompute: TypeError: Cannot read property 'nodeName' of null
at Patcher.match (http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1540:12)
at http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1364:23
at visitNodes (http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1320:11)
at visitNodes (http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1321:9)
at visitNodes (http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1321:9)
at visitNodes (http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1321:9)
at visitNodes (http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1321:9)
at patch (http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1334:3)
at http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:698:7
at LiveRange.operate (http://localhost:3000/packages/liverange.js?b3097d72d458e645fd4f0021c8ff5189abe8d98a:491:9)

我不知道是什么原因造成的。:/

但是,这段代码确实有效!它确实根据用户设置的内容对短语进行排序。但是在控制台中,我可以看到每次更改设置时都会引发此异常。第一次加载没问题。

那么,我在这里做一些根本错误的事情吗?我必须承认,我还没有完全理解 Meteor 在幕后所做的事情。

我不知道这是否有帮助。但在我尝试实现设置集合之前,我使用了该Session对象。所以我有这样的事情:

// on client
Session.setDefault('sortPhrasesBy', 'title);

Template.phrases.phrases = function () {
  var sort = {};

  var sortKey = Session.get('sortPhrasesBy');
  sort[sortKey] = 1;

  // returns cursor with all phrases, sorted a certain way
  return Phrases.find({}, {sort:sort});
};

这没有问题。它只是不是真正的灵活。

我应该这样做吗?如果有人碰巧知道,我很想知道那些建造流星的人正在为那里的个人测试/项目中的设置做了什么。

抱歉这么长的帖子,我试图预测可能会问到关于我已经尝试过的内容等问题。

感谢您的任何帮助,您可以提供!

4

3 回答 3

11

Meteor 帐户系统(例如帐户密码)具有内置的用户特定设置概念作为用户对象的“配置文件”字段。它是自动发布的并且也是响应式的(因为 Meteor.user() 是响应式的)。

以下是相关文档:http ://docs.meteor.com/#meteor_user

关于“nodeName”错误,很难调试,但通常当我收到该错误时,这是​​因为我试图访问实际不存在的模板帮助程序中的部分 DOM。当我不小心有两个具有相同 ID 的 DOM 元素时,我也看到了它(使用子模板很容易做到)。

为了追踪它,我删除了代码,直到它停止发生,然后逐个添加它,直到找到根本原因。

于 2013-10-04T16:34:11.667 回答
1

我为 Meteor 编写的用户会话智能包非常适合这个用例。

它基本上就像 Meteor 的Session,但每个变量都与一个用户相关。它是被动的,所有的变化都是持久的。它在客户端上可用,在带有附加userId参数的服务器上可用。

于 2013-09-02T19:06:36.510 回答
0

这里的错误看起来像您在客户端创建了一个服务器端 Meteor.publish() 但没有创建相应的 Meteor.subscribe() 。您正在返回一个空集并尝试更改其属性。您可以将订阅放在 Deps.autorun 块中,或者直接将其包含在帮助程序中,如下所示:

Template.phrases.phrases = function () {
  var sort = {};
  Meteor.subscribe('settings');

  var sortKey = getSetting('sortPhrasesBy'); // if I console.log this it is ALWAYS equal to 'title', 'body', or 'date', which is what I want.
  sort[sortKey] = 1;

  // returns cursor with all phrases, sorted
  return Phrases.find({}, {sort:sort});
};

您可能想要使用像 iron-router 这样的包,它有钩子以确保您在加载数据之前确实拥有订阅。请参阅铁路由器

于 2013-11-20T08:56:30.793 回答