Meteor全栈开发平台

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ 。网站上有对应每一小节的在线练习大家可以去试试。

全栈开发平台 - 不仅仅是前端

Meteor和那些名声如雷贯耳的前端框架,比如Angular, React等都不一样,它是一个 采用单一开发语言的全栈开发的平台:开发者可以使用JavaScript同时 进行前端后端的开发,然后交给Meteor运行这个包含了前后端的完整应用:

从图中你可以看到,Meteo在前端使用浏览器作为基础运行环境,在后端则是以NodeJS作为 基础运行环境,以MongoDB作为数据持久化系统。

Meteor提供了一个横跨前端和后端的中间层平台,预置封装了很多功能库,简化了 Web应用的开发:使用单一语言快速开发Web应用,这是Meteor的最重要诉求。

初识Meteor

从构成来讲,可以认为Meteor开发平台由两部分构成:

  • Meteor库 - 以功能包的形式存在,封装了诸如实时通信、反应式编程之类的核心功能。当 一个Meteor应用启动时,Meteor会自动加载这些库,为应用提供了一个基础环境。

  • Meteor工具 - 可以理解为命令行方式的开发环境,它使我们可以轻松地管理整个应用 开发流程:从创建应用、调试应用、自动化测试到打包、部署、热升级。

现在,让我们让我们使用Meteor命令行工具meteor创建并启动第一个Meteor应用吧。

≡ 创建应用 —— meteor create [project]

在终端中输入meteor create test,然后按回车:

~$ meteor create test↵

这个命令将在当前目录下创建一个子文件夹test,Meteor将使用内置的应用模板 作为这个文件夹的内容。我们可以进入test文件夹,执行ls命令查看一下内容:

~$ cd test↵
~/test$ ls -al↵

你可以看到Meteor创建了3个文件和1个目录。

  • test.css - 前端的样式表文件
  • test.html -前端的HTML文件
  • test.js - 前端/后端共用的JavaScript文件。全栈,对吧O(∩_∩)O~
  • .meteor - 这个子目录是Meteor应用必须的特殊子目录,由Meteor平台维护,我们不要动

先略过3个文件的具体内容,我们运行起来看看。

≡ 运行应用 —— meteor run

执行meteor命令启动应用,在终端中输入meteor,这等价于运行meteor run:

~/test$ meteor↵

当你看到终端中出现下面的提示信息:

...
App running at: http://localhost:3000/

恭喜!我们的第一个Meteor应用已经运行起来了!

≡ 停止应用运行 —— Ctrl+C

用鼠标左键点击一下终端区域,确保它获得键盘输入焦点(你应该可以看到一个 闪烁的光标),然后同时按Ctrl键和C键,即可停止应用运行:

^C
~/test$

≡ 复位应用数据 —— meteor reset

Meteor应用运行时会生成打包文件、创建应用数据库。可以使用下面命令 清理这些生成的文件和应用数据:

~/test$ meteor rest↵

meteor reset命令不影响你的源代码文件。

模板文件 - test.html

打开test.html,你可能会略有不适:

它不是一个标准的HTML文件:没有html顶层标签,奇怪的符号{{> hello}}... 不过,在Metoer中这样的文件却是合法的文件 —— 模板文件。

≡ 模板顶层标签 —— head/body/template

Meteor规定,在一个模板文件里,只能出现三种顶层标签:head、body和template。 也就是说,模板文件只能包含以这三种标签为顶层标签的HTML片段。

这是因为,Meteor在运行应用之前有一个打包/bundle的过程,此时Meteor会提取所有 模板文件(一个应用中可以有多个模板文件)中的head、body和template片段,分别进行 合并、编译后才呈现给用户:

上图中,a.html和b.html中的head片段合并后作为最终的head内容,b.html和c.html中 的body片段合并后作为最终的body内容,至于c.html中的template的内容,则最终替换了 b.html中的{{> hello}}。

≡ 模板语言 —— Spacebars

Meteor的模板使用的语言是私有的spacebars语言,它基于流行的handlebars,通过 在HTML片段中嵌入模板标签(以两对大括号为边界)实现模板化。因此,Meteor的模板 其实就是HTML标签和模板标签的混合体。

{{> hello}}模板标签用来调用一个子模板,Meteor将在最终呈现给用户的HTML文档中, 使用子模板hello的内容进行原地替换。

特殊的template标签用来定义一个子模板。

{{counter}}模板标签执行插值工作,Meteror将在最终呈现给用户的HTML文档中,使用 标识符counter对应的值进行原地替换。

样式文件 - test.css

