Meteor 快速指南



Meteor - 概述

根据 Meteor 官方文档:

Meteor 是一个用于开发现代 Web 和移动应用程序的全栈 JavaScript 平台。Meteor 包含一组关键技术,用于构建连接客户端的反应式应用程序,一个构建工具,以及来自 Node.js 和通用 JavaScript 社区的精选包。

特性

  • Web 和移动端 − Meteor 提供了一个用于开发 Web、Android 和 iOS 应用程序的平台。

  • 通用应用程序 − 适用于 Web 浏览器和移动设备的同一套代码。

  • − 大量易于安装和使用的包。

  • Meteor Galaxy − 用于 Meteor 应用程序部署的云服务。

优势

  • 开发者只需要 JavaScript 即可进行服务器端和客户端开发。
  • 编码非常简单,易于上手。
  • Meteor 应用默认情况下是实时的。
  • 官方和社区包极大地节省了时间。

局限性

  • Meteor 不太适合大型和复杂的应用程序。

  • 使用 Meteor 时会发生很多“魔法”,因此开发者可能会发现自己在某些方面受到限制。

Meteor - 环境搭建

在本章中,我们将学习如何在 Windows 操作系统上安装 Meteor。在开始使用 Meteor 之前,我们需要 NodeJS。如果您尚未安装,可以查看下面提供的链接。

先决条件

NodeJS 是 Meteor 开发所需的平台。如果您还没有准备好 NodeJS 环境,可以查看我们的 NodeJS 环境搭建

安装 Meteor

此页面 下载官方 Meteor 安装程序

如果安装过程中出现任何错误,请尝试以管理员身份运行安装程序。安装完成后,系统会要求您创建一个 Meteor 帐户。

安装 Meteor 安装程序后,您可以通过在命令提示符窗口中运行以下代码来测试是否一切安装正确。

C:\Users\username>meteor

输出如下:

Meteor Installation Test

Meteor - 第一个应用

在本章中,我们将学习如何创建您的第一个 Meteor 应用程序。

步骤 1 - 创建应用程序

要创建应用程序,我们将从命令提示符窗口运行 meteor create 命令。应用程序名称将为 meteorApp

C:\Users\username\Desktop\Meteor>meteor create meteorApp

步骤 2 - 运行应用程序

我们可以通过键入 meteor 命令来运行应用程序。

C:\Users\username\Desktop\meteorApp>meteor

此命令将启动多个进程,如下图所示。

Meteor First App Run

步骤 3 - 验证结果

现在,我们可以打开 https://127.0.0.1:3000/ 地址来查看我们的第一个 Meteor 应用是什么样的。

Meteor First App Output

Meteor - 模板

Meteor 模板使用三个顶级标签。前两个是 headbody。这些标签的功能与常规 HTML 中的相同。第三个标签是 template。在这里,我们将 HTML 连接到 JavaScript。

简单的模板

下面的示例展示了它的工作方式。我们正在创建一个带有 name = "myParagraph" 属性的模板。我们的 template 标签创建在 body 元素的下方,但是我们需要在它渲染到屏幕上之前包含它。我们可以使用 {{> myParagraph}} 语法来实现。在我们的模板中,我们使用了双大括号 ({{text}})。这是名为 Spacebars 的 Meteor 模板语言。

在我们的 JavaScript 文件中,我们设置了 Template.myParagraph.helpers({}) 方法,这将是我们与模板的连接。在这个示例中,我们只使用了 text 助手。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <h1>Header</h1>
   {{> myParagraph}}
</body>
 
<template name = "myParagraph">
   <p>{{text}}</p>
</template>

meteorApp.js

if (Meteor.isClient) {
   
   // This code only runs on the client
   Template.myParagraph.helpers({
      text: 'This is paragraph...'
   });
}

保存更改后,输出如下:

Meteor Templates Output

块模板

