2024年Electron条记_browserwindow 初始状态,HarmonyOS鸿蒙经典面试题 ...

打印 上一主题 下一主题

主题 551|帖子 551|积分 1653

深知大多数步伐员,想要提升技能,往往是本身探索成长,但本身不成体系的自学效果低效又漫长,而且极易碰到天花板技术故步自封!



既有得当小白学习的零基础资料,也有得当3年以上履历的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开辟知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习条记、源码课本、实战项目、大纲门路、讲解视频,并且后续会持续更新
需要这份体系化的资料的朋侪,可以戳这里获取
})
}
// 窗口加载和关闭
app.on(‘ready’, createWindow)
app.on(“window-all-closed”, () => {
console.log(“window-all-closed”)
app.quit()
})
  1. ## 窗口标题及环境(创建窗口)
  2. >
  3. > 这里要说明一下,低版本直接可以使用一个remote,主进程稍微配置一下就能创建窗口了,高版本就不行了,高版本需要安装一个@electron/remote模块,通过对这个模块稍微配置一下也能创建窗口了,本人之前版本是`"electron": "^26.0.0","@electron/remote": "^2.0.11"`,[具体配置可以可以看看这个小哥的博客](https://bbs.csdn.net/topics/618636735),我下面的代码和这两个不一样我是在主进程创建窗口,渲染进程向主进程发请求才能创建窗体(下面代码示例就是这个方法),因为方式和另两种不一样,因此记录一下
  4. >
  5. >
  6. >
  7. **ctrl+r 可以刷新当前窗口的index.html样式,ctrl+shift+i可以打开调试窗口**
  8. **这里强调一下main.js为主进程,创建的js里面重新创建的窗口为渲染进程**
  9. **主进程main.js代码如下**
复制代码
const { app, BrowserWindow, ipcMain } = require(“electron”) // ipcMain用于渲染进程创建窗体使用
const createWindow = () => {
// 创建窗口
let win = new BrowserWindow({
x: 100,
y: 50, //窗体坐标
webPreferences: {
nodeIntegration: true,
contextIsolation: false, //加入这两行代码就可以正常使用require了,不会报错了
}
})
//当前窗口显示的页面
win.loadFile(“index.html”)
// 窗口关闭
win.on(‘close’, () => {
console.log(‘close’)
win = null
})
}
// 窗口加载和关闭
app.on(‘ready’, createWindow)
app.on(“window-all-closed”, () => {
console.log(“window-all-closed”)
app.quit()
})
// 下面代码就是创建渲染进程窗体代码
// 在主进程中监听渲染进程的请求
// open-window后面的回调函数,参数一默认是事件对象,参数二为渲染进程传递来的数据
// pageFileName为ipcRenderer.send()的第二个参数,ipcRenderer.send()由渲染进程发起,参数一为事件名,参数二为页面配置(巨细,位置等等)
ipcMain.on(‘open-window’, (event, winconfig) => {
console.log(‘winconfig’, winconfig)
// 创建新窗口并设置相应的配置(配置由渲染进程提供)
let newWindow = new BrowserWindow(winconfig)
// 这里设置的是winconfig.pageFileName,所以渲染进程的请求的配置中必须pageFileName代表页面
newWindow.loadFile(winconfig.pageFileName)
// 监听创建的窗体关闭事件
newWindow.on(‘close’, () => {
console.log(‘close’)
newWindow = null
})
})
  1. **主进程页面index.html代码**
复制代码
萧寂 窗口标题

打开第一个新窗口 打开第二个新窗口
  1. **渲染进程index.js代码**
复制代码
// 这里强调一下main.js为主进程,窗口内里页面点击创建的js内里重新创建的窗口为渲染进程
// require直接使用会报错,由于electron是不被允许直接require的,不给这个权限,需要我们自行放开
// 权限需要在窗口的配置定义webPreferences对象,值为 {nodeIntegration: true,contextIsolation: false},这样就可以正常使用require了
// 创建窗口这里使用的是electron自带的ipcRenderer属性,它是向主进程发送创建窗体请求,参数一为事件名,参数二为窗体配置
const { ipcRenderer } = require(“electron”)
const path = require(“path”)
window.addEventListener(“DOMContentLoaded”, () => {
// 点击按钮打开新窗口
// 获取btn
const btn = document.getElementById(“btn”)
// 按钮点击打开新窗口
btn.addEventListener(“click”, () => {
// 创建新窗口(向主进程发起请求,创建窗体,并显示pageFileName指定的页面)
ipcRenderer.send(‘open-window’, {
width: 600,
height: 400,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
},
pageFileName: path.join(__dirname, “list.html”) // 确保传递了正确的页面文件名,list.html需要显示的页面
})
})
// 打开第二个窗口
// 获取btn
const btn2 = document.getElementById(“btn2”)
// 按钮点击打开新窗口
btn2.addEventListener(“click”, () => {
// 创建新窗口(向主进程发起请求,创建窗体,并显示pageFileName指定的页面)
ipcRenderer.send(‘open-window’, {
width: 200,
height: 200,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
},
pageFileName: path.join(__dirname, “list2.html”) // 确保传递了正确的页面文件名,list2.html需要显示的页面
})
})
})
  1. **项目结构**
  2. ![在这里插入图片描述](https://img-blog.csdnimg.cn/e8f596561f5a439186dc0a7a9dcd48ed.png)
  3. **效果图**
  4. ![在这里插入图片描述](https://img-blog.csdnimg.cn/5f5458d325ef401183fb72a73a892beb.png)
  5. ### 自定义窗口的实现(以及阻止窗口关闭)
  6. **项目结构**
  7. ![在这里插入图片描述](https://img-blog.csdnimg.cn/88214c2574a2405b850a97dea70384b1.png)
  8. **安装**
复制代码
npm install --save @electron/remote
  1. **main.js代码如下**
复制代码
const { app, BrowserWindow } = require(“electron”)
const createWindow = () => {
// 创建窗口
let win = new BrowserWindow({
x: 100,
y: 50, //窗体坐标
frame: false, // 只保存主体部分,然后后面的样式全部都是由html去模拟
webPreferences: {
nodeIntegration: true,
contextIsolation: false, //加入这两行代码就可以正常使用require了,不会报错了
enableRemoteModule: true
}
})
require(‘@electron/remote/main’).initialize()
require(“@electron/remote/main”).enable(win.webContents)
//当前窗口显示的页面
win.loadFile(“index.html”)
// 窗口关闭
win.on(‘close’, () => {
console.log(‘close’)
win = null
})
}
// 窗口加载和关闭
app.on(‘ready’, createWindow)
app.on(“window-all-closed”, () => {
console.log(“window-all-closed”)
app.quit()
})
  1. **index.html**
复制代码
萧寂 主题内容

   一  口  X  上面的三个模拟最小化,最大化和关闭

   是否关闭当前应用

  体系可能不会保存您的所有更改
  是否
  1. **index.css**
复制代码
main {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.box {
color: red;
}
span {
padding: 10px 5px;
cursor: pointer;
}
/* 将提示语隐藏 */
.isShow {
display: none;
}
.s1 {
cursor: pointer;
}
  1. **index.js**
复制代码
const remote = require(“@electron/remote”)
window.addEventListener(‘DOMContentLoaded’, () => {
//利用remote获取当前窗口对象
let mainwin = remote.getCurrentWindow()
// 这里代码是当窗口关闭,去进行一下制止,并弹出提示框,用户确定关闭再进行关闭
// 监听close事件,close事件触发会执行这个事件onbeforeunload
window.onbeforeunload = function () {
// 获取到弹框dom元素,并设置样式
document.querySelector(‘.isShow’).style.display = ‘block’
// 将主题内容隐藏
document.querySelector(‘h2’).style.display = ‘none’
  1. // 获取弹窗的按钮(确认和取消)
  2. let btn = document.querySelectorAll('.s1')
  3. // 点击确认关闭按钮
  4. btn[0].addEventListener('click', () => {
  5.   // 这里不再使用close事件,不然会一直触发window.onbeforeunload事件,进入死循环了
  6.   mainwin.destroy() //窗口销毁
  7. })
  8. // 点击取消按钮
  9. btn[1].addEventListener('click', () => {
  10.   // 将窗口隐藏就好了
  11.   // 获取到弹框dom元素,并设置样式
  12.   document.querySelector('.isShow').style.display = 'none'
  13.   // 将主题内容显示
  14.   document.querySelector('h2').style.display = 'block'
  15. })
  16. return false
复制代码
}
const spans = document.querySelectorAll(‘span’)
// 最小化
spans[0].addEventListener(“click”, () => {
mainwin.minimize() //窗口最小化
})
// 放大
spans[1].addEventListener(“click”, () => {
// 最大化操作
console.log(‘mainwin.isMaximized()’, mainwin.isMaximized()) //false,返回布尔值,代表当前界面是否是最大化了
if (!mainwin.isMaximized()) {
mainwin.maximize() //如果没有最大化的话,给个最大化
} else {
mainwin.restore() //如果是最大化了,给它规复到初始状态
}
})
// 关闭窗口
spans[2].addEventListener(“click”, () => {
mainwin.close() //关闭窗口
})
})
  1. **效果图**
  2. ![在这里插入图片描述](https://img-blog.csdnimg.cn/a034ed1bd3f8413395ae1cf0cbb39ad5.png)
  3. **当点击关闭按钮,会弹出提示框,点击是就关闭,点击否会将提示框进行隐藏**  
  4. ![在这里插入图片描述](https://img-blog.csdnimg.cn/56ef210c19d146b28db888514c9bf727.png)
  5. ### 父子及模态窗口
  6. **模态窗口定义**:定义完以后不能对主窗口或者别的窗口进行操作,除非模态窗口  
  7. **其余代码和上面一样,只修改了index.js代码,代码如下**
复制代码
const remote = require(‘@electron/remote’)
window.addEventListener(‘DOMContentLoaded’, () => {
let btn = document.querySelector(‘#btn’)
btn.addEventListener(‘click’, () => {
let subWin = new remote.BrowserWindow({
width: 200,
height: 200,
parent: remote.getCurrentWindow(), //这个属性指向父级,实现了父子关联
modal: true, //定义模态窗口(默认为false,定义完以后不能对主窗口大概别的窗口进行操作,除非关闭模态窗口)
})
subWin.loadFile(‘sub.html’)
subWin.on(‘close’, () => {
subWin = null
})
})
})
  1. ## 自定义菜单
  2. **main.js代码如下**
复制代码
const { app, BrowserWindow, Menu } = require(“electron”) //Menu是菜单模块
console.log(process.platform)
const createWindow = () => {
// 创建窗口
let win = new BrowserWindow({
x: 100,
y: 50,
title: ‘自定义菜单’,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
}
})
// 1.这里定义菜单(定义本身需要的菜单项)
let menuTemp = [
{
label: ‘文件’,
submenu: [ //定义二级菜单
{
label: ‘打开文件’,
click () {
// 这里就可以使用每个选项的点击事件
console.log(‘当前需要的就是打开某一具体的文件’)
}
},
{
type: ‘separator’ // 添加分割线,就这一个属性将上下分隔开
},
{
label: ‘关闭文件夹’
},
{
label: ‘关于’,
role: ‘about’ //弹出关于项
}
]
},
{
label: ‘编辑’
}
]
// 2.利用上面菜单项天生一个菜单
let menu = Menu.buildFromTemplate(menuTemp)
// 3.将上述的自定义菜单添加到应用内里
Menu.setApplicationMenu(menu)
require(‘@electron/remote/main’).initialize()
require(“@electron/remote/main”).enable(win.webContents)
win.loadFile(“index.html”)
win.on(‘close’, () => {
console.log(‘close’)
win = null
})
}
// 窗口加载和关闭
app.on(‘ready’, createWindow)
app.on(“window-all-closed”, () => {
console.log(“window-all-closed”)
app.quit()
})
  1. **这里打印有点中文乱码问题,解决方法就是在终端输入`chcp 65001`回车,重新执行即可解决中文乱码问题**
  2. ### 菜单角色及类型
  3. **main.js代码**
复制代码
const { app, BrowserWindow, Menu } = require(“electron”)
const createWindow = () => {
// 创建窗口
let win = new BrowserWindow({
x: 100,
y: 50, //窗体坐标
webPreferences: {
nodeIntegration: true,
contextIsolation: false, //加入这两行代码就可以正常使用require了,不会报错了
enableRemoteModule: true
}
})
require(‘@electron/remote/main’).initialize()
require(“@electron/remote/main”).enable(win.webContents)
// 1.自定义菜单项
let menutap = [
{
label: ‘角色’,
submenu: [
{ label: ‘复制’, role: ‘copy’ },
{ label: ‘剪切’, role: ‘cut’ },
{ label: ‘粘贴’, role: ‘paste’ },
{ label: ‘最小化’, role: ‘minimize’ },
]
},
{
label: ‘类型’,
submenu: [
{ label: ‘多选一’, type: ‘checkbox’ },
{ label: ‘多选二’, type: ‘checkbox’ },
{ label: ‘多选三’, type: ‘checkbox’ },
{ type: ‘separator’ },
{ label: ‘单选1’, type: ‘radio’ },
{ label: ‘单选2’, type: ‘radio’ },
{ label: ‘单选3’, type: ‘radio’ },
{ type: ‘separator’ },
{ label: ‘windows’, type: ‘submenu’, role: ‘windowMenu’ } //这里两个属性必须同时给出
]
},
{
label: ‘其他’,
submenu: [
{
label: ‘打开’,
icon: ‘’,
accelerator: ‘ctrl + o’, //定义快捷键
click () {
console.log(‘打开操作执行了’)
}
}
]
}
]
// 2.依据上述的数据创建一个menu
let menu = Menu.buildFromTemplate(menutap)
// 3.将上述菜单添加至app身上
Menu.setApplicationMenu(menu)
//当前窗口显示的页面
win.loadFile(“index.html”)
// 窗口关闭
win.on(‘close’, () => {
console.log(‘close’)
win = null
})
}
// 窗口加载和关闭
app.on(‘ready’, createWindow)
app.on(“window-all-closed”, () => {
console.log(“window-all-closed”)
app.quit()
})
  1. ![在这里插入图片描述](https://img-blog.csdnimg.cn/3751e1dd146847fabdc5e47f509ae866.png)
  2. ### 动态创建菜单
  3. **index.html代码如下**
复制代码
萧寂 动态创建菜单

创建自定义菜单
添加菜单项
  1. **index.js代码如下**
复制代码
const remote = require(‘@electron/remote’)
// 找到菜单和菜单项
const Menu = remote.Menu
const MenuItem = remote.MenuItem
window.addEventListener(‘DOMContentLoaded’, () => {
// 获取按钮
let btn = document.querySelectorAll(‘button’)
// 获取输入框
let input = document.querySelector(‘input’)
// 自定义全局变量存放菜单项
let menuItem = new Menu()
// 点击天生自定义菜单
btn[0].addEventListener(‘click’, () => {
// 创建菜单
let menuFile = new MenuItem({ label: ‘文件’, type: ‘normal’ })
let menuEdit = new MenuItem({ label: ‘编辑’, type: ‘normal’ })
let customMenu = new MenuItem({ label: ‘自定义菜单项’, submenu: menuItem })
// 将创建好的菜单添加到menu
let menu = new Menu()
menu.append(menuFile)
menu.append(menuEdit)
menu.append(customMenu)
// 将ment放置于app中显示
Menu.setApplicationMenu(menu)
})
// 点击动态添加菜单项
btn[1].addEventListener(‘click’, () => {
// 获取当前input输入框当中输入的内容
let con = input.value.trim()
if (con) {
menuItem.append(new MenuItem({ label: con, type: ‘normal’ }))
input.value = ‘’
}
})
})
  1. **效果图**   ![在这里插入图片形貌](https://img-blog.csdnimg.cn/d123960a5e76401ba3fee23fe0ea1de5.png)   **点击自定义创建菜单会替换原来的菜单项,在输入框输入菜单名,点击添加菜单项会在菜单栏的自定义菜单内里追加本身添加的菜单项**### 自定义右键菜单**所有代码都是在index.js内里写的,index.html无代码只引用了index.js**   
  2. **index.js代码如下**
复制代码
const remote = require(‘@electron/remote’)
const Menu = remote.Menu
// 01 创建一个自定义菜单的内容
let contextTemp = [
{ label: ‘RunCode’ },
{ label: ‘转到定义’ },
{ type: ‘separator’ },
{
label: ‘其他功能’,
click () {
console.log(“其他功能选项被点击了”) //这个打印不会在主进程显示,而是在桌面版使用ctrl+shifl+i去控制台看
}
}
]
// 02 依据上述内容来创建menu
let menu = Menu.buildFromTemplate(contextTemp)
window.addEventListener(‘DOMContentLoaded’, () => {
// 03 在鼠标右击行为发生后显示出来
window.addEventListener(‘contextmenu’, (e) => {
e.preventDefault() //制止有些元素点击的默认行为
menu.popup({ window: remote.getCurrentWindow() }) //将当前窗口对象作为popup参数,代表在当前窗口弹出
}, false)
})
  1. ## 主进程和渲染进程进行通讯### 同步和异步进行通讯
  2. **index.html**
复制代码
萧寂 渲染进程与主进程进行通讯


渲染主异步操作
渲染主同步操作
  1. **index.js**
复制代码
const { ipcRenderer } = require(‘electron’)
window.onload = () => {
// 获取元素
let abtn = document.querySelectorAll(‘button’)
// 01 采用异步的API在渲染进程中给主进程发送消息
abtn[0].addEventListener(‘click’, () => {
ipcRenderer.send(‘msg1’, ‘dataMag’)
})
// 当前接收主进程的消息
ipcRenderer.on(‘msgRe’, (ev, data) => {
console.log(‘data’, data) //主进程复兴的异步消息
})
// 02 采用同步的方式完成数据的通讯
abtn[1].addEventListener(‘click’, () => {
let val = ipcRenderer.sendSync(‘msg2’, ‘SyncMsg’)
console.log(‘val’, val) // 主进程复兴的同步消息
})
}
  1. **主进程main.js**
复制代码
const { app, BrowserWindow, ipcMain } = require(“electron”)
const createWindow = () => {
// 创建窗口
let win = new BrowserWindow({
x: 100,
y: 50, //窗体坐标
webPreferences: {
nodeIntegration: true,
contextIsolation: false, //加入这两行代码就可以正常使用require了,不会报错了
enableRemoteModule: true
}
})
require(‘@electron/remote/main’).initialize()
require(“@electron/remote/main”).enable(win.webContents)
//当前窗口显示的页面
win.loadFile(“index.html”)
// 窗口关闭
win.on(‘close’, () => {
console.log(‘close’)
win = null
})
}
// 窗口加载和关闭
app.on(‘ready’, createWindow)
app.on(“window-all-closed”, () => {
console.log(“window-all-closed”)
app.quit()
})
// 监听渲染进程发送的消息
ipcMain.on(‘msg1’, (e, data) => {
console.log(‘data’, data)
// 主进程给渲染进程发消息
e.sender.send(‘msgRe’, “主进程复兴的异步消息”)
})
// 监听渲染进程发送的消息
ipcMain.on(‘msg2’, (e, data) => {
console.log(‘data’, data)
// // 主进程给渲染进程发消息
e.returnValue = ‘主进程复兴的同步消息’
})
  1. ### 通过主进程主动发送消息控制渲染进程作出行为**以下代码没有使用index.html,index.html只是引用了一下index.js**   
  2. **index.js**
复制代码
const { ipcRenderer } = require(‘electron’)


网上学习资料一大堆,但如果学到的知识不成体系,碰到标题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份体系化的资料的朋侪,可以戳这里获取
一个人可以走的很快,但一群人才能走的更远!岂论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
   {
console.log(“window-all-closed”)
app.quit()
})
  // 监听渲染进程发送的消息
ipcMain.on(‘msg1’, (e, data) => {
console.log(‘data’, data)
// 主进程给渲染进程发消息
e.sender.send(‘msgRe’, “主进程复兴的异步消息”)
})
// 监听渲染进程发送的消息
ipcMain.on(‘msg2’, (e, data) => {
console.log(‘data’, data)
// // 主进程给渲染进程发消息
e.returnValue = ‘主进程复兴的同步消息’
})
  1. ### 通过主进程主动发送消息控制渲染进程作出行为**以下代码没有使用index.html,index.html只是引用了一下index.js**   
  2. **index.js**
复制代码
const { ipcRenderer } = require(‘electron’)
[外链图片转存中…(img-LeJartWV-1715608408428)]
[外链图片转存中…(img-U24kBqoq-1715608408429)]
网上学习资料一大堆,但如果学到的知识不成体系,碰到标题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份体系化的资料的朋侪,可以戳这里获取
一个人可以走的很快,但一群人才能走的更远!岂论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

愛在花開的季節

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表