Electron桌面应用开发基础

这篇具有很好参考价值的文章主要介绍了Electron桌面应用开发基础。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Electron桌面应用开发

Electron特点

Electron 是一种基于 Chromium 和 Node.js 的开源框架,可以用于快速构建跨平台的桌面应用程序。与传统的桌面应用程序不同,Electron 应用程序使用 HTML、CSS 和 JavaScript 技术 栈来实现界面设计和业务逻辑,并且具有良好的跨平台性能和扩展性。

跨平台性:Electron 可以在 Windows、Mac 和 Linux 等多个平台上运行。它通过使用 web 技术栈来实现界面设计和业务逻辑,从而实现了跨平台的一致性和可移植性。同时,由于 Electron 底层使用 Chromium 和 Node.js,也可以很方便地使用各种第三方库和插件。

灵活性:Electron 提供了很多自定义选项和 API 接口,可以满足各种定制化需求。例如,可以自定义菜单、对话框和图标等界面元素,还可以访问系统文件和网络资源等底层功能。

生态圈支持:Electron 在 GitHub 上拥有庞大的社区和生态圈,提供了很多开源项目和插件,可以快速开发出高质量的桌面应用程序。同时,Electron 也得到了很多知名公司和开发者的支持,如 Slack、GitHub Desktop、VS Code 等。

性能问题:由于 Electron 应用程序需要同时运行 Chromium 和 Node.js,因此在启动速度、内存占用和性能优化等方面可能存在一些问题。但是,通过合理的代码设计和优化,可以很好地解决这些问题。

总之,Electron 是一种灵活、可扩展、跨平台的桌面应用程序开发框架,具有良好的生态圈和社区支持。对于前端开发人员来说,它提供了一种全新的开发方式和编程思路,为构建高质量的桌面应用程序提供了更多的便利和选择。

Electron技术架构

地址:快速入门 | Electron

  • Chromium 支持最新特性的浏览器
  • Node.js Javascript运行时,可实现文件读写
  • Native APIS 提供统一的原生界面能力

环境搭建

  1. Node 安装 (我的版本14.15.0)
  2. 项目初始化
    npm init -y
    // 安装Electron 
    npm i --save-dev electron
    // 创建main.js 并在package.json中设置为入口
    "main":"main.js"
    // 创建index.html 用来书写页面内容
    
  3. 初始化代码

    package.json

    {
      "name": "myElectron",
      "version": "1.0.0",
      "description": "",
      "main": "main.js",
      "scripts": {
        "start": "nodemon --watch main.js --exec npm run build",
        "build": "electron ."
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "electron": "^24.4.0"
      },
      "dependencies": {
        "@electron/remote": "^2.0.9"
      }
    }
    

    main.js

    const { app, BrowserWindow } = require( 'electron' )
    // app 哪个控制应用程序的事件生命周期
    // BrowserWindow   创建和管理应用程序Windows 
    const createWindow = () => {
      let mainWin = new BrowserWindow( {
        width: 800,
        height: 600,
        show: false,
        backgroundColor: 'aqua',
    	} )
      mainWin.loadFile( 'index.html' )
      mainWin.on( 'ready-to-show', () => {
        mainWin.show()
      	} )
      mainWin.on( 'close', () => {
        mainWin = null
      	} )
    }
    app.on( 'ready', () => {
      createWindow()
    } )
    

