Electron开发要点
RoderickQiu
2019-01-24 17:43:56
还是想起来做一份electron开发要点录,不知道做不做得全。
包括一切Electron开发中可能用到的东西,诸如node,javascript或者bootstrap。
不时会来更新一下。
------
# 0. 资料大全
- https://blog.avocode.com/4-must-know-tips-for-building-cross-platform-electron-apps-f3ae9c2bffff (need proxy)
- https://electronjs.org/docs
- https://getbootstrap.com/docs/4.2/getting-started/introduction/
- http://www.fontawesome.com.cn/faicons/
- https://api.jquery.com/
# 1. 允许自动播放音频
在Chrome的新版本里面,自动播放音频被禁止了。因而基于Chromium的Electron中也就是一样的了。
解决方案:
```javascript
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');// 允许自动播放音频
```
在主进程中使用。
# 2. electron-store获取布尔值时的注意事项
```javascript
if (store.get("top") == true || store.get("top") == undefined) win.setAlwaysOnTop(true)
```
当你的项目还未定义时,其值为*undefined*,**特判永远重要**。
**附录:**
- `store.get("name")`获取值
- `store.set("name","val")`设置值
- `store.delete("name")`删除值
# 3. 菜单
无论是顶栏菜单还是右键菜单(有框窗口的),在打包之后都会消失不见。因此我们需要自己设置。
如:
```javascript
if (process.platform === 'darwin') {
var template = [{
label: 'wnr',
submenu: [{
label: 'Quit',
accelerator: 'CmdOrCtrl+Q',
click: function () {
app.quit();
}
}]
}, {
label: 'Edit',
submenu: [{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
selector: 'undo:'
}, {
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
selector: 'redo:'
}, {
type: 'separator'
}, {
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
selector: 'cut:'
}, {
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
selector: 'copy:'
}, {
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
selector: 'paste:'
}, {
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
selector: 'selectAll:'
}]
}];
var osxMenu = menu.buildFromTemplate(template);
menu.setApplicationMenu(osxMenu);
}
```
可以设置Content Menu。
# 4. 主进程中对于win的控制
```javascript
if (win != null) {
win.reload()
}
```
设置win之前从来都要判断win存不存在,类似的,在yDic中查询显示一本词典中的某个值如音标前要判断是否有音标,免得出事情。
# 5. 对于预设函数
```javascript
function (response, checkboxChecked) {
if (checkboxChecked) {
shell.openExternal("https://github.com/RoderickQiu/wnr/releases/latest");
}
})
```
纵使function的第一个位置的变量并没有用,也要放在那里占位,否则就是对函数的错误重载。
当然,如果官方提供了重载,那就是再好不过了。
# 6. 打包之后文件位置更换问题
```javascript
tray = new Tray('./res/icons/iconWin.ico')
```
当我未打包时,此程序运行正常;当我已打包时,则此程序运行错误。
```javascript
const path = require('path')
tray = new Tray(path.join(__dirname, '/res/icons/iconWin.ico'))
```
调用node的path功能才是正确姿势。
# 7. devDependencies & dependencies
```json
"dependencies": {
"electron-store": "^2.0.0",
"request": "^2.88.0",
"cheerio": "^1.0.0-rc.2"
},
"devDependencies": {
"electron": "^4.0.2",
"electron-builder": "^20.38.5"
},
```
electron和electron-builder等在打包后就不再需要的东西属于devDependencies。
# 8. electron-builder的设置
```json
"build": {
"win": {
"target": ["dir"],
"icon": "res/icons/iconWin.ico"
}
}
```
- target要设置成dir,因为我们还要放东西进去的,现在编译白费力气。
- icon要设置,否则就是electron默认icon了。
# 9. 同一个HTML文件中不能两次引用同一个node库或建立同名变量
```markup
<script src="updater.js"></script>
<script>
var ipc = require('electron').ipcRenderer;
function about() {
ipc.send("about");
}
</script>
```
当updater.js中也`var ipc = require('electron').ipcRenderer`时,以上代码非法。
# 10. input元素只允许输入数字
```markup
<input name="loop" id="loop" placeholder="loop for how many times" type="number" onkeypress="return (/[0-9]/.test(String.fromCharCode(event.keyCode)))" style="ime-mode:Disabled" class="small" required />
```
主要的有效代码是`onkeypress="return (/[0-9]/.test(String.fromCharCode(event.keyCode)))" style="ime-mode:Disabled"`。
# 11. js为html元素赋值时位置的关系
```markup
<span id="wordTitle"></span>
<script>
$("#wordTitle").val("Example");
</script>
```
script元素必须加载在html元素的后面,否则将会赋值失败。当然,我们也可以使用`$(document).ready(function(){...});`。
还有以下需要注意:
- `$("#wordTitle")`中的#不能忘,否则就不是id而是标签了。
- `.val()`适用于input,对于其他元素,应使用`.html()`。
# 12. style覆盖
```markup
<link rel="stylesheet" type="text/css" href="res/lib/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="style.css" />
```
有时bootstrap中的一些量并不合适,这时候我们可以再放一个style在下面,覆盖掉bootstrap的样式。
注意一定只能放在下面。
# 13. jQuery选择器和Electron冲突
```markup
if (typeof module === 'object') { window.module = module; module = undefined; }
```
在Electron中使用jQuery会遇到`$`的冲突情况,在此时这段神器代码将会发挥功用。
# 14. Electron的relaunch
```javascript
ipcMain.on('relauncher', function () {
app.relaunch();
app.exit(0)
})
```
需要注意的是部分Electron功能并没有想象中那么简单。如`relaunch()`就不能直接使程序重启,而只是注册了重启事件,还是需要先关闭程序,重启事件才会运行。
# 15. HTML获得GET传递值
```javascript
var $_GET = (function () {
var url = window.document.location.href.toString();
var u = url.split("?");
if (typeof (u[1]) == "string") {
u = u[1].split("&");
var get = {};
for (var i in u) {
var j = u[i].split("=");
get[j[0]] = j[1];
}
return get;
} else {
return {};
}
})();
var title = decodeURI($_GET['title']);
```
以上的代码可以获取`index.html?title=example`中的example。
# 16. setInterval并不能真正暂停代码运行
```javascript
var int;
function ender() {
window.clearInterval(int);
$("#work-rest").text("");
$("#now-timing").text("End!");
warninggiver(0);
isclockworking = 0;
$("#stopper").text("");
}
function clock() {
t = new Date().getTime();
if (method == 1) seconds = parseInt((worktime - t + starttime) / 1000);
else seconds = parseInt((resttime - t + starttime) / 1000);
if (seconds > 0) {
hours = parseInt(seconds / 3600);
minutes = parseInt((seconds - hours * 3600) / 60);
seconds = seconds - hours * 3600 - minutes * 60;
$("#now-timing").text(hours + "h " + minutes + "min " + seconds + "s");
} else {
times++;
if (times < loop * 2) {
starttime = new Date().getTime();
themechanger();
} else if (times == loop * 2) {
ender();
}
}
}
int = self.setInterval("clock()", 10);
minimizer();
```
以上的代码会让`clock()`在一段时间中每隔10ms运行一次,但并不会在`clock()`停止运行之前不运行`minimizer()`。
正确的方式是:
```javascript
var x = self.setInterval("y()", 1000);
function y(){
window.clearInterval(x);
z();
}
```
这段代码将会停止一秒(此处1000为毫秒,显然是个为了和时间戳保持单位相同而采取的举措),然后再去运行`z()`。
# 17. Electron在外部打开网页
```markup
<a href="javascript:require('electron').shell.openExternal('https://roderickqiu.scris.top/')" class="rest">Roderick Qiu</a>
```
`shell.openExternal(link)`方法可以在外部打开网页。
# 18. 关于表单的样式
表单的样式默认的一般都不好看,因此搜索“名称+美化”寻找解决方案是必然。
如:
```css
input{
display: inline-block;
line-height: inherit;
margin: 0rem;
padding: 1px 0px;
outline: none;
border: none;
}
input::-webkit-outer-spin-button, input::-webkit-inner-spin-button{
-webkit-appearance: none;
}
input::-webkit-input-placeholder {
color: #999999;
transition: color.5s;
}
input:focus::-webkit-input-placeholder, input:hover::-webkit-input-placeholder {
color: #999999c2;
transition: color.5s;
}
```
以上代码可以帮助建立一个纯净的,只有输入框,且选中时其提示文本会颜色变淡的number型input元素,就像wnr中使用的那个一样。
# 19. flex布局居中的注意事项
全局设置:
```css
html, body{
width: 100%;
min-height: 100%;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
align-items: center;/* center in v/h */
}
```
html:
```markup
<body class="mx-auto flex-column">
<main role="main" class="flex-shrink-0 align-content-center">
<div class="container-fluid text-center">
...
</div>
</main>
</body>
```
以上方案虽不是最好的,但是绝对能用。
如果在布局中有需要固定位置的元素,css里添加个类,`position: absolute`解决一切问题。
# 20. CSS中使用@media标签进行响应式控制
```css
#footer{
position: absolute;
bottom: 5px;
text-align: center;
}
@media(max-height:600px){
#footer{
position: relative;
}
}
```
则在高度比较大时,footer固定在底部;高度比较小的时候就不固定了以免和正文挤在一起。
# 21. 无边框窗口的拖动问题
- 对于`html, body`,`-webkit-app-region: drag;/* let the app draggable */`。
- 对于内容元素,`-webkit-app-region: no-drag;/* let it clickable */ -webkit-user-select: text;`。
- 对于UI,`-webkit-app-region: no-drag;/* let it clickable */ -webkit-user-select: none;`。
# 22. Electron设置任务栏进度条的方式
```cpp
ipcMain.on("progress-bar-set", function (event, message) {
if (win != null) win.setProgressBar(1 - message)
})
```
需要说明的是win.setProgressBar(-1)可以清除进度条,此时message应该设置为2。
# 23. Electron安装慢的解决方案
[链接](https://www.jianshu.com/p/2f07642bfe7e)
# 24. Electron等node扩展安装时没有权限的问题
一般来讲,关掉杀软和ide,用管理员命令行可以解决。
`--verbose` 大法好。
# 25. 只允许同时运行一个程序
```javascript
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) app.quit()// 只允许同时运行一个wnr
```
# 26. Asar-Unpack
```
"build": {
"asarUnpack": [
"./node_modules/node-notifier/vendor/**"
],
}
```
------
差不多就是以上了。