2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

使用 node-webkit 构建桌面应用程序(二)

  • 2015-05-19
  • 本文字数:4445 字

    阅读完需:约 15 分钟

在这片文章中,我们将使用 node-webkit 来编写一个实际的例子,来说明如何使用 HTML5+CSS3 技术编写桌面应用。我们将通过给 Moco 工具编写一个简单的设计器来说明一些具体的技术,比如和本地文件的交互,实现简单的上下文菜单等。

Moco 简介

Moco 是一个用于简化服务器搭建的轻量级的测试工具,使用 Moco 可以很容易地创建一个“假的”服务器,这个服务器的行为就好像真实的服务器一样。Moco 不但可以将集成测试变得更加简单,还可以搭建一个稳定的后端,从而使得纯前端的 Web 开发(或者前后端分离开发)变得平坦而容易。

Moco 需要一个配置文件来指明 request/response 的对应关系:

复制代码
[
{
"request": {
"method": "post",
"uri": "/action.do",
"json_paths": {
"$.type": "events"
}
},
"response": {
"status": 200,
"file": "spec/fixtures/events.json"
}
}
]

上例这个配置文件指定了:当发往 /action.do 的 POST 请求中,包含了 JSONPath 如 $.type=events 时,Moco 会响应一个 200 的状态码,并且会返回文件 spec/fixtures/events.json 的内容作为响应。

每个配置文件中可以指定多条规则,当请求到达时,Moco 会依次匹配,直到找到对应的规则,如果没有发现匹配,则返回 400 错误。

模板项目

我在 github 上创建了一个 node-webkit 的模板工程。你可以很从这个模板工程开始你的 node-webkit 之旅:

复制代码
$ git clone git@github.com:abruzzi/node-webkit-boilerplate.git
$ cd node-webkit-boilerplate
$ npm install
$ grunt

这个 grunt 命令会下载 node-webkit,并构建应用程序:

构建之后,可以执行

复制代码
$ ./launch.sh

启动应用程序,如果你看到了下面这个界面,说明基本的环境已经就绪,然后就可以进行下一步了。

引入 bootstrap

bootstrap 可以帮助我们快速地从零开始搭建一个专业的 Web 页面,bootstrap 提供了丰富的特性,开箱即用的组件,我们这里只使用其中的布局器和表单组件。

使用 bootstrap 的一个模板 HTML 如下:

复制代码
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>node-webkit application</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<h1>Hello, node-webkit!</h1>
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/app.js"></script>
</body>
</html>

有了 bootstrap,接下来可以很容易地创建出专业的页面,比如在下面这个页面中,我们创建了几个列表:

复制代码
<div class="row">
<div class="media">
<a class="pull-left" href="#">
<img class="media-object" src="http://placehold.it/64x64">
</a>
<div class="media-body">
<h4 class="media-heading">Listing object</h4>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
</div>
</div>
...
...
</div>

上面片段中的 http://placehold.it/ 是一个提供图片占位符的服务,你只需要指定占位符的大小如 64x64,这个服务就会返回给你一张对应尺寸的占位符。

有了这些元素之后就更像是一个桌面应用程序了。

Moco Services Designer

如前面所述,我们这篇文章中将要开发一个实际例子:moco 服务器需要一个配置文件,但是 moco 本身提供了丰富的特性,因此要记住所有的选项非常困难,所以需要一个图形界面支持用户通过简单的操作就可以导出 moco 的配置文件:

点击界面中的加号会生成一个新的规则,每个规则分为请求和响应两部分,这里我们只提供最简单的选项:

  1. 用户可以选择使用那种 HTTP 动词(GET/POST/PUT/DELETE);
  2. 用户可以指定一个 URI;
  3. 用户可以指定一个字符串作为返回;
  4. 用户可以定义多条规则;
  5. 访问本地文件。

首先在界面上有一个蓝色的加号:

复制代码
<div class="row">
<div class="col-lg-12 col-md-12">
<a id="addRule" href="#" class="pull-right">
<span class="glyphicon glyphicon-plus"></span>
</a>
</div>
</div>
<div id="rules">
</div>

点击这个加号可以在页面上 ID 为 rules 元素中添加一个新的 HTML 片段:

复制代码
$("#addRule").on("click", function() {
$("#rules").append(fragement);
});

这个片段来自另外一个文件:

复制代码
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">Rule
<a href="#" class="pull-right remove">
<span class="glyphicon glyphicon-minus"></span>
</a>
</div>
<ul class="list-group">
<li class="list-group-item">
<div class="input-group">
<select name="method">
<option value="get" selected="true">GET</option>
<option value="post">POST</option>
<option value="put">PUT</option>
<option value="delete">DELETE</option>
</select>
</div>
</li>
<li class="list-group-item">
Request
<div class="form-group">
<input type="text" class="form-control" name="uri" placeholder="/checkout">
</div>
</li>
<li class="list-group-item">
Response
<div class="form-group">
<textarea class="form-control" name="text" placeholder="content"></textarea>
</div>
</li>
</ul>
</div>
</div>

由于涉及本地文件的存取,我们需要引入 node.js 中的 fs 模块,首先在 app 目录中创建一个 node_modules 目录,并在该目录中创建一个 file.js 文件,内容如下:

复制代码
var fs = require('fs');
function File() {
function save(path, text) {
fs.writeFile(path, text);
}
function read(path, callback) {
fs.readFile(path, 'utf-8', callback);
}
this.save = save;
this.read = read;
}
module.exports = new File;

我们导出了 save 和 read 两个方法可供使用,然后在外部的 app.js 中可以通过 require 的方式引入该文件:

复制代码
var file = require('file.js');
var fragement = null;
file.read("rule.html", function(error, content) {
fragement = content;
});

要将页面上的内容保存到本地文件系统中,需要使用 node-webkit 提供的 nwsaveas。

复制代码
<input id="save" type="file" nwsaveas style="display:none" accept="text/*"/>

有了这个 nwsaveas,我们可以为它注册一个 change 事件的回调,当用户选择了文件名(选择文件是一个典型的异步操作,保存文件的代码其实不知道用户在何时完成选择)之后,这个回调会执行。

一个简单的做法是定义一个隐藏的按钮,ID 为 save,一个可见的按钮 ID 为 export,当 export 按钮被点击时,它触发 save 的点击,并且为 change 绑定回调函数。

复制代码
$("#export").on("click", function() {
chooseFile("#save");
});
function chooseFile(id) {
var chooser = $(id);
chooser.change(function(evt) {
var config = generateMocoConf();
var filename = $(this).val();
file.save(filename, config);
});
chooser.trigger('click');
}

这样,当用户完成选择之后,我们就有了文件名,这时候就可以将内容存入外部文件了。

当用户最终导出文件时,通过遍历所有的规则,然后生成一个 JSON:

复制代码
function generateMocoConf() {
var rules = $("#rules .row");
var config = [];
$(rules).each(function(index, item) {
var method = $('select[name="method"]', item).val();
config.push({
request: {
method: method,
uri: $('input[name="uri"]', item).val()
},
response: {
text: $('textarea[name="text"]', item).val()
}
});
});
return JSON.stringify(config, null, 4);
}

右键菜单

到目前为止一切都还很顺利,你可以添加规则,保存规则到文件。但是你可能已经发现了,拷贝 / 粘贴等不工作,而且右键菜单也不见了。

我们需要自己构建一个右键菜单,比如最简单的拷贝 / 剪切 / 粘贴:

复制代码
function Menu(cutLabel, copyLabel, pasteLabel) {
var gui = require('nw.gui'),
menu = new gui.Menu(),
cut = new gui.MenuItem({
label: cutLabel || "Cut",
click: function() {
document.execCommand("cut");
}
}),
copy = new gui.MenuItem({
label: copyLabel || "Copy",
click: function() {
document.execCommand("copy");
}
}),
paste = new gui.MenuItem({
label: pasteLabel || "Paste",
click: function() {
document.execCommand("paste");
}
});
menu.append(cut);
menu.append(copy);
menu.append(paste);
return menu;
}

nw.gui 是 node-webkit 提供的一个包,它可以访问整个应用程序级别的对象,比如 window,application 等,详细的文档在这里 [bd1]

我们可以通过这个包来创建一些 MenuItem,并且在这些 Item 上绑定事件。最后,当鼠标右键时,显示这些菜单即可:

复制代码
var menu = new Menu();
$(document).on("contextmenu", function(e) {
e.preventDefault();
menu.popup(e.originalEvent.x, e.originalEvent.y);
});

完整的代码请参看 github 上的 repo

作者简介