生命周期事件 // 执行顺序如下

  • ready: app初始化完成

  • dom-ready: 一个窗口中的文本加载完成

  • did-finsh-load: 导航完成时触发

  • closed:当窗口关闭时触发,此时应删除窗口引用

  • window-all-closed: 所有窗口关闭时触发

  • before-quit: 在关闭窗口之前触发

  • will-quit: 在窗口关闭并且应用退出时触发

  • quit: 当所有窗口被关闭时触发

  • 
     mainWin.webContents.on( 'did-finish-load', () => {
        console.log( '333-did-finish-load' );
      } )
      // 窗口中文本加载完成
      mainWin.webContents.on( 'dom-ready', () => {
        console.log( '222dom-ready' );
      } )
      // 主窗口关闭
      mainWin.on( 'closed', () => {
        console.log( '88888-事件发生' );
      } )
    
    app.on( 'window-all-closed', () => {
      console.log( '444-window-all-closed' );
      if ( process.platform !== 'darwin' ) app.quit()
    } )
    app.on( 'ready', () => {
      console.log( '111- app初始化完成' );
      createWindow()
    } )
    
    app.on( 'before-quit', () => {
      console.log( '555-before-quit' );
    } )
    app.on( 'will-quit', () => {
      console.log( '666-will-quit' );
    } )
    app.on( 'quit', () => {
      console.log( '777-quit' );
    } )
    

窗口设置

const mainWin = new BrowserWindow( {
    x: 100,  //x y 窗口开始位置
    y: 100,   
    show: false,
    width: 800,
    height: 600,
    minHeight: 400, // min max 最小最大宽高
    minWidth: 50,
    maxHeight: 1000,
    maxWidth: 1200,
    resizable: false, // 窗口是否可调整
    minimizable: true,
    maximizable: true,
    title: '桌面应用',
    frame: false,
    // autoHideMenuBar: true,
    webPreferences: {
      nodeIntegration: true,  // 运行渲染进程使用node
      enableRemoteModule: true,
      contextIsolation: false
    }
  } )
  require( '@electron/remote/main' ).initialize()
  require( "@electron/remote/main" ).enable( mainWin.webContents )

窗口标题及环境

  • 标题配置

    1. 优先读取index.html中的title
    2. index.html中不设置得情况下 可以读取 new BrowserWindow 中配置的title
  • 图标修改
    icon

  • frame 是否显示默认导航菜单 + 标题

  • transparent 设置透明

  • autoHideMenuBar 是否隐藏 导航菜单

  • 点击打开新窗口
    备注: 在main中运行时是主进程 在index.html中运行时是渲染进程
    app BrowserWindow 都属于主进程得模块
    出于安全考虑 渲染进程中没有办法使用require 可在main中配置
    渲染进程不允许直接使用主进程模块 通过remote进行调用
    electron 12 之后就已经废除了 remote
    // 替换为:
    const { BrowserWindow } = require('@electron/remote')

// 在主进程中:
require('@electron/remote/main').initialize()

自定义窗口实现

  1. 渲染进程中获取 主进程窗口实例
    let mainWin = remote.getCurrentWindow()
  2. 获取各个按钮
    var btnGroup = document.getElementsByClassName( 'btnGroup' )[0].getElementsByTagName( 'button' )
  3. 是否最大判断
    mainWin.isMaximized()
  4. 最大化
mainWin.maximize()
// 最大化还原
mainWin.restore()
  1. 最小化
mainWin.minimize()
 // <div class="btnGroup">
 //   <button>最小</button>
 //   <button>最大</button>
 //   <button>关闭</button>
 // </div>
 
 // 获取按钮组
  var btnGroup = document.getElementsByClassName( 'btnGroup' )[0].getElementsByTagName( 'button' )
  btnGroup[0].addEventListener( 'click', () => {
    if ( !mainWin.isMinimized() ) {
      mainWin.minimize()
    }
  } )
  btnGroup[1].addEventListener( 'click', () => {
    console.log( '最大化', mainWin.isMaximized() );
    if ( !mainWin.isMaximized() ) {  //  判断窗口是否最大化
      mainWin.maximize()  // 最大化
    } else {
      mainWin.restore()
    }
  } )
  btnGroup[2].addEventListener( 'click', () => {
    mainWin.close()
  } )

阻止窗口关闭

window.onbeforeunload = function() {
return false
}

动态创建菜单

  1. 准备模板
let menuArr = [{label:'打开',type:'normal',role:'copy'}]
  1. 利用模板生成菜单
let menu = Menu.buildFromTemplate( menuArr )
  1. 添加到应用
