你的分享就是我们的动力 ---﹥

学习如何创建由 jQuery Mobile 驱动的移动 web 应用程序(2)

时间:2011-06-28 09:57来源:www.chengxuyuans.com 点击:

应用程序架构

本节探索本教程的样例应用程序的架构,逐步演示构建过程的每个主要步骤。您可以逐步跟随本教程的操作,自己重建应用程序;或者,您也可以从 参考资料 下载完整的项目。

这个应用程序 — 简单地命名为 jQuery tutorial — 跨两个主要平台实现:

  • 移动代码,利用 JQM
  • 服务器端代码,在一个 MySQL 数据库中提供数据持久性

所有服务器端交互通过一些 PHP 文件完成,数据在一个 MySQL 数据库中的一个名为 opportunities 的表中进行管理。

数据库结构非常简单,只有 4 个字段(参见 表 2)。

 

列名 注释
opp_id 一个条目的数值标识符,这个标识符通过数据库自动递增。
opp_person 潜在客户的姓名或名称。
opp_contact 潜在客户的联系信息。
opp_description 简短的商机说明。

图 5 展示了 phpMyAdmin 中的文件的结构。列标题包括 Field、Type、Collation、Attributes、Null、Default、Extra、Action。(查看图 5 的 大图。)


数据库表结构的屏幕截图

您可以看到简单的结构和数据库类型。大部分条目是默认值。在一个生产应用程序中,您可能需要仔细考虑您的数据词典。

要启动应用程序,我使用 phpMyAdmin 的插入特性向数据库插入一些数据。图 6 显示了与本教程中显示的设备屏幕图像相关的数据的屏幕快照。列标题包括 opp_id、opp_person、opp_contact、opp_description。(查看图 6 的 大图。)


一些初始数据记录的屏幕截图

测试应用程序时,跳转到直接浏览下表是一个有用的健康检查。表 3 显示了应用程序使用的源文件清单。

文件 注释
header.php 包括 HTML 文档的头部分,包含必要的脚本标记来包含 JQM 文件。这个文件的内容在前面的 清单 1 中已显示。
footer.php 包括任何 HTML 页脚信息。对于许多应用程序而言,这个信息包含 Google Analytics JavaScript glue 以帮助收集关于应用程序的统计数据。
index.php 应用程序用户界面的主页,充当部件控制器、来自一个类 MVC 范式的部件视图、或一个松散配置的 MVC 设计中的控制器的部件。
utils.php 这个文件用于放置所有数据访问例程。
db.php 这个文件用于存储数据库凭证。
utils.js 这个文件用于存储几个表单级验证脚本。

了解这些文件如何协同工作的最好方法是逐步检查每个文件,这是我们下面将介绍的内容。


