[转] electron实战开发详细流程
【From】 http://www.myk3.com/arc-8856.html
很久没有更新博客,人越来越懒了,唉 说好做的electron教程距离上次玩electron已经过去了好几个月了。。
这次对electron做一个实战流程的介绍,关于electron的介绍,可以看这里 http://www.myk3.com/arc-4486.html
关于electron的demo安装,请看 http://www.myk3.com/arc-4483.html
使用 electron 您需要有一定的nodejs使用基础,能熟练使用js语言。那么,以这篇文档http://www.myk3.com/arc-4486.html 的项目为例,来介绍其中用到的技巧和流程。
思想:项目的界面采用html+css+js完成,关于顶部的标题栏和最大化最小化 关闭按钮也是用html完成。后面说他们与electron 的交互。而electron 提供包含在线网页的容器框架,一个electron窗口包含一个在线网页。
假如我们写好了登录页面,这里面有如下的地方需要雨electron 交互 甚至与node模块交互。分别是 点击页面中的新窗口打开的连接,会弹出新的无标题栏窗口,我们拦截点击事件,让其用默认浏览器打开。然后是自己写的标题栏的拖动,最大化,最小化,关闭按钮的响应。点击登录打开新窗口的响应。以及穿够页面加载完毕才显示。 如果你的网页载入很慢,建议html本地化,我这里的服务器性能不错,所以直接在线加载,速度也不错。
那么对上面页面中需要与electron 响应的功能,下面一一说明。
先创建一个登录窗口,并加载登录页面作为gui驱动。在main.js中写。修改你安装的demo中的createWindow方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function createWindow () { mainWindow = new BrowserWindow({ width: 500, //窗口宽度 height: 600, //窗口高度 resizable: false , //能否改变窗体大小 'accept-first-mouse' : true , title: '佳乐社区' , frame: false , show: false , //是否显示界面 先设置否 //icon:'3.ico', hasShadow : true }) mainWindow.loadURL(baseUrl+ 'user.php?a=basic&f=login&app=1' ) } |
我们让其加载完毕显示,加上在载入完毕显示的代码
1
2
3
|
mainWindow.webContents.on( 'did-finish-load' , function () { mainWindow.show(); }); |
这样登录窗口就显示了。接下来标题栏的拖动。很简单在标题栏的html元素上加上 css
1
|
-webkit-app-region: drag; |
对于加上-webkit-app-region: drag;的元素,只能拖动,而我们的最大化最小化,关闭都包含在其中,我们让他们可以点击,单独设置这几个按钮加上css
1
|
-webkit-app-region: no-drag; |
如图:
当然,你也可以保留window的标题栏,这样就不用自己写事件处理了,不过,小安觉得自带的太丑了,所以重写。
接下来对于页面中target="blank"a连接弹出的新窗口做拦截,让其用自带的浏览器打开,如果用无标题栏的electron打开,很丑,具体思想,调用node的exec函数执行cmd,不过需要先拦截,具体代码:
1
2
3
4
5
6
|
mainWindow.webContents.on( 'new-window' , function (event,url,fname,disposition,options) { var exec = require( 'child_process' ).exec; //加载node模块 url是将要跳转的地址 //拦截url调用外部浏览器打开 exec( 'start ' +url, function (err,stdout,stderr){}); event.preventDefault(); }); |
然后我们来看 最大化,最小化,关闭的处理
这里要介绍下electron的ipc通信,具体的专业术语不知道,反正就是让main.js和各个electron窗口之间能通信,互相控制,官方有个规则,一切的electron窗口原生操作都尽量在main.js中处理,这是安全的,虽然在各个electron窗口的html页面也可以写窗口的相关操作代码。
用实例来演示ipc的用法。main.js中创建了登录的electron窗口,在点击窗口中html写的最小化按钮时,触发页面js,我用jquery来绑定点击事件
1
2
3
4
5
|
var ipc = require( 'electron' ).ipcRenderer; //绑定最小化 f.$doc.delegate( '.window_min' , 'click' , function (e){ ipc.send( 'login-window-min' ); //发送了一个login-window-min的消息,这个消息将在 main.js中接受,名称可以自定义。 }) |
记得在html页面中使用ipc一定要先引用
1
|
require( 'electron' ).ipcRenderer; |
而在main.js中不一样,用这句 这里语法是es6,新一代的js语法,童鞋们可以学习下
1
|
const ipc = electron.ipcMain |
在main.js中处理接受到消息login-window-min 代码如下:
1
2
3
4
|
//登录窗口最小化 ipc.on( 'login-window-min' , function (){ mainWindow.minimize(); }) |
mainWindow是我们的登录窗口创建后返回的句柄,它是全局的,所以在main.js的任何地方都可以用,它的定义是全局的
1
|
let mainWindow |
而最大化和关闭都差不多。
完整代码登录的html中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
f.$doc.delegate( '.window_close' , 'click' , function (e){ ipc.send( 'login-window-close' ); }) f.$doc.delegate( '.window_min' , 'click' , function (e){ ipc.send( 'login-window-min' ); }) var is_window_max = false ; f.$doc.delegate( '.window_max' , 'click' , function (e){ ipc.send( 'login-window-max' ); if (is_window_max){ is_window_max = false ; $( this ).find( 'div' ).css( 'fontSize' , '24px' ); } else { $( this ).find( 'div' ).css( 'fontSize' , '20px' ); is_window_max = true ; } }) |
main.js中的处理过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//关闭所有窗口 调用ipc模块 主进程 ipc.on( 'login-window-close' , function (){ app.quit(); }) //登录窗口最小化 ipc.on( 'login-window-min' , function (){ mainWindow.minimize(); }) //登录窗口最大化 ipc.on( 'login-window-max' , function (){ if (mainWindow.isMaximized()){ mainWindow.restore(); } else { mainWindow.maximize(); } }) |
应为登录窗口是主窗体,所以当登录窗体关闭,应用结束,用 app.quit();
接下来介绍登录按钮点击后创建新electron窗口,在登录html页面中写绑定,在ajax登录验证成功的回调中打开新窗体
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
|
success: function (r){ $( '#login-error' ).hide(); $( '#login-error' ).fadeIn(500); $( '.notice-descript' ).text(r.msg); if (r.status){ //检查是否记住密码 lo.remember_pwd(); //如果是软件登录则打开内容窗口 if (f.app){ ipc.send( 'content-window-show' ,r.data); setTimeout( function (){ $( '#fm-login-submit' ).attr( 'disabled' , false ); },4000); return false ; } $( '.icon-notice' ).removeClass( 'icon-error' ).addClass( 'icon-success' ); $( '.loading-mask' ).show(); if (f.backurl){ //如果是其他地方跳转过来的登录 location.href = 'http://' +f.backurl; } else { location.href = 'user.php?a=index&f=home&app=' +f.app; } } else { $( '#fm-login-submit' ).attr( 'disabled' , false ); } } |
主要是这一句
1
|
ipc.send( 'content-window-show' ,r.data); |
发送打开新窗体的命令,带了参数r.data.
在main.js中我们来写监听并响应,其实和socket.io的编写方式差不多。
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
|
//内容窗口显示 一般登录成功才行 var contentWindow = null ; var remindWindow = null ; ipc.on( 'content-window-show' , function (event,u){ UserInfo = u; console.log(u); //先隐藏登录窗口 setTimeout( function (){ mainWindow.hide(); },1800); //创建提醒窗口 creatRemindWindow(); //创建内容窗口 if (contentWindow){ contentWindow.focus(); return ; } contentWindow = new BrowserWindow({ frame: false , height: 700, resizable: false , width: 1240, //icon:'3.ico', frame: false , show: false , }); contentWindow.loadURL(baseUrl+ 'user.php?a=index&f=home&app=1' ); contentWindow.webContents.on( 'did-finish-load' , function () { contentWindow.show(); }); contentWindow.setSkipTaskbar( true ); //contentWindow.webContents.openDevTools() contentWindow.on( 'closed' , function () { contentWindow = null ; }); contentWindow.webContents.on( 'new-window' , function (event,url,fname,disposition,options) { var exec = require( 'child_process' ).exec; //拦截url调用外部浏览器打开 exec( 'start ' +url, function (err,stdout,stderr){}); event.preventDefault(); }); ipc.on( 'content-window-min' , function (){ contentWindow.minimize(); }) }) |
我们看见了其实创建过程和创建登录窗口差不多,通过加载不同的
1
|
loadURL(baseUrl+ 'user.php?a=index&f=home&app=1' |
url来显示不同的页面作为GUI。
到这里,如果你能看明白,那么已经可以用electron做项目开发了,毕竟,核心的东西就这些,其他是一些小技巧,比如右下角图标和右键菜单的使用,代码如下:
载入模块
1
|
const {Menu,Tray, MenuItem} = electron; |
实现代码
1
2
3
4
5
6
7
8
|
//显示右下角图标 tray = new Tray(path.join(__dirname, '3.ico' )) //右下角的图标 const contextMenu = Menu.buildFromTemplate([ //右键菜单项 可以是多个 这里只有关闭一个项 {label: '关闭' , click: function (){ app.quit(); }}, //{label: 'Item2', type: 'radio'}, ]); |
给右下角图标绑定右键菜单
1
|
tray.setContextMenu(contextMenu); |
绑定双击事件,让其窗口显示
1
2
3
4
5
6
7
|
tray.on( 'double-click' , function (){ if (contentWindow){ contentWindow.show(); } else { mainWindow.show(); } }) |
上面这些代码需要写在createWindow 创建登录窗口的函数体中。
如图:
如果使用右下角图标,那么下方的任务栏不应该在显示程序信息,隐藏方法为
1
2
|
//隐藏任务栏 mainWindow.setSkipTaskbar( true ); |
右键菜单不仅可以绑定给右下角图标,也可以是html元素的任何位置,具体的代码我看看 比如绑定到h1标签上,在html中写js代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//右键菜单 const {remote} = require( 'electron' ); const {Menu,Tray, MenuItem} = remote; const menu = new Menu(); menu.append( new MenuItem({label: '查看' , click() { console.log( 'item 1 clicked' ); }})); //menu.append(new MenuItem({type: 'separator'})); menu.append( new MenuItem({label: '编辑' , type: 'checkbox' , checked: true })); var h1 = document.getElementById( 'rightButton' ); h1.addEventListener( 'contextmenu' , (e) => { e.preventDefault(); menu.popup(remote.getCurrentWindow()); }, false ); |
当然也可以在html中(非main.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
|
const BrowserWindow = require( 'electron' ).remote.BrowserWindow const path = require( 'path' ) const newWindowBtn = document.getElementById( 'openNewWindwo' ) const clo = document.getElementById( 'close' ) newWindowBtn.addEventListener( 'click' , function (event) { const modalPath = path.join( 'file://' , __dirname, 'modal.html' ) let win = new BrowserWindow({id:2, width: 400, height: 320,title: 'test' }) win.loadURL(`file: //${__dirname}/model.html`)//指定渲染的页面 //win.show()//打开一个窗口 //win.webContents.openDevTools() win.webContents.on( 'did-finish-load' , function () { win.show(); }); win.on( 'move' , updateReply) win.on( 'resize' , updateReply) win.on( 'closed' , function () { win = null }) function updateReply () { const mangageWindowReply = document.getElementById( 'manage-window-reply' ) const message = `Size: ${win.getSize()} Position: ${win.getPosition()}` mangageWindowReply.innerText = message } }) |
在html页面中(非main.js)枚举所有窗体
1
2
3
|
const {dialog} = require( 'electron' ).remote; win = BrowserWindow.getAllWindows(); win[0]就是第一个创建的窗口 |
最后介绍下文件对话框的使用 在html中写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//打开文件框 方便读写文件操作 $( '#dialog' ).on( 'click' , function (e){ const {dialog} = require( 'electron' ).remote; win = BrowserWindow.getAllWindows(); dialog.showOpenDialog(win[0],{properties: [ 'openFile' , 'multiSelections' ],filters: [ //{name: 'Images', extensions: ['jpg', 'png', 'gif']}, //{name: 'Movies', extensions: ['mkv', 'avi', 'mp4']}, //{name: 'Custom File Type', extensions: ['as']}, {name: 'All Files' , extensions: [ '*' ]} ]}, function (r){ console.log(r); }) }) |
好了,使用上大概我也就会这些,更多的操作可以去看官方英文文档,比较详细,希望能让你更快的学会electron,下一篇文档小安会抽时间做electron的打包教程,以及跨平台,其实只要打包后,下载对应的版本,跨平台修改的代码很少,至少对我我的这个项目而言,搬运到mac系统上只删除了几行代码就能运行了,祝你好运。感谢阅读
本文来自:绵阳史安平个人博客.励志于每一位朋友
欢迎转载,转载请注明本文链接: electron实战开发详细流程
http://www.myk3.com/arc-8856.html
[转] electron实战开发详细流程的更多相关文章
- FPGA 开发详细流程你了解吗?
FPGA 的详细开发流程就是利用 EDA 开发工具对 FPGA 芯片进行开发的过程. FPGA 的详细开发流程如下所示,主要包括电路设计.设计输入.综合(优化).布局布线(实现与优化).编程配置五大步 ...
- 用grunt搭建自动化的web前端开发环境实战教程(详细步骤)
用grunt搭建自动化的web前端开发环境实战教程(详细步骤) jQuery在使用grunt,bootstrap在使用grunt,百度UEditor在使用grunt,你没有理由不学.不用!前端自动化, ...
- S3C2440—3.用点亮LED来熟悉裸机开发的详细流程
文章目录 一.硬件知识 1.LED原理图 2.芯片手册 Ⅰ.找LED原理图 Ⅱ.找对应引脚 Ⅲ.在芯片手册中查找引脚信息 Ⅳ.查看寄存器说明 Ⅴ.配置寄存器 二.S3C2440框架与启动过程 三.要用 ...
- 【ASP.NET实战教程】基于ASP.NET技术下多用户博客系统全程实战开发(NNblog)
岁末主推:牛牛老师主讲,多用户博客系统,基于ASP.NET技术,年后将带来移动业务平台项目项目目标: 打造个性品牌Blogo,定制多用户博客 为每一个博客用户提供个性化的 blogo解决方案,打造精品 ...
- 王家林的81门一站式云计算分布式大数据&移动互联网解决方案课程第14门课程:Android软硬整合设计与框架揭秘: HAL&Framework &Native Service &App&HTML5架构设计与实战开发
掌握Android从底层开发到框架整合技术到上层App开发及HTML5的全部技术: 一次彻底的Android架构.思想和实战技术的洗礼: 彻底掌握Andorid HAL.Android Runtime ...
- springboot实战开发全套教程,让开发像搭积木一样简单!Github星标已上10W+!
前言 先说一下,这份教程在github上面星标已上10W,下面我会一一给大家举例出来全部内容,原链接后面我会发出来!首先我讲一下接下来我们会讲到的知识和技术,对比讲解了多种同类技术的使用手日区别,大家 ...
- electron 应用开发优秀实践
vivo 互联网前端团队-Yang Kun 一.背景 在团队中,我们因业务发展,需要用到桌面端技术,如离线可用.调用桌面系统能力.什么是桌面端开发?一句话概括就是:以 Windows .macOS 和 ...
- Cordova webapp实战开发:(4)Android环境搭建
在<Cordova webapp实战开发:(3)后面可能会学到的东西>中我们说了一下后续大致包括的内容,今天我们继续.上周我在掌中广材集成了友盟的社交分享,今天想集成iOS应该很顺利的,但 ...
- 【转】xcode APP 打包以及提交apple审核详细流程(新版本更新提交审核)
原文网址:http://blog.csdn.net/mad1989/article/details/8167529 最近项目到了最后的阶段,测试完一切ok后,准备打包以及提交,不料看到网上众教程,好多 ...
随机推荐
- Solidity 没名字的function(){...}作用
官方解释: 这个叫做fallback function,当有人 1. 只发送以太币给合约而不带任何输入数据:2. 调用smart contract时调起了一个不存在的方法.会触发执行这个方法. Wha ...
- UIWebView分页显示
問題:使用iOS UIWebView時,載入本地html檔案,但是該檔案太大,結果螢幕畫面形成一長條型顯示,雖然用滾動畫面可以看見整個html檔案,但是滑來滑去,不好用. 目標:用UIWebView載 ...
- 自定义UINavigationBar的背景【转】
from:http://cocoa.venj.me/blog/custom-navbar-background/ 为了让我们的应用程序更加美观,我们往往希望对iPhone自带的控件进行一点自定义.比如 ...
- 积分之谜——第六届蓝桥杯C语言B组(国赛)第一题
原创 标题:积分之迷 小明开了个网上商店,卖风铃.共有3个品牌:A,B,C. 为了促销,每件商品都会返固定的积分. 小明开业第一天收到了三笔订单: 第一笔:3个A + 7个B + 1个C,共返积分:3 ...
- 转 Delphi中XLSReadWrite控件的使用(2)---基本应用
unit Main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, ...
- Javascript脚本 : eval()函数
Javascript 中 eval(X)函数 是将参数 当做语句来执行 var number1='1+2'; alert(number1); 输出为 '12': var number2=eval('1 ...
- WPF中XAML的触发器的属性,事件 都有那些?以及如何寻找
在编写XAML的触发器时,会有属性,事件. 那么这些都是哪里来的呢? 属性,是附加属性或者依赖属性 事件,那就是事件. 如何寻找呢? 很简单,在想要使用的触发器的对象上(也就是有光标的时候)按下F12 ...
- 原生态js,返回至顶部
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- php代码审计2全局变量和超全局变量
全局变量:就是在函数外面定义的变量,不能在函数中直接使用,因为它的作用域不会到函数内部,所以在函数内部使用的时候尝尝看到类似global $a; 超全局变量:在所有脚本都有效,所以,在函数可以直接使用 ...
- bzoj2115(线性基)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2115 题意:求图中路径1~n上最大边权 xor 和 思路:参见 blog http://b ...