Menu.setApplicationMenu( menu )
let temp = [
  {
    label: 'send',
    click () {
      BrowserWindow.getFocusedWindow().webContents.send( 'msg2', '主进程发来消息' )
    }
  }
]

let tem = Menu.buildFromTemplate( temp )
Menu.setApplicationMenu( tem )


// <button id="selfMenu">自定义菜单</button>
  // <input type="text" value="" id="inputText">
  // <button id="addMenu">加入新增菜单</button>

1. 找到  Menu  MenuItem
2. new Menu()  可以将  new MenuItem() 创建的菜单进行添加到菜单栏中

let remote = require( '@electron/remote' )
let Menu = remote.Menu
let MenuItem = remote.MenuItem
window.addEventListener( 'DOMContentLoaded', () => {
  // 获取按钮-- 自定义菜单
  let selfBtn = document.getElementById( 'selfMenu' )
  let inputVal = document.getElementById( 'inputText' )
  let addMenu = document.getElementById( 'addMenu' )
  let selfMenuItem = new Menu()
  selfBtn.addEventListener( 'click', () => {
    let menuFile = new MenuItem( { label: '文件', type: 'normal' } )
    let menuEdit = new MenuItem( { label: '编辑', type: 'normal' } )
    let menuSelf = new MenuItem( { label: '自定义菜单', submenu: selfMenuItem } )
    let menu = new Menu()
    menu.append( menuFile )
    menu.append( menuEdit )
    menu.append( menuSelf )
    Menu.setApplicationMenu( menu )
  } )

  addMenu.addEventListener( 'click', () => {
    let content = inputVal.value.trim()
    if ( content ) {
      selfMenuItem.append( new MenuItem( { label: content, type: 'normal' } ) )
      content = ''
    }
  } )
})

右击弹出菜单

  1. 创建菜单

  2. 监听contextmenu 事件 并阻止默认行为

  3. menu.popup({window:remote.getCurrentWindow()})

     // 右键菜单
      let rightMenu = [
        {
          label: 'Run Code',
          type: 'normal'
        },
        {
          label: '刷新',
          role: 'refresh'
        },
        {
          type: 'separator'
        },
        {
          label: '其他功能',
          click () {
            console.log( '其他功能已执行' );
          }
        }
      ]
      let menuRight = Menu.buildFromTemplate( rightMenu )
      window.addEventListener( 'contextmenu', ( e ) => {
        e.preventDefault()
        menuRight.popup( {
          window: remote.getCurrentWindow
        } )
      } )
    

主进程与渲染进程通信

  1. ipcRender(on send) ipcMain( on ) 两个进程之间通信
- ipcMain  内部  e.sender.send('xx',xxx)
- ipcMain  内部接收 e.returnValue
  1. BrowserWindow.getFocusedWindow().webContents.send('mtp',来自于主进程的消息) // 依赖按钮之类的事件触发‘

  2. mainWin.contents.openDevtools() // 打开控制台

    // main.js
    let { app, BrowserWindow, ipcMain } = require( 'electron' )
    ipcMain.on( 'msg1', ( e, ev ) => {
      console.log( e, ev );
      e.sender.send( 'msg2', 666 )
      // BrowserWindow.getFocusedWindow().webContents.send( 'msg2', 666 )
    } )
    
    // index.js
    let remote = require( '@electron/remote' )
    let { ipcRenderer } = require( 'electron' )
    window.addEventListener( 'DOMContentLoaded', () => {
      console.log( 666 );
      ipcRenderer.send( 'msg1', '渲染进程发来贺电' )
      ipcRenderer.on( 'msg2', ( e, ev ) => {
        console.log( e, ev );
      } )
    } )
    
    

localtorage通信

  1. 获取主窗口id
- BrowserWindow  实例属性  id
  1. 子窗口设置ID
