Board logo

标题: 使用 Meteor 快速开发 Web 应用程序(2)深入剖析 Sales Portal 代码 [打印本页]

作者: look_w    时间: 2018-10-18 20:41     标题: 使用 Meteor 快速开发 Web 应用程序(2)深入剖析 Sales Portal 代码

深入剖析 Sales Portal 代码清单 1 显示了 sales.js 文件,它包含 Sales Portal 应用程序背后的所有服务器端和客户端逻辑。这是我需要为此应用程序编写的惟一的 JavaScript 代码。(可在代码 的 sales_nologin 目录中找到 sales.js。)
清单 1. Sales Portal 的客户端和服务器端逻辑:sales.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Sales2013 = new Meteor.Collection("regional_sales");

if (Meteor.is_client) {
Template.salesdata.dataset = function () {
   return Sales2013.find({});
};

Template.datapoint.selected = function () {
   return Session.equals("selected_datapoint", this._id) ? "selected" : '';
};

Template.datapoint.events = {
   'click': function () {
     Session.set("selected_datapoint", this._id);

   }
};

Template.salesdata.rendered = function()
{

$('.editable').editable(function(value, settings) {
    Sales2013.update(Session.get("selected_datapoint"),
{$set: {total: parseInt(value)}});
    return(value);
}, {
    type    : 'text',
    style : 'inherit',
    width : 100,
    submit  : 'OK',
});

    var cur = Sales2013.find();
    if (cur.count() === 0)  // do not render pie if no data
      return;
    var data = [];
    cur.forEach( function(sale) {
      data.push( [sale.region, sale.total]);
    });
var plot1 = $.jqplot ('chart', [data],
   {
     seriesDefaults: {
// Make this a pie chart.
renderer: $.jqplot.PieRenderer,
rendererOptions: {
  // Put data labels on the pie slices.
  // By default, labels show the percentage of the slice.
  showDataLabels: true
}
     },
     legend: { show:true, location: 'e' }
   }
);
}

}

if (Meteor.is_server) {
Meteor.startup(function () {
     Sales2013.remove({});
     Sales2013.insert({region:"US East", total: 2032333});
     Sales2013.insert({region:"US Central", total: 150332});
     Sales2013.insert({region:"US West", total: 1202412});
     Sales2013.insert({region:"Asia Pacific", total: 701223});
});
}




观察   中围绕 Meteor.is_client 和 Meteor.is_server 变量的条件。这些是 Meteor 核心提供的运行时上下文指标,可用在您代码中的任何地方。在本例中,它们支持将客户端和服务器端代码组合到同一个 source.js 文件中。条件外部的任何代码都同时在客户端和服务器上运行。
您也可以将客户端和服务器源代码完全分开,将客户端代码放在一个名为 client 的子目录中,将服务器端代码放在一个名为 server 的子目录中。在这种情况下,可将客户端和服务器都需要的共有内容放在一个名为 public 的子目录中。Sales Portal 应用程序的一个更加安全的版本(您在本文后面将会看到)使用了这种目录结构。
识别反应性数据另一个反应性数据源 中的 selected_datapoint 会话变量也是反应性的。(请参见   边栏,了解默认情况下属于反应性元素的更多信息。)在本例中,它用于更改销量数据的行突出显示形式。行突出显示通过更改动态的 CSS 样式来执行。selected_datapoint 会话变量会在用户单击一行时更新。因为 Meteor 会在这个变量每次更改时重新呈现依赖关系,所以突出显示形式会相应地进行更新。

Sales Portal 应用程序的一个反应性数据源是对 Sales2013 Meteor 集合的一次查询。可在   中的这个客户端代码段中看到它的用法:
Template.salesdata.dataset = function () {
    return Sales2013.find({});
};
因为该查询是反应性的,所以它的所有依赖关系都会在查询结果集更改时重新计算或重新呈现。这是在所有浏览器实例中更新销量数据和饼图的方式。清单 2 给出了相关的 HTML 模板代码,可在代码 的 sales_nologin 目录中的 sales.html 文件中找到:
清单 2. 客户端 HTML 和模板:sales.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<head>

<title>Sales by Region</title>
</head>

<body>
<div id="title">
   <h1>Global Sales 2013</h1>
</div>
<div id="container">

   <div id="salestable">
     {{> salesdata}}
   </div>
   <div id="chart">
   </div>
</div>

</body>