和模板文件类似,Meteor在打包过程中,会将所有的样式文件合并成一个大的样式文件, 然后在呈现给用户的HTML文档中引用这个样式文件:

上图中,a.css和b.css的内容将被合并为一个文件,并在最终呈现给用户的HTML文档中, 使用link标签引用这个文件。

代码文件 - test.js

test.js是最有趣的文件,Meteor将在前端和后端同时运行这个文件。可以这样理解:

  • 前端 - Meteor将在最终呈现给用户的HTML文档中使用script标签引用test.js
  • 后端 - Meteor将通过NodeJS读入并运行test.js

毫无疑问,如果不做任何处理,谁也没法保证一段JS代码既可以在前端浏览器环境中运行, 也可以在后端NodeJS中运行。在test.js中,我们需要判断当前的具体运行环境,以便 执行相应的代码。

≡ 判断代码执行环境 —— Meteor.isClient/Meteor.isServer

让同一个js文件即可以跑在前端,也可以跑在后端(比如NodeJS),已经有很多 应用了,只需要判断下在某个特定环境才存在的变量就可以了(比如,NodeJS有global,而 浏览器有window)。Meteor提供了一组更加清晰的API来实现这个判断:

  • Meteor.isClient - 为真时,表示当前运行环境为前端
  • Meteor.isServer - 为真时,表示当前运行环境为后端

你可以看到,在test.js中也是这么做的:

//test.js
if(Meteor.isClient){
//仅在前端执行的代码块
}
if(Meteor.isServer){
//仅在后端执行的代码块
}

≡ 前后端都执行的代码

很显然,如果在test.js中,不判断执行环境的代码将同时在前端和后端运行。比如:

//test.js
console.log("Hello,Meteor!");
if(Meteor.isClient){...}
if(Meteor.isServer){...}

运行应用后,你将在后台的终端中看到Hello,Meteor!,也将在前台的调试台 中看到相同的输出。

前端代码 - 模板实例对象

回忆下,在模板文件test.html中,我们定义了一个模板:

<!--test.html-->
<template name="hello">
<button>Click Me</button>
<p>You've pressed the button {{counter}} times.</p>
</template>

当Meteor运行这个应用时,将自动创建一个对应的模板实例对象:Template.hello。 对模板的数据绑定和事件绑定,这些通常需要使用JavaScript实现的功能,就通过这 个对象来实现:

在hello模板中,{{counter}}模板标签中的标识符couter的值,将由对应模板实例 对象的counter函数返回值决定,这个函数被称为模板的helper函数,使用模板实例的 helpers()方法声明模板标签中标识符对应的helper函数。

而通过模板实例对象的events方法,则为模板中的button元素挂接了click事件监听处理 函数。

前端代码 - 模板标签标识符解析/helper

使用Template.hello.helpers(helpers)方法声明hello模板中模板标签标识符的解析函数。参数helpers是一个JS对象,属性表示应用在模板标签中的标识符,值 通常是一个函数,被称为helper,大致是帮助Meteor解析模板中的标识符的值 这样的意思。

比如,在test.js中我们为hello模板中出现在{{counter}}模板标签中的counter表达 式声明其对应的helper函数:

//test.js
Template.hello.helpers({
'counter':function(){
return Session.get('counter');
}
});

每次当Meteor需要对模板标签{{counter}}进行计算时,都将调用其counter标识符 对应的helper函数进行计算:它简单地返回Session变量counter的当前值。

≡ 为helper函数设定参数

helper函数可以接受参数,比如对于模板test中的displayName标识符:

<template name="test">
<h1>Hello,{{displayName "Jason" "Mr."}}!</h1>
</template>

声明如下的helper函数:

Template.test.helpers({
'displayName' : function(name,title){
return title + ' ' + name;
}
});

那么Meteor渲染后将获得如下的HTML结果:

<h1>Hello,Mr. Jason!</h1>

≡ 使用常量helper

当然,也可以将helper定义为一个常量:

Template.test.helpers({
displayName : "Mr. WHOAMI"
})

这时,模板标签{{displayName}}将永远地被设定为固定的值了。

后端代码

在test.js中,后端代码几乎是空的,除了使用Meteor.startup(func)声明 了一个空的初始化函数。

Meteor.startup(func)方法在前端和后端都是可用的。参数func指定了 一个初始化函数,当平台就绪时,将调用这个初始化函数。

当在前端调用这个函数时,平台的就绪意味着DOM已经就绪,这时你可以进行DOM操作了:

//client side
Meteor.startup(function(){
//jQuery对象在Meteor前端总是可用的
$("<h1>Hello,world</h1>").appendTo("body");
});