邱俊涛,ThoughtWorks 咨询师,喜欢技术,崇尚轻量级的开发 / 工作方式,痛恨冗长的会议和各种繁琐的流程。他还是《JavaScript 核心概念及实践》一书的作者,个人博客是 http://icodeit.org ,博客上经常会有各种技术的分享。


感谢张凯峰对本文的策划,丁晓昀对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流。

2015-05-19 10:054360

评论

发布
暂无评论
发现更多内容

GuavaCache与物模型大对象引起的内存暴涨分析——设备管理运维类

阿里云AIoT

缓存 算法 监控 物联网 数据格式

手把手教你写spring boot starter

三十而立

Java 程序员 IT springboot boot

pytest学习和使用1-pytest安装和版本查看

Python 自动化测试 pytest

pytest学习和使用2-初步使用和用例运行

Python 自动化测试 pytest

武汉等保测评有限公司有哪几家?具体位于哪里?

行云管家

等保 等保测评 等保2.0 武汉

【分布式技术专题】「分布式技术架构」一文带你厘清分布式事务协议及分布式一致性协议的算法原理和核心流程机制(Paxos篇)

码界西柚

分布式 PAXOS paxos协议 算法分析

基于 Apache Flink 的实时计算数据流业务引擎在京东零售的实践和落地

Apache Flink

大数据 flink 实时计算

TiDB SQL调优案例之避免TiFlash帮倒忙

TiDB 社区干货传送门

性能调优 实践案例 故障排查/诊断

国家高新技术企业是国企吗?获得高新企业证书有什么用?

行云管家

高新企业 高新技术

1个案例读懂——游戏产品如何用A/B测试做增长

字节跳动数据平台

云服务 AB testing实战 A/B测试 企业号 3 月 PK 榜

NFTScan 与 UniPass 达成合作伙伴,双方在多链 NFT 数据方面展开合作!

NFT Research

NFT

Apache APISIX 3.2.0 LTS 正式发布

API7.ai 技术团队

阿里120W年薪架构师力荐750页微服务架构深度解析笔记

程序知音

Java 微服务 编程语言 后端技术

浅谈DWS函数出参方式

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 3 月 PK 榜

BSN-DDC基础网络详解(五):接入DDC网络(2)

BSN研习社

BSN-DDC基础网络

面试没有分库分表经验,就看这篇

三十而立

Java sql 程序员 IT 分库

全能代码编辑器:CodeRunner 最新激活版

真大的脸盆

Mac 代码编辑器 Mac 软件 代码编辑 编辑代码

Macbook技巧,Type-c接口失灵怎么办

互联网搬砖工作者

设计消息队列存储消息数据的 MySQL 表格

Geek_7d539e

温湿度计设备通过阿里云IoT物联网套件上报数据到钉钉群机器人实践——数据价值类

阿里云AIoT

JavaScript Serverless 物联网 机器人 机器学习/深度学习

大资管行业数字化转型解决方案 | 行业方案

袋鼠云数栈

大数据 数字化转型 解决方案

快速尝鲜:RabbitMQ 搭建完就得用起来

Java你猿哥

Java Spring Boot ssm RabbitMQ

技术详解 阿里云AIoT物模型支撑设备规模已超亿级——设备管理运维类

阿里云AIoT

运维 安全 监控 物联网 芯片

有效载荷标识与内容类型--MQTT 5.0新特性

EMQ映云科技

物联网 IoT mqtt 企业号 3 月 PK 榜 有效载荷标识

实战|网站监控如何做好监测点管理与内网数据采集

云智慧AIOps社区

安全 监控 监控宝 云智慧 网站监控

Java 8 的异步利器:CompletableFuture源码解析(建议精读)

Java你猿哥

Java ssm java8 源码解析

深入理解spring mvc启动过程与原理

三十而立

Java spring 程序员 开发 IT

阿里云AIoT物联网平台如何实现设备全球就近接入——设备接入类

阿里云AIoT

运维 监控 物联网 中间件 数据采集

PS 2023版本 24.2有哪些新功能?增加了哪些相机配置?

Rose

ps ps 2023 Photoshop 2023下载

共享订阅--MQTT 5.0新特性

EMQ映云科技

物联网 IoT mqtt 企业号 3 月 PK 榜 共享订阅

物联网数据应用开发最佳实践——数据价值类

阿里云AIoT

数据挖掘 物联网 存储 数据管理 调度

使用node-webkit构建桌面应用程序(二)_架构/框架_邱俊涛_InfoQ精选文章