- BrowserWindow.fromId(mainWin.id)
  1. 通信的时候存储 信息到localStorage中

  2. 新窗口打开时取值并使用

    // main.js
    ipcMain.on( 'msg', ( e, data ) => {
        if ( data ) {
          // 开启第二个窗口
          let sub2 = new BrowserWindow( {
            parent: BrowserWindow.fromId( mainId ),
            width: 300,
            height: 150,
            webPreferences: {
              nodeIntegration: true,
              enableRemoteModule: true,
              contextIsolation: false
            }
          } )
          sub2.loadFile( 'sub.html' )
          sub2.on( 'close', () => {
            sub2 = null
          } )
        }
      } )
      // 主进程接收窗口二的信息
      ipcMain.on( 'toMain', ( e, data ) => {
        // 将数据转发给index进程
        let mainOpen = BrowserWindow.fromId( mainId )
        mainOpen.webContents.send( 'win2', data )
      } )
    
    // index.js
    let remote = require( '@electron/remote' )
    let { ipcRenderer } = require( 'electron' )
    
    window.addEventListener( 'DOMContentLoaded', () => {
    
      // 获取打开窗口按钮
      let btnOpen = document.getElementById( 'openTwo' )
      btnOpen.addEventListener( 'click', () => {
        localStorage.setItem( 'name', '张三' )
        ipcRenderer.send( 'msg', true )
      } )
      ipcRenderer.on( 'win2', ( e, data ) => {
        console.log( 'index进程已经接收到', data );
      } )
    } )
    

渲染进程之间通信

  1. 主进程 A 渲染 B渲染
  2. A给B发生数据 ipcRender.send
  3. B接收 ipcRender.on
  4. B给A发数据 先发送给 主进程 主进程再发送给 A
  5. 注意: 主进程发送时不能直接使用BrowsserWindow.getFocusedWindow().webContents.send('mtp',来自于主进程的消息)
    因为当前焦点窗口不一定时主进程窗口

dialog模块

  • dialog模块: 主进程模块 在渲染进程中使用remote.diaog 调用对应触发得窗口api
  • 配置:
    remote.dialog.showOpenDialog( {
    defaultPath: __dirname,
    buttonLabel: '请选择',
    title: '高傲的狼',
    properties: ['openFile', 'multiSelections'],
    filters: [
    { name: '代码文件', extensions: ['js', 'html', 'json'] },
    { name: '图片文件', extensions: ['ico', 'jpeg', 'png'] },
    { name: '媒体文件', extensions: ['mp3', 'mp4', 'avi'] },
    ]
    } ).then( res => {
    console.log( res );
    } )

shell 打开url或者路劲

  1. shell.openExternal(url) 默认浏览器打开
  2. shell.showItemInFolder() 在桌面引用中打开

消息提示

  • option = {
    title:'高傲的狼',
    body:'你好哇,小家伙',
    icon:'./xxx.ico'
    }
  1. window.Notification(
option.title,option

)文章来源地址https://www.toymoban.com/news/detail-477028.html

快捷键

  1. 注册
globalShortcut('ctrl + q')  // 返回布尔值  true/false
  1. 判断是否注册过
globalShortcut.isRegistered('ctrl + q')
  1. 注销快捷键
- 时机 -- 在生命周期 will-quit中进行注销
- globalShortcut.unregister('ctrl + q')

剪切板模块

  1. clipboard 模块
- writeText
- readText
  1. 图片复制 粘贴
    1. let img = nativeImage.createFromPath( './女孩.jpg' )
      2. clipboard.writeImage( img )
// 将剪贴版中图片写到DOM中
3. let oimg = clipboard.readImage()
4. let imgDom = new Image()
5. imgDom.src = oimg.toDataURL()
6. document.body.appendChild( imgDom )

