Desktop app với Electron phần 2 : tạo menu
Electron
5
Javascript
269
nodejs
74
White

Mạnh Mẽ lên viết ngày 27/05/2015

Menu trong Electron app

Ở phần 1 mình đã giới thiệu về Electron và những bước cơ bản để tạo một app desktop chạy được trên môi trường Window. Để nhắc lại một chút thì Electron (trước kia gọi là Atom-shell) và một bộ khung để xây dựng desktop app dựa trên công nghệ NodeJS, được phát triển bởi Github và đã được ứng dụng cho rất nhiều app nổi tiếng mà trong đó phải kể đến trình soạn thảo Atom hay Slack app trên desktop.

Phần này mình sẽ hướng dẫn cách tạo menu cho app từ lần trước, cùng với những chú ý về Browser ProcessRender Process. Phần 1 các bạn có thể xem lại ở đây.

Trong một app xây dựng bằng Electron có 2 loại menu: Application MenuContext Menu. Application Menu*là menu ở phía trên xổ xuống, bạn tưởng tượng giống như *File , View, Edit của chương trình word,excel.... Context menu là menu hiện ra khi ấn chuột phải vào cửa sổ app.

Để tạo context menu thì cần hiểu về Browser ProcessRender Process nên mình để cuối bài, trước hãy chúng ta sẽ tạo một Application Menu trước.

Application Menu

Đầu tiên chúng ta sẽ dòng gói Menu. Trong app.js mình sẽ thêm

var Menu = require('menu');

Kế đó, bên trong hàm app.on('ready',function( .... ){}) mình sẽ khởi tạo Menu theo cấu trúc template.

var menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu);

Ở đây menuTemplate sẽ được định nghĩa gồm các menu con và các đầu mục bên trong đó:

var menuTemplate = [
  {
    label: 'Mdpreview',
    submenu: [
      {
        label: 'Quit',
        accelerator: 'Ctrl+Q',
        click: function () {app.quit();}
      }
    ]
  }, {
    label: 'View',
    submenu: [
      {
        label: 'Reload',
        accelerator: 'Ctrl+R',
        click: function() {
          BrowserWindow.getFocusedWindow().reloadIgnoringCache();
        }
      },
      {
        label: 'Toggle DevTools',
        accelerator: 'Alt+Ctrl+I',
        click: function() {
          BrowserWindow.getFocusedWindow().toggleDevTools();
        }
      }
    ]
  }
];

Ở đây bạn có thể thấy cả các phím tắt cho đầu mục như Ctrl+Q hay Ctrl+R. Menu như trên đây chỉ có 3 đề mục đơn giản nhất là Quit, Reload, và Toggle DevTools .

alt text

Context Menu

Electron là một dạng app multiprocess. Có 2 process chính là Browser ProcessRenderer Process. Browser Process chuyên làm các xử lý tính toán nặng, còn Renderer Process chuyên làm nhiệm vụ hiển thị. App của chúng ta có địnhg nghĩa "main": "app.js", ở trong package.json, vì vậy file app.js là dùng cho Browser Process.

Khi muốn tạo context menu, mình sẽ tạo sẵn một menu ẩn và hiển thị nó chỉ khi user click chuột phải. Context menu này sẽ được tạo ở Renderer Process bằng cách include một file js vào index.html

<script src="context.js"></script>

Bên trong file context.js sẽ là định nghĩa cho context menu.

'use strict';

var remote = require('remote');
var Menu = remote.require('menu');
var MenuItem = remote.require('menu-item');

var menu = new Menu();
menu.append(new MenuItem({
  label: 'ping',
  click: function() {
    console.log('ping');
  }
}));
menu.append(new MenuItem({
  type: 'separator'
}));
menu.append(new MenuItem({
  label: 'pong',
  type: 'checkbox', checked: true,
  click: function() {
    console.log('pong');
  }
}));

Cuối cùng là bind vào thao tác chuột của user