当在后端调用这个函数时,平台的就绪意味着Meteor平台的服务进程已经正常启动,可以 进行应用层级的初始化工作了,比如,为空的后端数据集填充一些数据:

//server side
Meteor.startup(function(){
var persons = new Mongo.Collection("persons");
if(persons.find().count() === 0){
persons.insert({...});
}
});

应用目录结构

一个Meteor应用由目录下的前端文件(HTML、CSS、脚本、资源文件等)和后端文件组成。 由于Meteor存在一个打包/bundle的阶段,因此,Meteor对应用的目录结构进行了约定, 以便其打包过程能够顺利完成。

默认情况下,Meteor会搜索应用目录(包括子目录)中的所有JavaScript文件,打包后分别 送往前端和后端运行,文件和子目录的名称会影响打包结果。Meteor对以下的子目录将特别处理:

≡ client —— 参与打包的前端代码文件夹

任何名称为client的目录,其文件都不会被送往后端运行。这类似于使用if(Meter.isClient){...} 进行前端代码隔离的效果。

在生产模式下,client目录里的文件将被自动合并、压缩,但在开发模式下,JavaScript 文件和CSS文件并不进行压缩处理(CSS还是会合并,但JavaScript文件不进行合并处理),以便于 开发过程中的调试和错误定位。

Meteor会搜索目录中所有的模板文件中的三个顶层元素:head, body, template,其中所有 的head段会合并,body段和template段的声明都将转换为模板操作的JavaScript代码。

≡ server —— 参与打包的后端代码文件夹

任何名称为server的目录,其文件都不会送往前端运行。这类似于使用if(Meteor.isServer){...} 进行后端代码隔离的效果,但不同的是,server目录内的部分代码不会发送到前端,因此一些敏感的 代码(比如身份验证等)应当放在这个目录。

Meteor会收集除了client, public和private子目录之外的所有JS文件,然后交给后端NodeJS 运行。后端的JavaScript代码对每个请求将使用一个单独的线程来处理,这不同于通常NodeJS的异步 代码模式,因为Meter认为这种模式更适合Meteor应用场景。

≡ public —— 不参与打包的前端资源文件夹

应用根目录下public子目录中的文件仅用于前端,这些文件不会被打包,可视为http访问的虚拟根目录。 例如,public目录下的logo.jpg文件,可以通过url:"/log.jpg"来访问。这个目录可以用来放置favicon.ico, robots.txt,或者一些静态的HTM文件。

≡ client/compatibility —— 不参与打包的前端兼容库目录

有些前端JavaScript库依赖于使用var定义的全局变量。为了兼容这些库,这个目录里的文件在被送 往前端时,不会被嵌套在一个作用域中,并且会在其他前端JavaScript文件之前先执行。

≡ tests —— 仅用于测试的文件夹

任何名为test的目录内的文件仅用于测试,前端和后端都不会使用。

内容小结

让我们简单回顾这个示例Meteor应用的开发过程(假装没有使用meteor工具):

  1. 创建模板文件test.html,定义文档结构
  2. 创建样式文件test.css,定义文档样式
  3. 编写前端脚本test.js,实现模板、数据、事件的绑定
  4. 在这个示例中,我们基本不需要编写后端脚本

这些就绪后,扔给Meteor运行就可以了。

这有点像Apache+PHP或者IIS+ASP这些东西,Meteor提供一个基本的运行环境,你往 里面扔一个模板,立马就可以看到效果,你编写一段后端脚本,立马增强了服务器的 能力。那么,Meteor和它们的区别在哪里呢?

≡ 横跨前后端的中间层平台

在前面的课程中,我们看到,前端和后端同时都有一个Meteor对象作为API入口(当然, 前端的Meteor对象和后端的Meteor对象不是完全相同的实现),可以使用Meteor.isClient或 Meteor.isServer判断代码运行环境,可以使用同样的Meteor.startup()方法分别在 前端和后端注入初始化代码。这意味着什么?

让我把最开始的那张示意图中的Meteor层再细化一下:

很显然,Meteor最与众不同的是,使用同一套代码,同时在前端和后端提供了应用运行的 基础环境。不得不提的是,Meteor平台在前端基础环境和后端基础环境之间,甚至已经基于 websocket建立了一个双向实时的通道!