到了这里,关于Electron桌面应用开发基础的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue.js + Electron 的跨平台桌面应用程序开发

    本文介绍了 Vue.js 和 Electron 的基本特点和原理,并分析了它们在桌面应用程序开发中的优势和应用场景。在基于 Vue.js 和 Electron 的桌面应用程序开发实践中,本文详细介绍了项目的搭建和配置,包括环境的准备、项目的初始化和依赖的安装等步骤。然后,本文介绍了使用 Vu

    2024年02月13日
    浏览(104)
  • 跨平台的桌面应用程序开发框架Electron | 开源日报 0906

    Stars: 109.3k License: MIT Electron 是一个基于 Node.js 和 Chromium 的开源框架,允许使用 JavaScript、HTML 和 CSS 编写跨平台的桌面应用程序。它被 Atom 编辑器等众多应用程序所采用。该项目具有以下核心优势: 跨平台:Electron 提供了 macOS、Windows 和 Linux 三个主要操作系统的二进制文件。

    2024年02月09日
    浏览(60)
  • 如何查看桌面应用app是不是基于electron/webui开发

    Typora 是一个优秀的基于markdown的笔记软件,那么它是怎么实现 markdown 文本文件 到可视化界面的呢 ? 以 mac 平台为例,我们在下载安装后,可以在如下目录找到它。 依旧以 Typora 为例,这里我们继续点开可以发现 Typora 的 Content/Resources/TypeMark/appsrc 目录下存在大量的 js 文件,

    2024年02月12日
    浏览(37)
  • 使用electron-vite +Vue+ElementPlus开发跨平台桌面应用

    我们的项目是基于Elasticsearch来进行数据的存储与查询的,使用过ES的朋友应该都比较清楚,现在还没有一个比较友好的ES的桌面客户端软件可以和MySQL的桌面客户端软件媲美的,使用ES起来非常麻烦,经常会被吐槽的三个点: 资深测试吐槽:为什么技术选型要选择ES,增删改查

    2023年04月09日
    浏览(92)
  • electron应用重启,开机自启动(electron开发常用的方法、优化方案)

    不会了一定先去参考官网:electron官网 主进程中监听 页面中调用 如果不启用非开发环境的话,开发者电脑开机会出现:To run a local app, execute the following on the command line: 弹框,解决方法就是开发环境不启用开机自启动,代码如上 思路:用nodejs去先定时重启应用,在杀死对应软

    2024年02月12日
    浏览(37)
  • 安卓程序开发——widget组件开发Widget就是可以放在桌面上的组件,包括像天气、便签、等。AppWidget 框架类练习Widget组件的基础应用、widget的配置、widget与服务结合实现

       掌握Android  widget组件的应用,练习Widget组件的基础应用、widget的配置、widget与服务结合实现时间倒计时 1.创建一个Android 应用,练习widget的基础用法。 2.在布局文件添加TextView ImageButton两个控件 3.在res下创建xml文件夹,再创建widget_template.xml元数据 4.添加WidgetProvider.java文件

    2024年02月20日
    浏览(39)
  • 桌面应用开发有哪些主流框架?

    受益于开源技术的发展,以及响应快速开发的实际业务需求,跨平台开发不仅限于移动端跨平台,桌面端虽然在市场应用方面场景不像移动端那么丰富,但也有市场的需求。 相对于个人开发者而言,跨平台框架的使用,主要为了满足以下三个主要能力: 生产力提升 :框架能

    2024年02月05日
    浏览(40)
  • C# 开发桌面应用简单介绍

    一. C#使用场景介绍 C#是微软公司发布的一种由C和C++衍生出来的面向对象的编程语言、运行于.NET Framework和.NET Core(完全开源,跨平台)之上的高级程序设计语言。 二. 开发流程 1. 创建项目:打开Visual Studio后右侧选择“创建新项目”,然后选择“C# Windows窗体应用”即可创建桌

    2024年02月05日
    浏览(57)
  • vue开发桌面exe应用

    Electron-vue Electron-vue搭建vue全家桶+Element UI客户端(一) 如何使用Vue.js构建桌面应用程序

    2024年02月10日
    浏览(44)
  • 如何使用Python进行桌面应用开发?

    Python提供了多个库和框架来进行桌面应用开发。以下是使用Python进行桌面应用开发的常用方法之一: PyQt:PyQt是一个用于开发跨平台桌面应用的Python库,它提供了丰富的GUI组件和工具。以下是使用PyQt创建桌面应用的基本步骤: a. 安装PyQt库:使用pip命令安装PyQt库,例如: p

    2024年02月17日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包