在下面的示例中,我们使用 {{#each paragraphs}} 迭代 paragraphs 数组,并为每个值返回模板 name = "paragraph"

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div>
      {{#each paragraphs}}
         {{> paragraph}}
      {{/each}}
   </div>
</body>
 
<template name = "paragraph">
   <p>{{text}}</p>
</template>

我们需要创建 paragraphs 助手。这将是一个包含五个文本值的数组。

meteorApp.js

if (Meteor.isClient) {
   
   // This code only runs on the client
   Template.body.helpers({
      paragraphs: [
         { text: "This is paragraph 1..." },
         { text: "This is paragraph 2..." },
         { text: "This is paragraph 3..." },
         { text: "This is paragraph 4..." },
         { text: "This is paragraph 5..." }
      ]
   });
}

现在,我们可以看到屏幕上出现了五个段落。

Meteor Templates Output 2

Meteor - 集合

在本章中,我们将学习如何使用 MongoDB 集合。

创建集合

我们可以使用以下代码创建一个新的集合:

meteorApp.js

MyCollection = new Mongo.Collection('myCollection');

添加数据

创建集合后,我们可以使用 insert 方法添加数据。

meteorApp.js

MyCollection = new Mongo.Collection('myCollection');

var myData = {
   key1: "value 1...",
   key2: "value 2...",
   key3: "value 3...",
   key4: "value 4...",
   key5: "value 5..."
}

MyCollection.insert(myData);

查找数据

我们可以使用 find 方法搜索集合中的数据。

meteorApp.js

MyCollection = new Mongo.Collection('myCollection');

var myData = {
   key1: "value 1...",
   key2: "value 2...",
   key3: "value 3...",
   key4: "value 4...",
   key5: "value 5..."
}

MyCollection.insert(myData);

var findCollection = MyCollection.find().fetch();
console.log(findCollection);

控制台将显示我们之前插入的数据。

Meteor Collection Find

我们可以通过添加搜索参数来获得相同的结果。

meteorApp.js

MyCollection = new Mongo.Collection('myCollection');

var myData = {
   key1: "value 1...",
   key2: "value 2...",
   key3: "value 3...",
   key4: "value 4...",
   key5: "value 5..."
}

MyCollection.insert(myData);

var findCollection = MyCollection.find({key1: "value 1..."}).fetch();
console.log(findCollection);

更新数据

下一步是更新我们的数据。创建集合并插入新数据后,我们可以使用 update 方法。

meteorApp.js

MyCollection = new Mongo.Collection('myCollection');

var myData = {
   key1: "value 1...",
   key2: "value 2...",
   key3: "value 3...",
   key4: "value 4...",
   key5: "value 5..."
}

MyCollection.insert(myData);

var findCollection = MyCollection.find().fetch();
var myId = findCollection[0]._id;

var updatedData = {
   key1: "updated value 1...",
   key2: "updated value 2...",
   key3: "updated value 3...",
   key4: "updated value 4...",
   key5: "updated value 5..."
}

MyCollection.update(myId, updatedData);

var findUpdatedCollection = MyCollection.find().fetch();
console.log(findUpdatedCollection);

控制台将显示我们的集合已更新。

Meteor Collections Update

删除数据

可以使用 remove 方法从集合中删除数据。在这个示例中,我们将 id 作为参数来删除特定数据。

meteorApp.js

MyCollection = new Mongo.Collection('myCollection');

var myData = {
   key1: "value 1...",
   key2: "value 2...",
   key3: "value 3...",
   key4: "value 4...",
   key5: "value 5..."
}

MyCollection.insert(myData);

var findCollection = MyCollection.find().fetch();
var myId = findCollection[0]._id;

MyCollection.remove(myId);

var findDeletedCollection = MyCollection.find().fetch();
console.log(findDeletedCollection);

控制台将显示一个空数组。

Meteor Collections Remove

如果要删除集合中的所有内容,可以使用相同的方法,但是,我们将使用空对象 {} 代替 id。出于安全原因,我们需要在服务器端执行此操作。

meteorApp.js

if (Meteor.isServer) {

   MyCollection = new Mongo.Collection('myCollection');

   var myData = {
      key1: "value 1...",
      key2: "value 2...",
      key3: "value 3...",
      key4: "value 4...",
      key5: "value 5..."
   }

   MyCollection.insert(myData);
   MyCollection.remove({});
	
   var findDeletedCollection = MyCollection.find().fetch();
   console.log(findDeletedCollection);
}

我们还可以使用其他参数删除数据。与前面的示例一样,Meteor 将强制我们从服务器端执行此操作。

meteorApp.js

if (Meteor.isServer) {

   MyCollection = new Mongo.Collection('myCollection');

   var myData = {
      key1: "value 1...",
      key2: "value 2...",
      key3: "value 3...",
      key4: "value 4...",
      key5: "value 5..."
   }

   MyCollection.insert(myData);
   MyCollection.remove({key1: "value 1..."});
	
   var findDeletedCollection = MyCollection.find().fetch();
   console.log(findDeletedCollection);
}

可以看出数据已从命令窗口中删除。

Meteor Collections Remove Server

Meteor - 表单

在本章中,我们将学习如何使用 Meteor 表单。

文本输入

首先,我们将创建一个带有文本输入字段和提交按钮的 form 元素。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div>
      {{> myTemplate}}
   </div>
</body>
 
<template name = "myTemplate">
   <form>
      <input type = "text" name = "myForm">
      <input type = "submit" value = "SUBMIT">
   </form>
</template>

在 JavaScript 文件中,我们将创建 submit 事件。我们需要阻止默认事件行为以阻止浏览器刷新。接下来,我们将获取输入字段的内容并将其赋值给 textValue 变量。

在下面的示例中,我们只将内容记录到开发人员控制台中。最后我们需要清除输入字段。

meteorApp.js

if (Meteor.isClient) {

   Template.myTemplate.events({

      'submit form': function(event) {
         event.preventDefault();
         var textValue = event.target.myForm.value;
         console.log(textValue);
         event.target.myForm.value = "";
      }
   });
}

当我们在输入字段中键入“Some text...”并提交时,控制台将记录我们输入的文本。

Meteor Forms Text

单选按钮

单选按钮可以使用类似的概念。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div>
      {{> myTemplate}}
   </div>
</body>
 
<template name = "myTemplate">
   <form>
      <input type = "radio" name = "myForm" value = "form-1">FORM 1
      <input type = "radio" name = "myForm" value = "form-2">FORM 2
      <input type = "submit" value = "SUBMIT">
   </form>
</template>

meteorApp.js

if (Meteor.isClient) {

   Template.myTemplate.events({

      'submit form': function(event) {
         event.preventDefault();
         var radioValue = event.target.myForm.value;
         console.log(radioValue);
      }
   });
}

当我们提交第一个按钮时,控制台将显示以下输出。

Meteor Forms Radio

复选框

下面的示例展示了如何使用复选框。您可以看到我们只是重复相同的过程。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div>
      {{> myTemplate}}
   </div>
</body>
 
<template name = "myTemplate">
   <form>
      <input type = "checkbox" name = "myForm" value = "form-1">FORM 1
      <input type = "checkbox" name = "myForm" value = "form-2">FORM 2
      <input type = "submit" value = "SUBMIT">
   </form>
</template>

meteorApp.js

if (Meteor.isClient) {

   Template.myTemplate.events({
   
      'submit form': function(event) {
         event.preventDefault();
         var checkboxValue1 = event.target.myForm[0].checked;
         var checkboxValue2 = event.target.myForm[1].checked;
         console.log(checkboxValue1);
         console.log(checkboxValue2);
      }
   });
}

提交表单后,已选中的输入将被记录为 true,而未选中的输入将被记录为 false

Meteor Forms Checkbox

下拉选择

在下面的示例中,我们将学习如何使用 select 元素。我们将使用 change 事件来更新每次选项更改时的数据。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div>
      {{> myTemplate}}
   </div>
</body>
 
<template name = "myTemplate">
   <select>
      <option name = "myOption" value = "option-1">OPTION 1</option>
      <option name = "myOption" value = "option-2">OPTION 2</option>
      <option name = "myOption" value = "option-3">OPTION 3</option>
      <option name = "myOption" value = "option-4">OPTION 4</option>
   </select>
</template>

meteorApp.js

if (Meteor.isClient) {

   Template.myTemplate.events({

      'change select': function(event) {
         event.preventDefault();
         var selectValue = event.target.value;
         console.log(selectValue);
      }
   });
}

如果我们选择第三个选项,控制台将记录选项值。

Meteor Forms Select

Meteor - 事件

在本章中,我们将学习如何使用 标签、类id 作为事件选择器。使用事件非常简单。

让我们在 HTML 模板中创建三个元素。第一个是 p,第二个是 myClass 类,最后一个是 myId id。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div>
      {{> myTemplate}}
   </div>
</body>
 
<template name = "myTemplate">
   <p>PARAGRAPH...</p>
   <button class = "myClass">CLASS</button>
   <button id = "myId">ID</button>
</template>

在我们的 JavaScript 文件中,我们为上面创建的三个元素设置了三个事件。您可以看到我们只是在 click 事件后添加了 p、.myClass#myId。这些是我们上面提到的 选择器

meteorApp.js

if (Meteor.isClient) {

   Template.myTemplate.events({

      'click p': function() {
         console.log("The PARAGRAPH is clicked...");
      },

      'click .myClass': function() {
         console.log("The CLASS is clicked...");
      },

      'click #myId': function() {
         console.log("The ID is clicked...");
      },
   });
}

要测试这一点,我们可以先单击 PARAGRAPH,然后单击 CLASS 按钮,最后单击 ID 按钮。我们将得到以下控制台日志。

Meteor Events Log

我们可以使用所有其他 JavaScript 事件——click、dbclick、contextmenu、mousedown、mouseup、mouseover、mouseout、mousemove——按照上面的示例。

Meteor - Session

Session 用于在用户使用应用程序时保存数据。当用户离开应用程序时,这些数据将被删除。

在本章中,我们将学习如何设置 session 对象,存储一些数据,并返回这些数据。我们将使用基本的 HTML 设置。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div>
      {{> myTemplate}}
   </div>
</body>
 
<template name = "myTemplate">
</template>

现在,我们将使用 Session.set() 方法在本地存储 myData。设置该方法后,我们可以使用 Session.get() 方法返回它。

meteorApp.js

if (Meteor.isClient) {
  
   var myData = {
      key1: "value1",
      key2: "value2"
   }

   Session.set('mySession', myData);

   var sessionDataToLog = Session.get('mySession');
   console.log(sessionDataToLog);
}

如果我们检查控制台,我们将看到已存储的数据被记录。

Meteor Session Log

在下一章中,我们将学习如何使用 Session 变量自动更新模板。

Meteor - Tracker

Tracker 是一个小型库,用于在 Session 变量更改后自动更新模板。在本章中,我们将学习 Tracker 的工作原理。

首先,我们将创建一个 button,用于更新 session。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div>
      {{> myTemplate}}
   </div>
</body>
 
<template name = "myTemplate">
   <button id = "myButton">CLICK ME</button>
</template>

接下来,我们将设置起始 session 值 myData 并创建一个 mySession 对象。Tracker.autorun 方法用于监控 mySession。每当此对象更改时,模板将自动更新。为了测试它,我们将为更新设置一个 click 事件。

meteorApp.js

if (Meteor.isClient) {
  
   var myData = 0
   Session.set('mySession', myData);

   Tracker.autorun(function () {
      var sessionData = Session.get('mySession');
      console.log(sessionData)
   });

   Template.myTemplate.events({

      'click #myButton': function() {
         Session.set('mySession', myData ++);
      }
   });
}

如果我们单击 CLICK ME 按钮五次,我们将看到 Tracker 每次 session 更新时都会记录新值。

Meteor Tracker Log

Meteor - 包

Meteor 提供了数千个社区包,您可以在开发应用程序时使用。

添加包

您可以查看官方 Meteor 包服务器 这里。只需搜索您需要的包,然后在命令提示符窗口中添加它。例如,如果您想将 http 包添加到您的应用程序,您可以运行以下代码:

C:\Users\username\Desktop\meteorApp>meteor add http

删除包

可以使用类似的原理来删除包:

C:\Users\username\Desktop\meteorApp>meteor remove http

更新包

您可以运行以下代码来更新包:

C:\Users\username\Desktop\meteorApp>meteor update http

检查当前包

您还可以检查当前应用程序正在使用哪些包。

C:\Users\username\Desktop\meteorApp>meteor list

包维护

如果包的名称中包含 :,则表示它是社区包,而没有前缀的包由 Meteor 开发组维护。

添加 Meteor 开发组包

C:\Users\username\Desktop\meteorApp>meteor add http

添加社区包

C:\Users\username\Desktop\meteorApp>meteor add cfs:http-methods

Meteor - 核心 API

如果您想限制代码仅在服务器端或客户端运行,可以使用以下代码:

meteorApp.js

if (Meteor.isClient) {
   // Code running on client...
}

if (Meteor.isServer) {
   // Code running on server...
}

您可以限制代码仅在应用程序使用 Cordova 打包时运行。

if (Meteor.isCordova) {
   // Code running on Cordova...
}

有些插件需要等待服务器和 DOM 准备好。您可以使用以下代码等待一切开始。

Meteor.startup(function () {
   // Code running after platform is ready...
});

下表列出了一些其他核心 API 方法。

序号 方法及详情
1

Meteor.wrapAsync(function)

用于包装异步代码并将其转换为同步代码。

2

Meteor.absoluteUrl([path], [options])

用于生成指向应用程序的绝对URL。

3

Meteor.settings

用于设置部署配置。

4

Meteor.publish(name, function)

用于将记录发布到客户端。

Meteor - 检查

check 方法用于检查参数或类型是否与模式匹配。

安装 Check 包

打开命令提示符窗口并安装包。

C:\Users\username\Desktop\meteorApp>meteor add check

使用 Check

在下面的示例中,我们想检查myValue是否为字符串。由于它是真值,应用程序将继续运行而不会出现任何错误。

meteorApp.js

var myValue = 'My Value...';
check(myValue, String);

在这个示例中,myValue不是字符串而是数字,因此控制台将记录错误。

meteorApp.js

var myValue = 1;
check(myValue, String);
Meteor Check Log Error

Match Test

Match.test类似于check,区别在于测试失败时,不会出现控制台错误,而是会得到一个而不会中断服务器。以下示例演示如何测试具有多个键的对象。

meteorApp.js

var myObject = {
   key1 : "Value 1...",
   key2 : "Value 2..."
}

var myTest = Match.test(myObject, {
   key1: String,
   key2: String
});

if ( myTest ) {
   console.log("Test is TRUE...");
} else {
   console.log("Test is FALSE...");
}

由于两个键都是字符串,因此测试结果为true。控制台将记录第一个选项。

Meteor Match Test True

如果我们将key2更改为数字,则测试将失败,控制台将记录第二个选项。

meteorApp.js

var myObject = {
   key1 : "Value 1...",
   key2 : 1
}

var myValue = 1;

var myTest = Match.test(myObject, {
   key1: String,
   key2: String
});

if ( myTest ) {
   console.log("Test is TRUE...");
} else {
   console.log("Test is FALSE...");
}
Meteor Match Test False

Meteor - Blaze

Blaze 是一个用于构建实时响应式模板的 Meteor 包。

渲染方法

此方法用于将模板渲染到 DOM。首先,我们将创建将要渲染的myNewTemplate。我们还将添加myContainer,它将用作父元素,以便render方法知道在哪里渲染我们的模板。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div id = "myContainer">
   </div>
</body>

<template name = "myNewTemplate">
   <p>Text from my new template...</p>
</template>

接下来,我们将创建一个渲染函数,它将接受两个参数。第一个是要渲染的模板,第二个是我们上面提到的父元素。

meteorApp.js

Meteor.startup(function () {

   if(Meteor.isClient) {
      var myNewTemplate = Template.myNewTemplate;
      var myContainer = document.getElementById('myContainer');
      Blaze.render(myNewTemplate, myContainer);
   }
});
Meteor Blaze Render

使用数据进行渲染

如果需要以响应方式传递一些数据,可以使用renderWithData方法。HTML 将与上一个示例完全相同。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div id = "myContainer">
   </div>
</body>

<template name = "myNewTemplate">
   <p>Text from my new template...</p>
</template>

我们可以在Meteor.renderWithData方法中将数据作为第二个参数添加。其他两个参数与上一个示例相同。在这个示例中,我们的数据是一个将记录一些文本的函数。

meteorApp.js

Meteor.startup(function () {

   if(Meteor.isClient) {
      var myNewTemplate = Template.myNewTemplate;
		
      var myData = function() {
         console.log('Log from the data object...')
      }

      var myContainer = document.getElementById('myContainer');
      Blaze.renderWithData(myNewTemplate, myData, myContainer);
   }
});
Meteor Blaze Render With Data

移除方法

我们可以添加remove方法。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div id = "myContainer">
   </div>
</body>

<template name = "myNewTemplate">
   <p>Text from my new template...</p>
</template>

在这个示例中,我们正在渲染一个将在三秒钟后移除的模板。请注意我们用来移除模板的Blaze.Remove方法。

meteorApp.js

Meteor.startup(function () {

   if(Meteor.isClient) {
      var myNewTemplate = Template.myNewTemplate;
      var myContainer = document.getElementById('myContainer');
      var myRenderedTemplate = Blaze.render(myNewTemplate, myContainer);

      Meteor.setTimeout(function() {
         Blaze.remove(myRenderedTemplate);
      }, 3000);
   }
});

下表显示了可使用的其他方法。

序号 方法及详情
1

Blaze.getData([elementOrView])

用于从渲染元素中检索数据。

2

Blaze.toHTML(templateOrView)

用于将模板或视图渲染为字符串。

3

Blaze.toHTMLWithData(templateOrView, data)

用于将模板或视图渲染为带有附加数据的字符串。

4

new Blaze.View([name], renderFunction)

用于创建 DOM 的一个新的 Blaze 响应式部分。

5

Blaze.currentView

用于获取当前视图。

6

Blaze.getView([element])

用于获取当前视图。

7

Blaze.With(data, contentFunc)

用于构造一个使用上下文渲染某些内容的视图。

8

Blaze.If(conditionFunc, contentFunc, [elseFunc])

用于构造一个渲染某些条件内容的视图。

9

Blaze.Unless(conditionFunc, contentFunc, [elseFunc])

用于构造一个渲染某些条件内容的视图(Blaze.if 的反向操作)。

10

Blaze.Each(argFunc, contentFunc, [elseFunc])

用于构造一个为每个项目渲染contentFunc的视图。

11

new Blaze.Template([viewName], renderFunction)

用于使用名称和内容构造一个新的 Blaze 视图。

12

Blaze.isTemplate(value)

如果值为模板对象,则返回 true。

Meteor - 定时器

Meteor 提供了自己的setTimeoutsetInterval方法。这些方法用于确保所有全局变量具有正确的的值。它们的工作方式与普通的 JavaScript setTimoutsetInterval相同。

超时

这是一个Meteor.setTimeout示例。

Meteor.setTimeout(function() {
   console.log("Timeout called after three seconds...");
}, 3000);

我们可以在控制台中看到,一旦应用程序启动,超时函数就会被调用。

Meteor Timeout

间隔

以下示例演示如何设置和清除间隔。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   <div>
      {{> myTemplate}}
   </div>
</body>
 
<template name = "myTemplate">
   <button>CLEAR</button>
</template>

我们将设置初始counter变量,该变量将在每次间隔调用后更新。

meteorApp.js

if (Meteor.isClient) {

   var counter = 0;

   var myInterval = Meteor.setInterval(function() {
      counter ++
      console.log("Interval called " + counter + " times...");
   }, 3000);

   Template.myTemplate.events({

      'click button': function() {
         Meteor.clearInterval(myInterval);
         console.log('Interval cleared...')
      }
   });
}

控制台将每三秒钟记录一次更新后的counter变量。我们可以通过单击CLEAR按钮来停止此操作。这将调用clearInterval方法。

Meteor Interval

Meteor - EJSON

EJSON 是 JSON 语法的扩展,支持DateBinary类型。

安装 EJSON

要安装 EJSON 包,我们需要从命令提示符窗口中添加它。

C:\Users\username\Desktop\meteorApp>meteor add ejson

日期示例

我们可以使用parse方法反序列化date

if (Meteor.isClient) {
   var myEjsonDate = '{"$date": 1455029631493}';
   var myDate = EJSON.parse(myEjsonDate);
   console.log(myDate);
}

控制台将记录正确的日期值。

Meteor EJSON Date

二进制示例

同样的方法可以应用于二进制类型。

if (Meteor.isClient) {
   var myEjsonBinary = '{"$binary": "c3VyZS4="}';
   var myBinary = EJSON.parse(myEjsonBinary);
   console.log(myBinary);
}

您可以看到控制台正在记录新的反序列化值。

Meteor EJSON Binary

序列化

我们可以使用stringify方法序列化对象。这是上面示例的反向过程。

if (Meteor.isClient) {

   var myObject = {
      myDate : new Date(),
      myBinary : new Uint8Array([115, 117, 114, 101, 46])
   }

   var myEjosnData = EJSON.stringify(myObject);
   console.log(myEjosnData);
}

我们可以在控制台中看到我们的新值。

Meteor EJSON Stringify

序号 方法及详情
1

EJSON.parse(string)

用于将字符串解析为 EJSON 值。

2

EJSON.stringify(value)

用于将值序列化为字符串。

3

EJSON.fromJSONValue(value)

用于从 JSON 反序列化 EJSON 值。

4

EJSON.toJSONValue(value)

用于将 EJSON 值序列化为 JSON。

5

EJSON.equals(value1, value2)

用于比较两个值是否相等。

6

EJSON.clone(value)

用于返回值的深拷贝。

7

EJSON.newBinary

用于赋值 EJSON 可以序列化的二进制数据。

8

EJSON.isBinary(x)

用于检查值是否为二进制数据。

9

EJSON.addType(name, factory)

用于创建自定义 EJSON 类型。

10

customType.typeName()

用于返回自定义类型的名称。

11

customType.toJSONValue()

用于序列化自定义类型。

12

customType.clone()

用于返回自定义类型的深拷贝。

13

customType.equals(otherValue)

用于比较自定义类型值和其他值。

Meteor - HTTP

此包提供带有get、post、putdelete方法的 HTTP 请求 API。

安装包

我们将在命令提示符窗口中运行以下代码来安装此包。

C:\Users\username\Desktop\meteorApp>meteor add http

CALL 方法

这是一个通用方法,可以使用GETPOSTPUTDELETE参数。以下示例演示如何使用GET参数。本章中的示例将使用来自此网站的伪造 REST API。

您可以看到此方法使用了四个参数。我们已经提到了第一个参数GET。第二个是 API URL。第三个参数是一个空对象,我们可以在其中设置一些可选参数。最后的方法是一个异步回调,我们可以在其中处理错误并使用响应。

HTTP.call( 'GET', 'http://jsonplaceholder.typicode.com/posts/1', {},
   function( error, response ) {

   if (error) {
      console.log(error);
   } else {
      console.log(response);
   }
});

GET 方法

可以使用GET代替CALL方法发送相同的请求。您可以看到第一个参数现在是 API URL。

HTTP.get('http://jsonplaceholder.typicode.com/posts/1', {}, function( error, response ) {

   if ( error ) {
      console.log( error );
   } else {
      console.log( response );
   }
});

前面两个示例将记录相同的输出。

Meteor HTTP Call

POST 方法

在此方法中,我们将需要发送到服务器的数据 (postData) 作为第二个参数。其他所有内容与我们的GET请求相同。

var postData = {

   data: {
      "name1": "Value1",
      "name2": "Value2",
   }
}

HTTP.post( 'http://jsonplaceholder.typicode.com/posts', postData, 
   function( error, response ) {

   if ( error ) {
      console.log( error );
   } else {
      console.log( response);
   }
});

控制台将记录我们的postData对象。

Meteor HTTP Post

PUT 方法

我们可以使用PUT方法更新我们的数据。概念与我们上一个示例相同。

var updateData = {

   data: {
      "updatedName1": "updatedValue1",
      "UpdatedName2": "updatedValue2",
   }
}

HTTP.put( 'http://jsonplaceholder.typicode.com/posts/1', updateData, 
   function( error, response ) {
	
   if ( error ) {
      console.log( error );
   } else {
      console.log( response );
   }
});

现在,我们可以在控制台中看到我们更新后的对象。

Meteor HTTP Put

DEL 方法

我们可以使用DEL方法向服务器发送删除请求。我们将删除data对象中的所有内容。

var deleteData = {
   data: {}
}

HTTP.del( 'http://jsonplaceholder.typicode.com/posts/1', deleteData, 
   function( error, response ) {
	
   if ( error ) {
      console.log( error );
   } else {
      console.log( response );
   }
});

控制台将显示删除过程成功。

Meteor HTTP Del

Meteor - 邮件

当您需要从 Meteor 应用程序发送电子邮件时,可以使用此包。

步骤 1 - 添加包

打开命令提示符窗口并运行以下命令:

C:\Users\username\Desktop\meteorApp>meteor add email

步骤 2 - Mailgun 帐户

我们需要在这里创建一个帐户这里。这是 Meteor 应用程序的默认电子邮件提供商。

登录后,打开Domains选项卡,然后单击Domain Name下方的sandbox URL。它将打开一个新页面,我们可以在其中找到Default SMTP LoginDefault Password。创建MAIL_URL环境变量需要这两个值。

发送电子邮件

要创建一个有效的MAIL_URL,只需将您的 Mailgun 凭据插入YOUR_DEFAULT_SMTP_LOGINYOUR_DEFAULT_PASSWORD的位置。

if (Meteor.isServer) {

   Meteor.startup( function() {
      process.env.MAIL_URL = 
         "smtp://YOUR_DEFAULT_SMTP_LOGIN:[email protected]:587";

      Email.send({
         to: "[email protected]",
         from: "[email protected]",
         subject: "Meteor Email",
         text: "The email content..."
      });
   });
}

运行应用程序时,电子邮件将发送到您的地址。

Meteor Email Received

Meteor - 资源

静态服务器资源位于应用程序内的private子文件夹中。在以下示例中,我们将学习如何使用简单 JSON 文件中的数据。

步骤 1 - 创建文件和文件夹

让我们创建一个private文件夹和该文件夹内的my-json.json文件。我们将使用命令提示符窗口中的以下命令执行此操作,但是您也可以手动创建它。

C:\Users\username\Desktop\meteorApp>mkdir private

C:\Users\username\Desktop\meteorApp\private>touch my-json.json

步骤 2 - 获取文本

为了能够读取文件中的数据,我们将使用Asssets.getText方法。请注意,这只能在服务器端完成。由于我们使用的是 JSON,因此需要对其进行解析。

if (Meteor.isServer) {
   var myFile = JSON.parse(Assets.getText('my-json.json'));
   console.log(myFile.data.text)
}

命令提示符窗口中的输出如下。

Meteor Assets Get Text

步骤 3 - 创建 EJSON 文件

我们将在private文件夹内创建此文件。此文件将包含二进制数据"myBinary": {"$binary": "c3VyZS4="}

C:\Users\username\Desktop\meteorApp\private>touch my-ejson.ejson

步骤 4 - 获取二进制数据

要读取 EJSON 文件,我们可以使用Assets.getBinary方法。

if (Meteor.isServer) {
   var myFile = Assets.getBinary('my-ejson.ejson');
   console.log(EJSON.stringify(myFile));
}

命令提示符将记录 EJSON 值。

Meteor Assets Get Binary

Meteor - 安全

在本章中,我们将学习如何保护我们的应用程序,以及在开发应用程序时应考虑的事项。

Autopublish 和 Insecure

Autopublish是一个自动将数据库中的所有数据发布到客户端的包。这是一个便利功能,在生产环境中应将其禁用。可以从命令提示符禁用它。

C:\Users\username\Desktop\meteorApp>meteor remove autopublish

您可以使用Meteor.publish()Meteor.subscribe()方法将一些数据发布到客户端,我们将在“发布和订阅”一章中介绍这些方法。

Insecure是一个允许在开发者控制台中编写 MongoDB 命令的包,这样应用程序的每个用户都能够访问数据库。可以通过在命令提示符中运行以下命令来删除该包。

C:\Users\username\Desktop\meteorApp>meteor remove insecure

良好的做法是在您开始开发应用程序后立即删除这两个包,这样您以后就不必更改和更新代码了。

使用服务器端方法

您应该始终在服务器上创建方法。您可以使用服务器上的Meteor.methods()和客户端上的Meteor.call()来做到这一点。我们将在方法一章中详细了解这一点。

其他安全措施

如果您想为您的应用程序添加额外的安全层,您应该考虑使用其他一些 Meteor 包,例如:

  • 浏览器策略 (Browser Policy) 可用于控制应加载到您的应用程序的外部资源。

  • Check 包可用于检查用户输入类型,然后再进行处理。

  • 审计参数检查 (Audit Arguments Check) 是一个包,它将确保在处理之前正确检查所有参数。如果您错过了某些参数,此包将通知您。

  • Mylar 包可以添加一些额外的安全层。如果您需要那种保护,可以查看它们。

Meteor - 排序

我们可以在从数据库获取数据后对其进行排序。在下面的示例中,我们将创建一个 **Users** 集合。我们将使用 **sort** 参数 (**{sort: {name: 1}}**) 来按名称对集合数据进行排序。数字 **1** 用于设置升序。如果我们想使用降序,我们将使用 **-1** 代替。

Users = new Mongo.Collection('users');

Users.insert({
   name: 'James',
   email: '[email protected]',
   joined: new Date(2016, 2, 23)
});

Users.insert({
   name: 'John',
   email: '[email protected]',
   joined: new Date(2016, 2, 19)
});

Users.insert({
   name: 'Jennifer',
   email: '[email protected]',
   joined: new Date(2016, 6, 24)
});

var sortByName = Users.find({}, {sort: {name: 1}}).fetch();

var sortByEmail = Users.find({}, {sort: {email: 1}}).fetch();

var sortByJoined = Users.find({}, {sort: {joined: 1}}).fetch();

console.log(sortByName);
console.log(sortByEmail);
console.log(sortByJoined);
Meteor Sorting Name

我们可以用同样的方法按电子邮件对数据进行排序。

Users = new Mongo.Collection('users');

Users.insert({
   name: 'James',
   email: '[email protected]',
   joined: new Date(2016, 2, 23)
});

Users.insert({
   name: 'John',
   email: '[email protected]',
   joined: new Date(2016, 2, 19)
});

Users.insert({
   name: 'Jennifer',
   email: '[email protected]',
   joined: new Date(2016, 6, 24)
});

var sortByEmail = Users.find({}, {sort: {email: 1}}).fetch();

console.log(sortByEmail);
Meteor Sorting Email

最后,我们可以按加入日期对其进行排序。

Users = new Mongo.Collection('users');

Users.insert({
   name: 'James',
   email: '[email protected]',
   joined: new Date(2016, 2, 23)
});

Users.insert({
   name: 'John',
   email: '[email protected]',
   joined: new Date(2016, 2, 19)
});

Users.insert({
   name: 'Jennifer',
   email: '[email protected]',
   joined: new Date(2016, 6, 24)
});

var sortByJoined = Users.find({}, {sort: {joined: 1}}).fetch();

console.log(sortByJoined);
Meteor Sorting Joined

Meteor - 账户

此包允许完整的用户身份验证功能。您可以通过在命令提示符窗口中运行以下代码来添加它。

C:\Users\username\Desktop\meteorApp>meteor add accounts-password

身份验证示例

此示例将显示基本身份验证。我们将创建 **register**、**login** 和 **home** 模板。如果存在 **currentUser**(如果用户已成功注册或登录),则将显示 **home** 模板。如果没有 **currentUser**,则 **register** 和 **login** 模板将可见。

meteorApp.html

<head>
   <title>meteorApp</title>
</head>
 
<body>
   {{#if currentUser}}
      {{> home}}
      {{else}}
      {{> register}}
      {{> login}}
   {{/if}}
</body>

<template name = "register">
   <h2>REGISTER:</h2>
   <form>
      <input type = "email" name = "registerEmail"><br>
      <input type = "password" name = "registerPassword"><br>
      <input type = "submit" value = "Register"><br>
   </form>
</template>

<template name = "login">
   <h2>LOGIN:</h2>
   <form>
      <input type = "email" name = "loginEmail"><br>
      <input type = "password" name="loginPassword"><br>
      <input type = "submit" value = "Login"><br>
   </form>
</template>

<template name = "home">
   <p>You're logged in.</p>
   <button class = "logout">Logout</button>
</template>

首先,我们需要创建一个 **register** 事件。此函数将读取注册输入,创建一个新用户,并将其存储到数据库中。

第二个事件是 **login**。这次函数将读取 **login** 模板中的输入,如果电子邮件和密码有效,则登录用户;如果无效,则返回错误。

最后,**logout** 事件将在单击按钮后用于注销用户。

meteorApp.js

if (Meteor.isClient) {

   Template.register.events({
      'submit form': function(event) {
         event.preventDefault();

         var registerData = {
            email: event.target.registerEmail.value,
            password: event.target.registerPassword.value
         }

         Accounts.createUser(registerData, function(error) {
         
            if (Meteor.user()) {
               console.log(Meteor.userId());
            } else {
               console.log("ERROR: " + error.reason);
            }
         });
      }
   });

   Template.login.events({
   
      'submit form': function(event) {
         event.preventDefault();
         var myEmail = event.target.loginEmail.value;
         var myPassword = event.target.loginPassword.value;
			
         Meteor.loginWithPassword(myEmail, myPassword, function(error) {

            if (Meteor.user()) {
               console.log(Meteor.userId());
            } else {
               console.log("ERROR: " + error.reason);
            }
         });
      }
   });

   Template.home.events({

      'click .logout': function(event) {
         event.preventDefault();
			
         Meteor.logout(function(error) {

            if(error) {
               console.log("ERROR: " + error.reason);
            }
         });
      }
   });
}

应用程序启动后,我们将看到以下页面。

Meteor Accounts Start

在 **register** 表单中输入电子邮件和密码后,我们可以注册和登录新用户。我们将看到控制台记录用户的 **id** 并呈现 **home** 模板。

Meteor Accounts Register

**login** 事件将检查数据库并登录用户(如果电子邮件和密码正确)。如果不是,控制台将记录错误。

Meteor Accounts Login Error

如果用户单击 **LOGOUT** 按钮,应用程序将注销用户并显示 **register** 和 **login** 模板。

Meteor - 方法

Meteor 方法是在服务器端编写的函数,但可以从客户端调用。

在服务器端,我们将创建两个简单的函数。第一个函数将向我们的参数添加 5,而第二个函数将添加 **10**。

使用方法

meteorApp.js

	
if(Meteor.isServer) {

   Meteor.methods({

      method1: function (arg) {
         var result = arg + 5;
         return result;
      },

      method2: function (arg) {
         var result = arg + 10;
         return result;
      }
   });
}

if(Meteor.isClient) {
   var aaa = 'aaa'
   Meteor.call('method1', aaa, function (error, result) {
	
      if (error) {
         console.log(error);
         else {
            console.log('Method 1 result is: ' + result);
         }
      }
   );

   Meteor.call('method2', 5, function (error, result) {

      if (error) {
         console.log(error);
      } else {
         console.log('Method 2 result is: ' + result);
      }
   });
}

启动应用程序后,我们将在控制台中看到计算出的值。

Meteor Methods Log

处理错误

要处理错误,您可以使用 **Meteor.Error** 方法。以下示例显示了如何处理未登录用户的错误。

if(Meteor.isServer) {

   Meteor.methods({

      method1: function (param) {

         if (! this.userId) {
            throw new Meteor.Error("logged-out",
               "The user must be logged in to post a comment.");
         }
         return result;
      }
   });
}

if(Meteor.isClient) {  Meteor.call('method1', 1, function (error, result) {

   if (error && error.error === "logged-out") {
      console.log("errorMessage:", "Please log in to post a comment.");
   } else {
      console.log('Method 1 result is: ' + result);
   }});

}

控制台将显示我们自定义的错误消息。

Meteor Methods Error

Meteor - Package.js

在本章中,我们将学习如何创建我们自己的 Meteor 包。

创建包

让我们在桌面上添加一个新文件夹,将在其中创建包。我们将使用命令提示符窗口。

C:\Users\username\Desktop\meteorApp> mkdir packages

现在,我们可以在上面创建的文件夹中创建包。从命令提示符运行以下命令。**用户名** 是 Meteor 开发人员用户名,**包名称** 是包的名称。

C:\Users\username\Desktop\meteorApp\packages>meteor create --package username:package-name

添加包

为了能够将本地包添加到我们的应用程序,我们需要设置 **环境变量**,它将告诉 Meteor 从本地文件夹加载包。右键单击计算机图标,然后选择 **属性/高级系统设置/环境变量/新建**。

**变量名** 应为 **PACKAGE_DIRS**。**变量值** 应为我们创建的文件夹的路径。在本例中,为 **C:\Users\username\Desktop\meteorApp\packages**。

添加新的环境变量后,不要忘记重新启动 **命令提示符**。

现在,我们可以通过运行以下代码将包添加到我们的应用程序:

C:\Users\username\Desktop\meteorApp>meteor add username:package-name

包文件

在我们创建的包中将找到以下四个文件。

  • package-name-test.js
  • package-name.js
  • package.js
  • README.md

测试包 (package-name-test.js)

Meteor 提供了 **tinytest** 包用于测试。让我们首先使用命令提示符窗口中的以下命令安装它。

C:\Users\username\Desktop\meteorApp>meteor add tinytest

如果我们打开 **package-name-test.js**,我们将看到默认的测试示例。我们将使用此示例来测试应用程序。注意:在开发 Meteor 包时,最好编写自己的测试。

要测试包,让我们在命令提示符中运行此代码。

C:\Users\username\Desktop>meteor test-packages packages/package-name

我们将得到以下结果。

Meteor Package Test

package.js 文件

这是我们可以编写代码的文件。让我们为我们的包创建一些简单的功能。我们的包将在控制台中记录一些文本。

packages/package.js

myPackageFunction = function() {
   console.log('This is simple package...');
}

package-name.js 文件

这是我们可以设置一些包配置的文件。我们稍后会回到它,但现在我们需要导出 **myPackageFunction** 以便我们可以在我们的应用程序中使用它。我们需要在 **Package.onUse** 函数内添加它。该文件看起来像这样。

packages/package-name.js

Package.describe({
   name: 'username:package-name',
   version: '0.0.1',
   
   // Brief, one-line summary of the package.
   summary: '',
   
   // URL to the Git repository containing the source code for this package.
   git: '',
   
   // By default, Meteor will default to using README.md for documentation.
   
   // To avoid submitting documentation, set this field to null.
   documentation: 'README.md'
});

Package.onUse(function(api) {
   api.versionsFrom('1.2.1');
   api.use('ecmascript');
   api.addFiles('mypackage.js');
   api.export('myPackageFunction'); // We are exporting the function we created above...
});

Package.onTest(function(api) {
   api.use('ecmascript');
   api.use('tinytest');
   api.use('username:package-name');
   api.addFiles('package-name-tests.js');
});

使用包

现在我们终于可以从我们的 **meteorApp.js** 文件中调用 **myPackageFunction()** 了。

packages/package.js

if(Meteor.isClient) {
   myPackageFunction();
}

控制台将记录来自我们包的文本。

Meteor Package Log

为了更好地理解如何配置 **package.js** 文件,我们将使用 Meteor 官方文档中的示例。

这是一个示例文件……

/* Information about this package */
Package.describe({
   
   // Short two-sentence summary.
   summary: "What this does",

   // Version number.
   version: "1.0.0",

   // Optional.  Default is package directory name.
   name: "username:package-name",

   // Optional github URL to your source repository.
   git: "https://github.com/something/something.git",
});

/* This defines your actual package */
Package.onUse(function (api) {

   // If no version is specified for an 'api.use' dependency, use the
   // one defined in Meteor 0.9.0.
   api.versionsFrom('0.9.0');

   // Use Underscore package, but only on the server.
   // Version not specified, so it will be as of Meteor 0.9.0.
   api.use('underscore', 'server');

   // Use iron:router package, version 1.0.0 or newer.
   api.use('iron:[email protected]');

   // Give users of this package access to the Templating package.
   api.imply('templating')

   // Export the object 'Email' to packages or apps that use this package.
   api.export('Email', 'server');

   // Specify the source code for the package.
   api.addFiles('email.js', 'server');
});

/* This defines the tests for the package */
Package.onTest(function (api) {

   // Sets up a dependency on this package
   api.use('username:package-name');

   // Allows you to use the 'tinytest' framework
   api.use('[email protected]');

   // Specify the source code for the package tests
   api.addFiles('email_tests.js', 'server');
});

/* This lets you use npm packages in your package*/
Npm.depends({
   simplesmtp: "0.3.10",
   "stream-buffers": "0.2.5"
});

Meteor - 发布和订阅

正如在集合章节中已经讨论的那样,我们所有的数据都可以在客户端上使用。这是一个安全问题,可以使用发布和订阅方法来处理。

删除 Autopublish

在这个例子中,我们将使用 **PlayersCollection** 集合以及以下数据。我们之前准备了这个集合,以便能够专注于本章本身。如果您不确定如何在 Meteor 应用程序中创建 MongoDB 集合,请查看我们的 集合 章节。

Meteor Publish and Subscribe Database Data

为了保护我们的数据,我们需要删除允许我们在客户端使用数据的 **autopublish** 包。

C:\Users\username\Desktop\meteorApp>meteor remove autopublish

此步骤之后,我们将无法从客户端获取数据库数据。我们只能在命令提示符窗口的服务器端看到它。查看以下代码:

meteorApp.js

var PlayersCollection = new Mongo.Collection('playersCollection');
var myLog = PlayersCollection.find().fetch();
console.log(myLog);

**命令提示符** 窗口将显示包含四个对象的整个集合,而 **开发者控制台** 将显示一个空数组。现在我们的应用程序更安全了。

Meteor Publish and Subscribe Autopublish Removed

使用发布和订阅

假设我们想允许客户端使用我们的数据。为此,我们需要在服务器上创建 **Meteor.publish()** 方法。此方法将数据发送到客户端。

为了能够在客户端接收和使用该数据,我们将创建 **Meteor.subscribe()** 方法。在示例的末尾,我们正在搜索数据库。此代码在客户端和服务器端都运行。

var PlayersCollection = new Mongo.Collection('playersCollection');

if(Meteor.isServer) {

   Meteor.publish('allowedData', function() {
      return PlayersCollection.find();
   })
}

if (Meteor.isClient) {
   Meteor.subscribe('allowedData');
};

Meteor.setTimeout(function() {
   var myLog = PlayersCollection.find().fetch();
   console.log(myLog);
}, 1000);

我们可以看到我们的数据已记录在 **开发者控制台** 和 **命令提示符** 窗口中。

Meteor Publish and Subscribe Allowed All

过滤客户端数据

我们还可以发布部分数据。在这个例子中,我们正在发布名称为 **"John"** 的数据。

var PlayersCollection = new Mongo.Collection('playersCollection');

if(Meteor.isServer) {

   Meteor.publish('allowedData', function() {
      return PlayersCollection.find({name: "John"});
   })
}

if (Meteor.isClient) {
   Meteor.subscribe('allowedData');
};

Meteor.setTimeout(function() {
   myLog = PlayersCollection.find().fetch();
   console.log(myLog);
}, 1000);

运行此代码后,**命令提示符** 将记录所有数据,而客户端 **控制台** 将只记录两个名称为 **John** 的对象。

Meteor Publish and Subscribe Allowed All

Meteor - 结构

Meteor 提供了一些特殊的文件夹,可以帮助开发人员构建他们的应用程序。

client

如果您创建一个 **client** 文件夹,则此文件夹中的所有内容都将在客户端运行。这是您可以放置 **HTML、CSS** 和客户端 **JavaScript** 的文件夹。您应该在此文件夹中放置 **Meteor.subscribe** 函数、**模板、助手** 和 **事件**。请注意,您不需要在放在 **client** 文件夹中的文件中运行 **Meteor.isClient** 函数。

server

此文件夹中的文件将仅在 **服务器端** 运行。这是应该保存 **方法、Meteor.Publish()** 函数和其他敏感数据的地方。所有身份验证数据都应保存在此处。您不需要对此文件夹内的文件使用 **Meteor.isServer()**。

public

这是您应该放置图像、网站图标以及所有其他提供给客户端的数据的地方。

private

只能从服务器访问此文件夹中的文件。它们将对客户端隐藏。您可以将仅服务器使用的 **JSON** 或 **EJSON** 文件放在此文件夹中。

client/compatibility

一些 JavaScript 库将变量导出为全局变量。将需要在不包含在新变量作用域中执行的文件用于此文件夹。

其余部分

其余文件夹可以按照您想要的方式进行组织。放在上述文件夹之外的代码将在 **客户端** 和 **服务器端** 执行。这是一个您可以定义模型的好地方。

加载顺序

了解文件的加载顺序总是好的。以下列表取自 Meteor 官方文档。

  • HTML 模板文件始终在其他所有内容之前加载

  • 以 **main.** 开头的文件最后加载

  • 任何 **lib/** 目录中的文件接下来加载

  • 路径较深的文件接下来加载

  • 然后按整个路径的字母顺序加载文件

Meteor - 部署

Meteor 的一大优点是部署应用程序非常容易。应用程序完成后,有一种简单的方法可以与世界分享。您只需在命令提示符窗口中运行以下代码即可。

C:\Users\username\Desktop\meteorApp>meteor deploy my-first-app-ever.meteor.com

系统会要求您输入 Meteor 开发者帐户的用户名密码

现在,您可以通过以下链接访问浏览器中的应用程序,链接名称为您的应用程序名称。

http://my-first-app-ever.meteor.com/
Meteor Deploy

Meteor - 移动端运行

在本章中,我们将学习如何在 Android 设备上运行应用程序。Meteor 最近才为 Windows 操作系统添加了此功能,因此我们需要将我们的 Meteor 应用程序更新到 1.3 Beta 版本。

注意 - 在撰写本教程时,Meteor 的 1.3 版本处于 Beta 阶段。正式版发布后,我们会更新此内容。

由于我们想使用最新的 Meteor 版本,我们可以通过在命令提示符窗口中运行以下代码来更新它。

C:\Users\username\Desktop\meteorApp>meteor update --release 1.3-beta.11

步骤 1 - 安装 Android SDK

使用下表中的链接安装 Android SDK。

序号 软件及说明
1

Java 开发工具包和 Android SDK

您需要 Android SDK 才能在移动环境中运行 Meteor 应用程序。如果您尚未安装它,您可以查看我们的 Android 环境设置 教程。

步骤 2 - 添加 Android 平台

现在,我们需要向项目中添加一个 Android 平台。

C:\Users\username\Desktop\meteorApp>meteor add-platform android

步骤 3 - 在 Android 模拟器上运行应用程序

要在 Android 模拟器上运行应用程序,我们将在行尾使用–verbose命令,以便能够识别启动过程中的潜在错误。

C:\Users\username\Desktop\meteorApp>meteor run android --verbose

Meteor Mobile

在 Android 设备上运行应用程序

由于 Android 模拟器速度较慢,直接在您的设备上运行应用程序始终是更好的选择。您可以通过将设备连接到计算机,启用开发者模式和 USB 调试来实现。

此过程因特定设备而异。您需要在设置/关于中找到内部版本号,然后点击七次。您将收到一条通知,告知您是开发者,并且开发者选项将被解锁。

再次搜索您的设置并启用USB 调试

您可以在命令提示符中使用以下命令在移动设备上运行 Meteor 应用程序。

C:\Users\username\Desktop\meteorApp>meteor run android-device

Meteor - 待办事项应用

在本章中,我们将学习如何创建一个简单的待办事项应用程序。

步骤 1 - 创建应用程序

打开命令提示符并运行以下命令:

C:\Users\username\Desktop>meteor create todo-app

要查看应用程序,您需要使用meteor命令运行应用程序并访问https://127.0.0.1:3000

C:\Users\username\Desktop\todo-app>meteor

步骤 2 - 创建文件夹和文件

我们将重构默认的文件结构。让我们创建一个client文件夹,在其中创建todo-app.html、todo-app.csstodo-app.js

C:\Users\username\Desktop\todo-app>mkdir client
C:\Users\username\Desktop\todo-app\client>touch todo-app.html
C:\Users\username\Desktop\todo-app\client>touch todo-app.js

我们还将创建一个包含server.jsserver文件夹。

C:\Users\username\Desktop\todo-app>mkdir server
C:\Users\username\Desktop\todo-app\server>touch server.js

最后,让我们创建一个包含task-collection.js文件的collections文件夹。

C:\Users\username\Desktop\todo-app>mkdir server
C:\Users\username\Desktop\todo-app\collections>touch task-collection.js

您可以在下图中看到应用程序结构:

Meteor Todo App Structure

步骤 3 - client/todo-app.html

我们的第一步是为应用程序创建 HTML。我们需要一个输入字段,以便添加新的任务。任务将以列表的形式显示,并具有删除选中功能。我们还将具有显示或隐藏已完成任务的功能。

<head>
   <title>Todo App</title>
</head>

<body>
   <h1>Todo List ({{incompleteCount}})</h1>

   <label class = "hide-completed">
      <input type = "checkbox" checked = "{{hideCompleted}}" />
      Hide Completed Tasks
   </label>

   <form class = "new-task">
      <input type = "text" name = "text" placeholder = "Add new tasks" />
   </form>

   <ul>
      {{#each tasks}}
         {{> task}}
      {{/each}}
   </ul>
</body>

<template name = "task">
   <li class = "{{#if checked}}checked{{/if}}">
      <button class = "delete">x</button>
      <input type = "checkbox" checked = "{{checked}}" class = "toggle-checked" />
      <span>{{username}} - {{text}}</span>
   </li>
</template>

步骤 4 - collections/task-collection.js

在这里,我们将创建一个新的 MongoDB 集合,以便我们可以在服务器端和客户端使用它。

Tasks = new Mongo.Collection("tasks");

步骤 5 - server/server.js

我们将在服务器端定义应用程序的方法。这些方法将从客户端调用。在这个文件中,我们还将发布数据库查询。

// Publishing tasks from the server...

Meteor.publish("tasks", function () {
   return Tasks.find({});
});

// Methods for handling MongoDb Tasks collection data...

Meteor.methods({

   addTask: function (text) {

      Tasks.insert({
         text: text,
         createdAt: new Date(),
      });
   },

   deleteTask: function (taskId) {
      var task = Tasks.findOne(taskId);
      Tasks.remove(taskId);
   },

   setChecked: function (taskId, setChecked) {
      var task = Tasks.findOne(taskId);
      Tasks.update(taskId, { $set: { checked: setChecked} });
   }
});

步骤 6 - client/todo-app.js

这是主要的客户端 JavaScript 文件。此文件也可以重构,但我们将在此处编写所有客户端代码。首先,我们订阅在服务器上发布的task集合。然后,我们创建helpers来处理应用程序逻辑,最后,我们定义将调用服务器方法的events

// Subscribing to the published tasks
Meteor.subscribe("tasks");

// Show/Hide functionality
Template.body.helpers({

   tasks: function () {

      if (Session.get("hideCompleted")) {

         // If hide completed is checked, filter tasks
         return Tasks.find({checked: {$ne: true}}, {sort: {createdAt: -1}});
      } else {
         
         // Otherwise, return all of the tasks
         return Tasks.find({}, {sort: {createdAt: -1}});
      }
   },

   hideCompleted: function () {
      return Session.get("hideCompleted");
   },

   incompleteCount: function () {
      return Tasks.find({checked: {$ne: true}}).count();
   }
});

// Events for creating new tasks and Show/Hide functionality.
// Calling methods from the server

Template.body.events({

   "submit .new-task": function (event) {
      event.preventDefault();
      var text = event.target.text.value;

      Meteor.call("addTask", text);
      event.target.text.value = "";
   },

   "change .hide-completed input": function (event) {
      Session.set("hideCompleted", event.target.checked);
   }
});

// Events for Deleting and Check/Uncheck functionality
Template.task.events({
   
   "click .toggle-checked": function () {

      // Set the checked property to the opposite of its current value
      Meteor.call("setChecked", this._id, ! this.checked);
   },

   "click .delete": function () {
      Meteor.call("deleteTask", this._id);
   }
});

步骤 7 - 部署

完成开发后,我们可以从命令提示符窗口部署应用程序。我们的应用程序的部署名称将为my-first-todo-app

C:\Users\username\Desktop\todo-app>meteor deploy my-first-todo-app

我们可以打开http://my-first-todo-app.meteor.com/来开始使用我们的应用程序。

Meteor Todo App Deploy

Meteor - 最佳实践

我们已经在前面的章节中介绍了一些 Meteor 开发的最佳实践。以下是在使用 Meteor 时需要注意的一些最佳实践。

目录结构

Meteor 应用程序的目录结构没有严格的规则。有关指南的更多信息,请查看 Meteor - 结构章节。

使用方法

在处理敏感数据时,应始终使用 Meteor - 方法,而不是直接从客户端调用insert、updateremove

数据管理

使用 发布和订阅 方法来保护您的数据。如果您希望您的数据对所有客户端可用,则可以使用null作为发布名称。发布少量数据也将提高应用程序的性能。

验证数据

您应该验证将存储在集合中的所有数据。最佳选择之一是 collection2 包。此包简化了服务器端和客户端验证的设置。

最小化 Session

session变量是全局变量,使用全局变量违反了 JavaScript 的最佳实践。

路由器

Meteor 路由有两个最流行的选项。对于较小的应用程序,可以使用 Iron Router。它会在数据更改后自动重新运行。对于较大的应用程序,可以使用 Flow Router。此路由器让您可以更自由地优化模板的重新渲染,代价是需要编写少量样板代码。

在选择在应用程序中使用包之前,始终检查该包是否定期更新。

广告