Meteor全栈开发平台的更多相关文章

  1. Meteor全栈开发平台 - 不仅仅是前端

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .网站上有对应每一 ...

  2. Python全栈开发【模块】

    Python全栈开发[模块] 本节内容: 模块介绍 time random os sys json & picle shelve XML hashlib ConfigParser loggin ...

  3. 诚聘:全栈开发人员,三线城市10-16K

    北京快鸽联盟信息技术有限公司成立于2013年,专注于校园及社区快递和增值服务.目前已有十余家各地分部,并与上百所大学,各大快递和电商公司有密切合作,年处理快件量超千万,长期处于行业领先地位. 诚聘全栈 ...

  4. python 全栈开发之路 day1

    python 全栈开发之路 day1   本节内容 计算机发展介绍 计算机硬件组成 计算机基本原理 计算机 计算机(computer)俗称电脑,是一种用于高速计算的电子计算机器,可以进行数值计算,又可 ...

  5. spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发

     前言 Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Electron通过将Chromium和Node.js合并到同一个运行时环 ...

  6. Win10构建Python全栈开发环境With WSL

    目录 Win10构建Python全栈开发环境With WSL 启动WSL 总结 对<Dev on Windows with WSL>的补充 Win10构建Python全栈开发环境With ...

  7. python全栈开发中级班全程笔记(第二模块、第四章)(常用模块导入)

    python全栈开发笔记第二模块 第四章 :常用模块(第二部分)     一.os 模块的 详解 1.os.getcwd()    :得到当前工作目录,即当前python解释器所在目录路径 impor ...

  8. 学习笔记之Python全栈开发/人工智能公开课_腾讯课堂

    Python全栈开发/人工智能公开课_腾讯课堂 https://ke.qq.com/course/190378 https://github.com/haoran119/ke.qq.com.pytho ...

  9. 一文读懂NodeJS全栈开发利器:CabloyJS(万字长文)

    目录 0 修订 0.1 修订说明 0.2 修订历史 1 基本概念 1.1 CabloyJS是什么 1.2 CabloyJS核心解决什么问题 1.3 CabloyJS的开发历程 2 数据版本与开发流程 ...

随机推荐

  1. poj1364(差分约束系统)

    poj1364 设s[i] 表示a1 + a2 + ... + a(i-1)的和 给我们n个点,m条约束 如果是a b gt c    那么表示 s[a+b+1] - s[a] > c     ...

  2. 苹果公司的新的编程语言 Swift 高级语言(十一)--初始化类的析构函数的一个实例

    一 .实例的初始化          实例的初始化是准备一个类.结构或枚举的实例以便使用的过程. 初始化包含设置一个实例的每个存储属性为一个初始值,以及运行不论什么其他新的实例可以使用之前须要的设置或 ...

  3. 【原创】poj ----- 2376 Cleaning Shifts 解题报告

    题目地址: http://poj.org/problem?id=2376 题目内容: Cleaning Shifts Time Limit: 1000MS   Memory Limit: 65536K ...

  4. JavaScript 常见陷阱

    JavaScript中的一些特性和通常我们想象的不太一样.这里我总结了一些有悖直觉的语言特性. 1 数组 1.1 数组的遍历 在直接支持for a in b的语言中,比方Python/Ruby里的a的 ...

  5. Solr入门指南

    本文转自http://chuanliang2007.spaces.live.com/blog/cns!E5B7AB2851A4C9D2!499.entry?wa=wsignin1.0 因为搜索引擎功能 ...

  6. jsp简单练习-简单的下拉表单

    <%@ page contentType="text/html; charset=gb2312" %> <html> <body> <fo ...

  7. java.io.FileNotFoundException: /home/hadoop/hadoop/dfs/namenode/current/VERSION (Permission denied)

    今天布置hadoop集群,尝试单独将secondarynamenode分属到一台独立的虚拟机上, 当格式化后,start-dfs.sh.namenode没启动.查看日志.报错例如以下 查看权限才发现, ...

  8. Recall(检出率)和 Precision(准确性)

    这两个方面是模式识别和信息检索使用措施值. 浅显易懂的理解,用以下的图片和公式最好只是. 那么 - 召回率R:用检索到相关文档数作为分子.全部相关文档总数作为分母.即R = A / ( A + C ) ...

  9. Android - 设置ImageView为全屏显示

    设置ImageView为全屏显示 本文地址: http://blog.csdn.net/caroline_wendy ImageView默认会适应屏幕大小, 假设想使用全屏填充, 则须要使用: and ...

  10. HTML5实际和离线应用分析

    当前离线Web申请书,即,该装置不能访问因特网时的应用的执行.HTML5离线应用重点,主要开发人员希望.步骤离线应用开发有:首先我们应该知道设备是否可以连接;然后,它也应该可以访问某些资源(像.CSS ...