当前位置 博文首页 > Echoyya、:Electron小白入门自学笔记(一)

    Echoyya、:Electron小白入门自学笔记(一)

    作者:Echoyya、 时间:2021-01-19 12:04

    码文不易啊,转载请带上本文链接呀,感谢感谢 https://www.cnblogs.com/echoyya/p/14297176.html

    一、从Hello Electron开始

    1. 创建一个空的文件夹,并创建入口 main.js 文件,index.html内容文件,

    2. 安装electron

      • npm init -y:初始化配置文件 package.json

      • npm i electron

    3. main.js 文件

      • 引入模块,创建应用

      • 创建窗口

      • 加载内容

      • 打开调试工具(可选)

      • 关闭窗口及应用监听

    4. 执行文件

      • 直接执行:electron main.js

      • 默认执行:electron .

      • package.json 添加执行脚本: "start": "electorn main.js", 执行:npm run start

      • 执行上述命令报错解决:先可尝试全局安装,在执行命令,如若仍然报错,可能需要配置脚本执行权限

      windows下运行*.ps1脚本(powershell的脚本)的时候,需要设置执行权限,PowerShell默认的执行策略就是Restricted,禁止任何脚本的执行。

      • 首先管理员身份运行 windows powershell ,输入Get-ExecutionPolicy ,用于获得当前的执行策略。

      • Set-ExecutionPolicy 命令设置/更改执行策略,选择RemoteSigned这个执行策略,这个策略既安全又可以执行本地编写的脚本

    // main.js  引入模块
    // app模块:控制应用的生命周期
    // BrowserWindow模块: 创建浏览器窗口
    const { app ,BrowserWindow} = require('electron');
    
    //  path模块: node 的内置模块,用于拼接路径
    const path = require('path');
    
    // 1.初始化应用之后,会触发监听ready 事件
    app.on('ready',ny_createWindow)
    
    let win;
    // 创建窗口
    function ny_createWindow(){
      // 1.1创建窗口
      win = new BrowserWindow({
        width:330,
        height:355,
        resizable:false, // 是否可改变宽高,默认true
        movable:false,   // 是否可拖拽,默认true
        webPreferences: {
          nodeIntegration: true, // 是否集成 Nodejs
          enableRemoteModule: true, // 是否允许渲染进程 调用主进程模块
        }
        // 1.为了在渲染进程中使用require(),还需要启用 nodeIntegration 。
        // 2.从v9版本开始,remote除非将 enableRemoteModule 设置为true,否则不允许在渲染进程中使用。
      });
    
      // 1.2 加载内容
      // win.loadURL('http://www.baidu.com')   // 远程
    
      // __dirname: 当前js文件所在的文件夹路径,绝对路径
      // win.loadURL(path.join(__dirname, './index.html')) // 本地 相对路径
    
      // mac 系统:需要拼接 file 协议
      // path.join('file://',__dirname,'./index.html')
    
      // 1.3 调试工具
      win.webContents.openDevTools(); // webContents: 控制和渲染页面的
    
      // 1.4 关闭窗口, 关闭窗口前想做的事
      win.on('close',function(){
        win = null;  // 关闭窗口
        app.quit();  // 关闭应用
      })
    
    

    二、制作设置菜单 Menu

    1. 创建menu.js ,引入模板,创建菜单模板

    2. 构建菜单(实例化一个菜单对象)

    3. 设置菜单对象到应用中

    4. 用到的方法:buildFromTemplate , setApplicationMenu

    5. 选项:

      • type:('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio')
      • label:标题
      • accelerator:快捷键,区分 mac 及 win
      • submenu:子菜单
      • click:点击事件
    6. main.js中引用: require('./menu');

    // menu.js  引入模板
    const { Menu } = require('electron')
    
    // 1.设置一个模板
    let template = [
      {
        label:'文件',
        submenu:[
          {
            label:'新建文件',
            accelerator:'ctrl+N',
            click:function(){
              console.log('new file')
            }
          },
          {
            type:'separator'
          },
          {
            label:'新建窗口',
            accelerator:(function(){
              if(process.platform =='darwin'){  //mac 基于darwin
                return 'alt+command+M'
              }else{ //win
                return 'alt+ctrl+M'
              }
            })(),
            click:function(){
              console.log('new window')
            }
          },
          {
            type:'separator'
          },
          {
            label:'自动保存',
            accelerator:'ctrl+S',
            type:'checkbox',
            checked:true,
            click:function(){
              console.log('saved')
            }
          },
        ]
      },
      {
        label:'编辑'
      },
    ]
    
    // 2. 构建菜单(实例化一个菜单对象) 
    const menu = Menu.buildFromTemplate(template);
    
    //3. 设置菜单对象到应用中
    Menu.setApplicationMenu(menu);
    
    

    三、主进程(Main Process)和渲染进程(Render Process)

    主进程

    在Electron中,入口是一个js文件,运行这个入口文件的进程称作主进程。

    (通常会是package.json里的main脚本,一般是main.js)

    在主进程使用BrowserWindow模块可以创建并管理web页面,也就是应用的GUI(图形界面)

    const { BrowserWindow } = require('electron');
    const path = require('path');
    
    // 主进程创建web页面
    let win = new BrowserWindow({...});
    
    // 加载本地文件
    // win.loadURL(path.join('file://',__dirname, './index.html'))  // mac
    win.loadURL(path.join(__dirname, './index.html'))
      
    

    渲染进程

    在主进程创建的每一个web页面也都运行着自己的进程,页面引入的js文件就属于渲染进程。

    渲染进程各自管理自己的页面,可以想象是浏览器的一个个的tab。

    electron核心可以分成2个部分,主进程渲染进程。主进程连接着操作系统和渲染进程,可以看做页面和计算机沟通的桥梁。渲染进程就是我们所熟悉前端环境了。只是载体改变了,从浏览器变成了window。传统的web环境我们是不能对用户的系统进行操作的。而electron相当于node环境,可以在项目里使用所有的node api 。

    简单理解:
    给web项目套上一个node环境的壳。

    四、在渲染进程中创建一个子窗口

    1. 创建渲染进程对应render.js文件

    2. 渲染进程引入BrowserWindow模块,需要借助于remote模块,

      • 渲染进程不能直接使用 BrowserWindow ,因为该模块默认是主进程允许使用的
      • 借助 remote ,从中引入主进程中的模块,需要在主进程窗口中配置 enableRemoteModule,允许渲染进程 调用主进程模块
    3. 并在index.html中引入render.js,两种引入方法及区别

      <!-- 1.引入render.js -->
      <script src="./render-process/render.js"></script>
       
      <!-- 2.electron 基于node -->
      <script>
          require('./render-process/render.js');
      </script>
        
      <--   
       区别:
       	src: 是全局变量
       	require: 引入的文件的最外层的变量,不是全局变量,注:为了在渲染进程中使用require(),还需在主进程窗口配置中启用 nodeIntegration 。
       	//main.js
           win = new BrowserWindow({
              width:330,
              height:355,
              resizable:false, // 是否可改变宽高,默认true
              movable:false,   // 是否可拖拽,默认true
              webPreferences: {
                    nodeIntegration: true, // 是否集成 Nodejs
                    enableRemoteModule: true, // 是否允许渲染进程 调用主进程模块
                }
           })    
        使用:
           1.元素绑定onclick事件 ==== src引入
           2.require  ==== 给元素绑定一个ID ,在render.js获取元素并绑定事件
      -->
      

    五、进程间通信

    在electron下,主进程与渲染进程相互通信要通过ipc(Inter-Process Communication),进程间通讯模块来完成,

    主进程与渲染进程调用的ipc模块是不一样的:

    • 主进程调用ipcMain

    • 渲染进程调用ipcRenderer

    A. 渲染进程 给 主进程 发送指令

    1. ipcRenderer模块:渲染进程引入,用于发送事件给主进程,和监听主进程返回的回复事件

      • const { ipcRenderer } = require('electron');

      • 发送事件:ipcRenderer.send('事件名称',传递的数据);

      • 监听事件:ipcRenderer.on('监听事件名称',接收的数据);

    2. ipcMain模块:主进程引入,用于接收渲染进程发送的事件并进行回复

      • const { ipcMain } = require('electron');

      • 监听事件:ipcMain.on('监听事件名称',接收的数据);

    index.html:

    <h1>Hello Electron!</h1>
    <button onclick="ny_click()">click me</button>
    
    <!-- 引入render.js 渲染进程-->
    <script src="./render-process/render.js"></script>
    

    render.js:

    function ny_click(){
      console.log('Render:','Echoyya')
      ipcRenderer.send('myName','Echoyya');
    }
    

    main.js:

    ipcMain.on('myName',function(event,msg){
      console.log('Main:',msg);
    })
    

    运行结果:主进程输出结果会打印在终端,而渲染进程输出结果会打印在调试工具中

    B. 主进程 给 渲染进程 发送指令

    了解了 渲染进程 -> 主进程 后,反之就很好理解和掌握了,大同小异,简单总结一下:

    1. main.js 发送指令 两种方式:

      ipcMain.on('myName',function(event,msg){
        // 1. 通过event 
        //event.sender.send('msg-b','程序媛');
        
        // 2. 通过webContents (推荐)
        win.webContents.send('msg-b','程序媛'); 
      })
      
    2. render.js 渲染进程接收指定

      ipcRenderer.on('msg-b',function (event, msg) {
      	console.log('Render:',msg)
      });
      

      运行结果

    C. 渲染进程 给 渲染进程 发送指令

    思路:渲染进程 -> 主进程 -> 渲染进程

    a.js: ipcRenderer.send('dataToMain','渲染进程 -> 主进程 -> 渲染进程')

    main.js:

    ipcMain.on('dataToMain',function(event,data){
    	win.webContents.send('dataToRender',data);
    })
    

    b.js:

     ipcRenderer.on('dataToRender', function (event, data) {
    	console.log(data)
     })
    

    D. 不同渲染进程之间数据共享

    1. 可以很简单的使用H5的api来完成,如localStorage,sessionStorage,但今天要说的是另一种

    2. 在主进程中将一个对象储存为全局变量,然后通过remote模块操作

      • 创建a.js , b.js,并在index.html中引入

    index.html:

    <button >改变数据</button>
    <button >获取数据</button>
    	
    <script>
    	require('./render-process/a.js');
    	require('./render-process/b.js');
    </script>
    

    main.js:

    // 全局变量
    global.shareObject = {
      name:'上海'
    }
    

    a.js:

    const remote = require('electron').remote;
    
    let btn1 = document.getElementById('btn1');
    
    btn1.onclick = function(){
      
      remote.getGlobal('shareObject').name = '北京';
      
      console.log('has changed');
    
    }
    

    b.js:

    const remote = require('electron').remote;
    
    let btn2 = document.getElementById('btn2');
    
    btn2.onclick = function(){
    
      let msg = remote.getGlobal('shareObject').name
    
      console.log(msg)
    
    }
    

    六、提示框 dialog 模块

    1. 首先dialog模块是主进程可使用模块

    2. 调用语法:dialog.showMessageBox({ ... }),版本升级后不支持原来的回调方法,改为返回promise对象

    3. 常用配置对象参数:

      • type:类型(error/info)
      • title:标题
      • message:提示信息
      • icon:本地图标(需使用nativeImage模块,且主进程与渲染进程均可用该模块)
      • buttons:按钮(数组类型)
    const { dialog ,nativeImage} = require('electron');
    const path = require('path');
     
    // 1.信息对话框
    dialog.showMessageBox({
      title:'温馨提示',
      message:'XXXXX XXXXX XXXXX XXXXX XXXXX',
      buttons:['Yes','No'],
      icon:nativeImage.createFromPath(path.join(__dirname,'../src/img/icon1.png'))
    }).then(function(index){
      if(index.response == 0){ // 点击了Yes按钮
        console.log('I want you !');
      }else{ // 点击了No按钮
        console.log('no no no');
      }
    });
    
    // 2.错误提示框
    dialog.showErrorBox('1213','访问错误')
    

    七、打包(electron-packager)

    打包必要元素及格式输入:electron-packager <应用目录> <应用名称> <打包平台> --out=<输出目录> <架构> <应用版本> <忽略文件> <图标> --overwrite

    执行上述命令,可在输出目录中,打包成功一个exe 可执行文件,此命令区分mac及win,设备原因,此处仅演示win系统打包,mac系统的同学,需自行查找相关资料!!!

    package.json:

    "scripts": {
    	"start": "electorn main.js", 
    	"pack":"electron-packager ./  test --platform=win32 --out=./dist --arch=x64 --app-version=1.0.0 --ignore=node_modules --icon=./src/img/hrbb.ico --overwrite "
    },
    

    下一篇:没有了