window.addEventListener('contextmenu', function (e) {
  e.preventDefault();
  menu.popup(remote.getCurrentWindow());
}, false);

alt text
Nếu bạn để ý thì ở file context.jsnói trên đã dùng một package tên là remote. Bạn sẽ tự hỏi tại sao lại cần remote ở đây.

Như đã nói ở trên thì context.js là thuộc Renderer Process, tuy nhiên khi dùng remote để gọi các package menumenu-item thì 2 package này sẽ là của Browser Process gọi sang. Như vậy phẩn xử lý của menumenu-item được giữ ở ngoài Renderer Process giúp phần xử lý render chỉ gồm những logic liên quan đến view, trở nên nhẹ nhàng và mượt hơn.

Kết

Ở phần tiếp mình sẽ nói tiếp về remote cụ thể hơn, cùng với cách đóng gói app và release.
Source code cho phần này bạn có thể tìm thấy ở link dưới đây :

////////////////////////////// context.js //////////////////////////////
'use strict';
var remote = require('remote');
var Menu = remote.require('menu');
var MenuItem = remote.require('menu-item');
var menu = new Menu();
menu.append(new MenuItem({
label: 'ping',
click: function() {
console.log('ping');
}
}));
menu.append(new MenuItem({
type: 'separator'
}));
menu.append(new MenuItem({
label: 'pong',
type: 'checkbox', checked: true,
click: function() {
console.log('pong');
}
}));
window.addEventListener('contextmenu', function (e) {
e.preventDefault();
menu.popup(remote.getCurrentWindow());
}, false);
////////////////////////////// app.js //////////////////////////////
'use strict';
var app = require('app');
var BrowserWindow = require('browser-window');
var Menu = require('menu');
var mainWindow = null;
app.on('window-all-closed', function() {
if (process.platform != 'darwin')
app.quit();
});
app.on('ready', function() {
createApplicationMenu();
openWindow();
});
var openWindow = function(){
mainWindow = new BrowserWindow({width: 800, height: 600});
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.on('closed', function() {
mainWindow = null;
});
}
var createApplicationMenu = function() {
var menuTemplate = [
{
label: 'Mdpreview',
submenu: [
{
label: 'Quit',
accelerator: 'Ctrl+Q',
click: function () {app.quit();}
}
]
}, {
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'Ctrl+R',
click: function() {
BrowserWindow.getFocusedWindow().reloadIgnoringCache();
}
},
{
label: 'Toggle DevTools',
accelerator: 'Alt+Ctrl+I',
click: function() {
BrowserWindow.getFocusedWindow().toggleDevTools();
}
}
]
}
];
var menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu)
}
view raw mdpreview.js hosted with ❤ by GitHub

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Mạnh Mẽ lên

7 bài viết.
29 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
47 6
(Ảnh) Flux trong giới Javascript không chỉ là chủ đề nổi tiếng nhất mà còn là chủ đề khó nắm bắt nhất. Bài viết này sẽ cố gắng giải thích một cách...
Mạnh Mẽ lên viết 3 năm trước
47 6
White
34 15
Electron và Atom (Ảnh) Các bạn có biết đến trình soạn thảo Atom của Github không nhỉ. Atom là một dự án mã nguồn mở khá giống Sublime nhưng có th...
Mạnh Mẽ lên viết hơn 3 năm trước
34 15
White
23 9
(Ảnh) Bạn có biết Javascript, ngôn ngữ lập trình web mà chúng ta vẫn sử dụng còn có một tên gọi khác là ECMAScript ? ECMAScript hiện nay không phả...
Mạnh Mẽ lên viết hơn 3 năm trước
23 9
Bài viết liên quan
White
51 8
Tăng sức mạnh cho javascript với lodash Lần này mình sẽ giới thiệu 1 thư viện javascript vô cùng bá đạo có tên là "lodash]1]", có thể nói nó là LI...
Huy Hoàng Phạm viết 3 năm trước
51 8
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
7 bài viết.
29 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!