【问题标题】:Global variables in MeteorMeteor 中的全局变量
【发布时间】:2015-02-15 00:42:25
【问题描述】:

我有

var Schemas = {};

Meteor.isClient && Template.registerHelper("Schemas", Schemas);

Schemas.Person = new SimpleSchema({
  fullName: {
    type: String,
    index: 1,
    optional: true,
  },
  email: {
    type: String,
    optional: true
  },
  address: {
    type: String,
    optional: true
  },
  isActive: {
    type: Boolean,
  },
  age: {
    type: Number,
    optional: true
  }
});

在一个文件中

var Collections = {};

Meteor.isClient && Template.registerHelper("Collections", Collections);

Persons = Collections.Persons = new Mongo.Collection("Persons");
Persons.attachSchema(Schemas.Person);

在另一个文件中。

我收到错误 ReferenceError: Schemas is not defined。很明显,我必须在我的 collections.js 文件中定义 Schemas 而不是将它们分开。但是 Meteor 如何处理单独文件中的代码?我可以访问一些对象和变量,而另一些则无法访问。

【问题讨论】:

标签: javascript node.js meteor scope


【解决方案1】:

当您以经典的 JavaScript 方式定义变量时:

var someVar = 'someValue';

.js 文件的根目录中,Meteor 使用 IIFE 将其范围限定为文件。

如果你想定义一个全局变量,干脆不要写var,给:

someVar = 'someValue';

默认情况下,这将在您的所有应用程序中定义一个变量,尽管您可以通过在specific recognized folder(例如clientserver 文件夹)中编写该声明来限制它。

但是,这个变量不会首先被绝对定义。它将在 Meteor 运行定义它的实际代码时定义。因此,这可能不是最佳实践,因为您将难以处理加载顺序,并且它将使您的代码取决于 Meteor loads files: 您将文件放入哪个文件夹,文件的名称...您的如果你稍微接触一下你的架构,代码很容易出现混乱的错误。

正如我在another closely related post 中建议的,你应该直接去买一个包!

【讨论】:

  • 我尝试在 lib 目录中定义我的全局变量,但包肯定更健壮
  • 我想补充一点,这真的很酷,因为您可以在 /client 中有一个 constants.js 文件,在 /server 目录中还有另一个。如果你想在两者之间共享一个常量文件,你可以在 /lib/constants 中创建它。
  • 这不是 Meteor 问题。请参阅下面的 ReferenceError。
【解决方案2】:

Meteor 中使用 var 关键字声明的变量的作用域仅限于声明它们的文件。

如果你想创建一个全局变量这样做

Schemas = {}

【讨论】:

  • 我不确定我对此有何感想...是否没有 ES6/webpack 风格的方法可以从另一个文件导入变量以避免全局变量?
【解决方案3】:

ReferenceError 是节点错误。 Meteor 是一个基于 Node.js 的框架。

Node 具有全局范围(又名 Node 的 global 变量)。 如果您尝试访问未定义的全局变量,Node(不是 Meteor)会抛出此错误。

浏览器还有一个名为 window 的全局作用域,并且在访问未定义的变量时不会抛出 ReferenceErrors。

这是我喜欢为类添加功能的一种模式(它非常像 Meteor):

/lib/Helpers.js      <-- Helpers for everyone (node+browser)
/server/Helpers.js   <-- Server helpers (node)
/client/Helpers.js   <-- Client helpers (browser)

考虑这些实现:

// /lib/Helpers.js
Helpers = {/* functions */};  // Assigned to window.Helpers and global.Helpers

// /server/Helpers.js
Helpers = _.extend(Helpers, {/*more functions*/}

// /client/Helpers.js
Helpers = _.extend(Helpers, {/*more functions*/}

这是一个简单的例子。如果我不想担心加载顺序怎么办?为什么不在 /lib/Helpers.js 中使用 _.extend()?

// /lib/Helpers.js
// Helpers = {/* functions */};                  // Overwrites...
Helpers = _.extend(Helpers, {/* functions */});  // ReferenceError

因为如果未定义 Helpers,您将从 Node 收到 ReferenceError - 特别是用作参数的“Helpers”。 (Node 知道将 Helpers 分配为 global.Helpers)。

这里有两种“修复”此问题的方法:

1) 为某事分配助手

// /lib/Helpers.js
// Helpers = Helpers || {}    // would be another ReferenceError
if (typeof Helpers === 'undefined') Helpers = {};
Helpers = _.extend(Helpers, {/* functions */});

2) 使用来自全局的帮助器

// /lib/Helpers.js
Helpers = _.extend(global.Helpers, {/* functions */});  // works in node, but...

两者都很糟糕。

1) 的语法很糟糕。
2)在节点中工作,但在浏览器中没有全局。所以它没有达到它的目的。

所以我放弃了第一次在 lib 中覆盖它,如果有任何内容被覆盖,则查找运行时错误。

如果你有一个方便的跨浏览器语法,请评论:-) var 某事 = 某事 || {} something.blah = foo;

这是其他一些JS shorthand tips

【讨论】:

  • 请注意,第三段代码必须添加在每个需要使用全局变量的文件的开头,以供每个变量使用。
  • 你能解释一下你为什么提到 ES6 以及这与这个问题有什么关系吗?
  • @Fletch 嗯...实际上没有。所以我删除了它。出于某种原因,我认为 ES6 模块将有助于清理全局命名空间,但我找不到任何关于它的信息:-/
【解决方案4】:

会话变量是全局变量,可以在不同的文件/函数中轻松访问。 Session.setPersistent 用于在所有文件中持久设置变量名称。当他们的应用程序太大时,可能会限制使用会话变量,因为它们不会被删除(因此可能存在内存泄漏),并且可能会在控制台中出现错误(如果未定义左右)。文档链接:https://docs.meteor.com/api/session.html

【讨论】:

猜你喜欢
  • 2020-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 2013-10-06
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多