<template name="salesdata">
<div class="salesdata">
   {{#each dataset}}
     {{> datapoint}}
   {{/each}}
</div>
</template>


<template name="datapoint">
<div class="datapoint {{selected}}">
   <span class="region">{{region}}</span>
   <span class="sales editable">{{total}}</span>
</div>
</template>




中的 HTML 文件是一个 Handlebars 模板,Meteor 目前支持该模板。在 {{ }} 中可以看到 Handlebars 表达式。通过它的 Spark 引擎(将在本文的   一节中描述),Meteor 可处理其他 JavaScript 模板组件。
销售数据行通过 salesdata 模板代码呈现,这些代码已在   中以粗体形式显示。此模板依赖于 dataset 帮助函数(如   中所示),所以在每次查询发生更改时都会重新呈现。
在服务器上提供抽样数据 Sales Portal 的最初的地区销量数据由清单 3 中所示的服务器端代码(来自   )提供:
清单 3. 提供 MongoDB 中的数据的服务器端代码
1
2
3
4
5
6
7
8
9
if (Meteor.is_server) {
Meteor.startup(function () {
     Sales2013.remove({});
     Sales2013.insert({region:"US East", total: 2032333});
     Sales2013.insert({region:"US Central", total: 150332});
     Sales2013.insert({region:"US West", total: 1202412});
     Sales2013.insert({region:"Asia Pacific", total: 701223});
});
}




Meteor 的延迟补偿Meteor 有一个称为 延迟补偿(latency compensation)的特性。从根本上讲,延迟补偿是大数据管理领域中的 最终一致性概念的一种视觉表现。当通过 Minimongo  stub 更新客户端上的数据时,任何更改都会立即在客户端上反映出来,包括反应性重新呈现。这些更改还会被传播到服务器。但是,传播的更改可能会失败,失败的原因有很多,包括拒绝访问。发布 - 订阅机制负责确保客户端最终(通常很快)反映了服务器的实际状态。延迟补偿可实现一种无需等待的、响应非常迅速的 UI,这是现代 Web 2.0 应用程序的一个鲜明特征。而代价可能是出现短暂的视觉数据不一致性。

在 Meteor 服务器上,运行着一个完整的 MongoDB 实例。这个完整实例可接受来自 Meteor 以外的客户端的查询和更新。
在 Meteor 客户端上,可以使用相同的 JavaScript MongoDB API。这统一了客户端和服务器编码,实现了客户端和服务器上的代码重用。客户端 API 由一个称为 Minimongo 的智能 stub 提供。Minimongo 使用 来反映数据库更改。因为 Minimongo 通常处理小型的客户端数据集,所以它不支持索引。
使用一种发布 - 订阅模型来控制 MongoDB 服务器与 Minimongo 客户端之间同步的数据。默认情况下,所有服务器端 Meteor 集合都会被发布。Meteor 使用 DDP(Distributed Data Protocol,分布式数据协议)在客户端与服务器之间移动数据。(可为其他数据库创建 stub 并提供程序形式的 DDP 驱动程序;Meteor 社区的持续工作包括一个即将推出的 MySQL 驱动程序。)
集成 jQuery 插件 Sales Portal 使用 jqPlot jQuery 插件呈现饼图。饼图的呈现和重新呈现是反应性的,由 Sales2013 集合中的数据更改推动。您之前已经看到,每次 Sales2013 集合更改时,都会重新呈现 salesdata 模板。清单 4 显示了在 salesdata 模板的 rendered 事件触发时,重新绘制饼图的客户端函数(来自   ):
清单 4. 使用 jqPlot 插件呈现饼图的 jQuery 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Template.salesdata.rendered= function()
{

  $('.editable').editable(function(value, settings) {
     Sales2013.update(Session.get("selected_datapoint"),
{$set: {total: parseInt(value)}});
     return(value);
  }, {
     type    : 'text',
     style : 'inherit',
     width : 100,
     submit  : 'OK',
});

  
     var cur = Sales2013.find();

     if (cur.count() === 0)  // do not render pie if no data
       return;
     var data = [];
     cur.forEach( function(sale) {
       data.push( [sale.region, sale.total]);
     });
  var plot1 = $.jqplot ('chart', [data],
    {
      seriesDefaults: {
// Make this a pie chart.
renderer: $.jqplot.PieRenderer,
rendererOptions: {
   // Put data labels on the pie slices.
   // By default, labels show the percentage of the slice.
   showDataLabels: true
}
      },
      legend: { show:true, location: 'e' }
    }
  );
  
}




Sales Portal 使用 Jeditable jQuery 插件实现销量数据的就地编辑 (in-place editing)。处理编辑的代码位于   中的 Template.salesdata.rendered = function() 和 var cur = Sales2013.find(); 行之间。
请参见 ,获取 jQuery、jqPlot 和 Jeditable 插件的更多信息。
理解 Meteor 的电子表格和脚本加载顺序要成功加载 jQuery 插件,按照正确的顺序加载与它们有关联的 CSS 文件和 JavaScript 代码至关重要。
请注意,在   中,sales.html 文件不包含任何 <script> 标记或 <link type="text/css" ... > 样式表。相反,Meteor 通过扫描目录来自动加载客户端脚本和样式表:从最深的目录开始,然后在每个目录中按字母顺序依次扫描。
为了利用这个加载顺序(和脚本或 CSS 文件的名称无关紧要的事实),我重新命名了一些脚本,以确保它们的加载位置不变。例如,jquery.jeditable.mini.js 重命名为 client/js 目录下的 zjquery.jeditable.mini.js,以确保它最后被加载。我还将 jqplot.pieRenderer.min.js 重命名为 yjqplot.pieRenderer.min.js,以确保它在 jquery.jqplot.min.js 之后加载。我将来自插件的 CSS 文件放在 client/css 子目录中,确保它们首先被加载。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0