大多数应用程序的关键是创建正确的数据模型。如上节所述,这个应用程序的数据模型非常直观。在代码详解中,可以从 清单 5 中的数据库定义开始。

					
CREATE TABLE IF NOT EXISTS `opportunities` (
  `opp_id` int(11) NOT NULL AUTO_INCREMENT,
  `opp_person` varchar(100) NOT NULL,
  `opp_contact` varchar(50) NOT NULL,
  `opp_description` varchar(500) NOT NULL,
  UNIQUE KEY `opp_id` (`opp_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=25 ;

如果您想通过包含额外的字段来修改应用程序,可以通过两种方法将它们添加到数据库:一是通过 phpMyAdmin 这样的工具手动添加,如前面的 图 5 所示;二是通过扩展 SQL 脚本。数据库表就绪后,下一步是连接到数据库。可以通过一些 mysql 函数连接到数据库,如 清单 6 中的 db.php 所示。

 

					
<?
$mysql_db = "databasename";
$mysql_user = "username";
$mysql_pass = "password";
$mysql_link = mysql_connect("localhost", $mysql_user, $mysql_pass);
mysql_select_db($mysql_db, $mysql_link);
?>

显然,您需要使用您自己的环境的数据库名、用户名和密码。如果您不能访问支持 MySQL 和 PHP 的主机帐户但想跟随本教程操作,则现在是配置您的环境的好时机。参见 参考资料 了解一些可用选项。

数据库就绪后,下一步是切换到一个自上而下的方法,这需要查看这个应用程序的主源文件 index.php,如 清单 7 所示。

 

					
<?
require('db.php');
require('utils.php');
require('header.php');
?>
    <div  data-role="page">
    <div data-role="header">
    <h1>JQuery Tutorial</h1>
    </div>
    <div data-role="content">

<? 
$action = $_REQUEST['action'];
if ($action == 'addnew') {
   showOneOpp(-1);
} else if ($action == 'upsert') {
    if ($_REQUEST['id'] == '-1') {
        addOpp($_REQUEST['person'],$_REQUEST['contact'],$_REQUEST['description']);
    } else {
        updateOpp($_REQUEST['id'],$_REQUEST['person'],$_REQUEST['contact'],
$_REQUEST['description']);
    }
   showOpps();
} else if ($action == 'delete') {
    killOpp($_REQUEST['id']);
    showOpps();
} else if ($action == 'details') {
    showOneOpp($_REQUEST['id']);
} else {
    showOpps();
}
?>
    </div>
    <div data-role="footer">
    Sample code for IBM developerWorks
    </div>
    </div>
<? require('footer.php'); ?>
</body>
</html>

这个 PHP 文件是服务器上的所有交互的入口点。根据一个名为 action 的参数的存在性和值,脚本执行不同的功能。在深入具体操作之前,请注意这个文档中的 jQuery Mobile 结构,该结构包含多个 div 元素,每个元素都带有相应 data-role,用于页面、页眉、内容和页脚。

这个应用程序架构相当简单 — 页面每次加载时,其内容都将被 content div 中新生成的内容替代。在某种程度上,这可能带有欺骗性并返回一些旧的 web 应用程序习惯。也许是这样,但本教程的目标是在一个有用的真实世界场景中演示 JQM 的一些基本功能,因此,保持这个简单结构有助于实现所有目标。

要理解发生了什么事,我们从上到下仔细查看一下 index.php。

  1. db.php 文件被包含进来 — 这个文件向您提供数据库访问权。
  2. utils.php 文件被包含进来 — 这个文件提供所有特定于这个应用程序的数据管理功能。
  3. header.php 文件被包含进来 — 这个文件包含 jQuery Core 和 jQuery Mobile JavaScript 文件、jQuery Mobile CSS 文件以及一个特定于应用程序的 JavaScript 文件:utils.js。
  4. JQM div 元素被定义,页眉包含一个 h1 标记和一个伴随标题文本。
  5. 通过从 $_REQUEST 内置数组提取建立 $action 变量。$_REQUEST 变量 coalesces $_GET$_POST 数据,简化发送到这个页面的各种请求的处理过程。
  6. 使用以下选项评估 $action 变量,每个选项都调用 utils.php 中的一个或多个函数:
    1. addnew — 显示一个空表单以添加一个新条目。当您正在参加商贸展或会见一位新的潜在客户时,这个特性可能正是您需要的。
    2. upsert — 如果记录是新的,您可能想将它插入表中。如果记录已经存在,您需要更新它的列。如果 id 字段的值等于 -1,说明您有一条全新的记录,必须执行插入操作。其他值代表一条有效记录、商机或标识符。
    3. delete — 用户已请求删除这条记录。
    4. details — 用户已经选择一个条目,想查看这个商机的细节。
    5. 如果 $action 变量为空,则表示只显示一列商机。这是页面首次加载时的默认行为。
  7. 页面最后包含 footer.php。在这个应用程序中,页脚包含一些 Google 分析代码,以便跟踪应用程序的使用情况。

理解这个页面后,下一步是检查 utils.php 中包含的功能。特别是,您需要查看 showOpps 函数,该函数为用户界面生成一个商机列表,并引入一个新的 JQM 功能:listview,如 清单 8 所示。

 

					
function showOpps()
{
global $mysql_link;

$COL_OPPID= 0;
$COL_PERSON= 1;
$COL_CONTACT= 2;
$COL_DESCRIPTION= 3;
$sql ="select * from opportunities order by opp_id desc";
$result = mysql_query($sql,$mysql_link);

  if(mysql_num_rows($result))
  {
    print("<a data-rel=\"dialog\" data-transition=\"pop\" 
href=\"index.php?action=addnew\">Add New Opportunity</a>
<br/><br/>");
    print("<ul data-role=\"listview\" data-filter=\"true\">"); 
    while($row = mysql_fetch_row($result)) {
        print("<li data-ibm-jquery-contact=\"".$row[$COL_CONTACT]."\">");
        print("<a data-rel=\"dialog\" data-transition=\"pop\"
 href=\"index.php?action=details&id=".$row[$COL_OPPID]."\">");
        print("Person:&nbsp;".$row[$COL_PERSON]."<br/>");
        print("Contact:&nbsp;".$row[$COL_CONTACT]."<br/>");
        print("Description:&nbsp;".$row[$COL_DESCRIPTION]);
        print("</a>");

        print("</li>\n");
    }
    print("</ul>");
   }
}

showOpps 函数跳到数据库,取出所有行,首先显示最新记录,然后将数据组织到一个 listview 中。注意这个代码清单中的 JQM 特性。

  1. 在获取行之前,将为 Add New Opportunity 生成一个定位标记。这里包含了两个特定于 JQM 的特性:
    1. data-rel="dialog" 告知 JQM 新窗口出现时应该如何显示。它获取一个对话框的颜色方案。
    2. data-transition="pop" 告知 JQM 对话框以弹出方式显示。当对话框被清除时,它执行一个反向过渡,这时,对话框逐渐缩小直到消失。当您试验这个应用程序时,尝试将这个值更改为翻页、淡出或其他可用过渡。
      图 7 显示了添加新条目的对话框屏幕。这次,它在一个 iPod 上处于纵向显示模式(portrait mode)。


      Adding a new opportunity 对话框的屏幕截图,其中包含 Person 字段、活动 Next 按钮和 qwerty 键盘
       
  2. 当列表被创建时,它被创建为一个无序列表(或 ul 元素)。 这个元素的 data-role 是一个 listview。这是 JQM 的一个重要属性,因为列表管理是一个重要主题。另外,要注意 data-filter="true" 属性。这个简单属性提供整个应用程序中最有价值的功能(尽管有争议) — 主屏幕上的先行(look-ahead)搜索,如 图 8 所示。


    过滤后的结果的屏幕截图


    当用户输入一个词组时,将检查列表中的每个条目,查看是否存在该词组;如果不存在,将从列表中删除该条目,只留下匹配的条目。在 图 8 中,单词 “Lego” 只存在于一个条目中。 一个有趣的边注:图 8 中的图像来自我的 MacBook 上运行的 WebKit (Safari)。Safari 和 Chrome 都是测试以移动为目标的 web 应用程序的桌面浏览器的不错选择。
  3. 当用户选择链接中的一个条目时,他们实际上是使用一个 data-reldialog 和一个 data-transitionpop 激活一个定位。结果是 图 9(同样来自桌面机)中的一个对话框视图中的一个特定条目的关联细节。这个条目显示 Person、Contact info 和 Comments 字段以及 Save Opportunity 按钮。


    一条商机记录的细节的屏幕截图


    注意,不管这个屏幕图像来自那个设备,它都有相似的观感。这个教程在 Android 设备、iPod 和 Safari(WebKit nightly build)上都能很好地运行。可以看出,jQuery Mobile 的一些设计目标取得了成果。
  4. 这个代码清单中最后需要注意的项目是使用列表项列示的属性。在本例中,每个列表项都包含一个名为 data-ibm-jquery-contact 的自定义属性,该属性的值来自数据库中的 opp_contact 字段。这个项目存在的目的为了将来实现以下功能:添加当用户在列表中的一个条目上执行 “敲击并保持(taphold)” 操作时致电或发送电子邮件的能力。

当一条现有商机记录在对话框中显示(如 图 9 所示)之后,用户可以选择几个选项。这个页面的代码在 utils.php 中的 showOneOpp 函数中提供,如 清单 9 所示:

 

					
function showOneOpp($id)
{
global $mysql_link;


$COL_OPPID= 0;
$COL_PERSON= 1;
$COL_CONTACT= 2;
$COL_DESCRIPTION= 3;

$person = "";
$contact = "";
$description = "";

    if ($id != -1) {
        $sql ="select * from opportunities where opp_id = " . $id;
        $result = mysql_query($sql,$mysql_link);

        if(mysql_num_rows($result)) {
            $row = mysql_fetch_row($result);
            $person = $row[$COL_PERSON];
            $contact = $row[$COL_CONTACT];
            $description = $row[$COL_DESCRIPTION];
        }
        print("<a rel=\"external\" href=\"javascript:deleteEntry($id)
\">Delete this entry</a>");
    }

    print("<form method=\"post\" rel=\"external\" action=\"index.php\" 
onsubmit=\"return checkForm();\">");
    print("<input type=\"hidden\" name=\"action\" value=\"upsert\"/>");
    print("<input type=\"hidden\" name=\"id\" value=\"$id\"/>");
    print("<fieldset>");

    print("<div data-role=\"fieldcontain\">");
    print("<label for=\"person\">Person</label>");
    print("<input type=\"text\" name=\"person\" maxlength=\"100\" 
id=\"person\" value=\"$person\" />");
    print("</div>");

    print("<div data-role=\"fieldcontain\">");
    print("<label for=\"contact\">Contact info</label>");
    print("<input type=\"text\" name=\"contact\" maxlength=\"100\" 
id=\"contact\" value=\"$contact\" />");
    print("</div>");

    print("<div data-role=\"fieldcontain\">");
    print("<label for=\"description\">Comments</label>");
    print("<input type=\"text\" name=\"description\" maxlength=\"100\" 
id=\"description\" value=\"$description\" />");
    print("</div>");

    print("<fieldset>");
    print("<button type=\"submit\" value=\"Save\">Save Opportunity
</button>");

    print("</form>\n");

}

这个 showOneOpp 代码是填充您在其中编写所有表单元素的屏幕的一种强力方法。这个屏幕上的一些需要注意的项目包括:

  1. 如果 $id 等于 -1,那么您将准备这个屏幕以添加一条新的商机记录;否则,您将载入现有商机记录并初始化一些页级变量:$person$contact$description
  2. 如果您拥有一条现有记录,那么您将显示一个链接,允许用于删除该商机。
  3. 每个字段周围的 data-role="fieldcontain" 帮助 JQM 显示这些字段:将标签和相关输入 HTML 元素组合在一起,通过细线分隔。
  4. 当用户填充这些字段并选择 Save Opportunity 按钮时,那些字段将受到检查,以确保所有字段都已填充,如果已填充,则保存字段。图 10 显示了警告用户填充所有字段的警报。


    表单级验证的屏幕截图
     
  5. 屏幕上的另一个选项是删除一个现有条目。如果选择该选项,另一个 JavaScript 函数将提示用户确认是否的确要移除选中的商机记录,如 图 11 所示。


    确认删除一条商机记录的屏幕截图


    选择删除提示处的 OK 将使用一个动作 delete 将应用程序发送回 index.php。

这些表单级验证的 JavaScript 例程包含在 utils.js 文件中,该文件由 header.php 包含文件加载。清单 10 显示了 utils.js。

 

					
function checkForm() {
    try {
        if ($.trim($('#person').val()) == "" ||
            $.trim($('#contact').val()) == "" ||
            $.trim($('#description').val()) == "") {
                alert("Please enter all fields");
                return false;
            }
    } catch (e) {
        alert(e);
        return false;
    }
    return true;
}

function deleteEntry(id) {
    try {
        var confirmString = "Delete this entry.  Are you sure?\n" + $.trim($('#person')
.val()) + "\n" + $.trim($('#contact').val()) + "\n" + $.trim($('#description').val());
        if (window.confirm(confirmString)) {
            window.location="index.php?action=delete&id=" + id;
        }
    } catch (e) {
        alert(e);
        return false;
    }
    return true;

}

这些函数是非常直观的 JavaScript,通过一些 jQuery 选择器辅助。

您已经看到了这个应用程序的大部分功能。现在看看 utils.php 中实现的另外几个函数,如 清单 11 所示。

 

					
function addOpp($person,$contact,$description)
{
    global $mysql_link;

    $sql = "insert opportunities(opp_id,opp_person,opp_contact,opp_description) values 
(NULL,'$person','$contact','$description')";
    $result = mysql_query($sql,$mysql_link);
    if ($result == 1) {
        return "SUCCESS";
    } else {
        return "FAILED";
    }

}

function updateOpp($id,$person,$contact,$description)
{
global $mysql_link;

$sql = "update opportunities set opp_person='".$person."',opp_contact= 
'".$contact."',opp_description='".$description."' where opp_id= ".$id;
$result = mysql_query($sql,$mysql_link);
if ($result == 1) {
    return "SUCCESS";     
} else {
    return "FAILED";
}

}


function killOpp($id)
{
global $mysql_link;

$sql = "delete from opportunities where opp_id =$id";

$result = mysql_query($sql,$mysql_link);

}

可以看到,这些例程实现一些直观的 PHP/MySQL 数据访问功能:插入、更新和删除商机记录。

尽管使用 jQuery Mobile 构建的本教程样例应用程序的代码到此结束,但这应该被视为一个起点,而不是一个终点,因为还有更多 jQuery Mobile 知识等待您去探索。JQM 项目计划在 2011 年初推出其 1.0 发布。随着时间推移,希望它能集成到 PhoneGap 这样的框架中,甚至可能集成到 Appcelerator 的 Titanium 这样的替代开发环境中。

最后,本教程检查这个新创建的、由 JQM 驱动的 web 应用程序的安装快捷键。


这个应用程序不是原生应用程序,因此不能从传统 App Store 下载,但是,您可以在您的设备的主屏幕上为它创建一个快捷键。图 12 展示如何在一个 iPod 设备上创建一个快捷键。


选择您的屏幕底部的 + 号之后出现的菜单的屏幕截图

iPod 平台允许添加新书签、向主屏幕添加链接、或将链接电邮给朋友。选择 Add to Home Screen 选项。然后,命名链接,如 图 13 所示。


Add to Home Screen 选项的屏幕截图

您提供快捷键名称后,快捷键将出现在您的主屏幕中,正好在您的 “最喜爱的游戏” 旁边,如 图 14 所示。


iPod 平台的主屏幕上的快捷键的屏幕截图

在 Android 平台上添加快捷键需要更多步骤,首先需要创建一个新书签,如 图 15 所示。


在 Android 平台上创建一个新书签的屏幕截图

选中书签,给它提供一个名称,如 图 16 所示。


可用书签的屏幕截图

现在您的书签拥有了一个名称,可供后续使用。

下一步是转到主屏幕,按住屏幕上的一个空白区域。这时会出现一个选项,允许向主屏幕添加项目。选择 Shortcuts 选项,如 图 17 所示。


添加一个快捷键的屏幕截图

然后,选择 Bookmark 以查看现有书签,如 图 18 所示。


选择查看现有书签的屏幕截图

然后,您将看到一些可用书签。选择您新创建的 jQuery Mobile 应用程序对应的适当条目,如 图 19 所示。


选择您的 web 应用程序的屏幕截图

最后,您的快捷键现在应该出现在桌面上,如 图 20 所示。


图 20. Android 主屏幕上的快捷键
Android 主屏幕上的 jQuery Mobile 应用程序快捷键的屏幕截图

本教程到此结束。如果您跟随本教程的操作,您应该已经了解 jQuery Mobile 的基本结构及其与 jQuery Core 项目的关系。您创建了一个销售商机跟踪应用程序,该程序拥有跨平台兼容性,能在多种设备上运行。而且,您能将该应用程序安装到您最喜欢的智能手机的主屏幕 上。

本文地址http://www.chengxuyuans.com/web_technology/179.html