当前位置: 首页 > news >正文

十五分钟带你学会 Electron

文章目录

    • 什么是 Electron
    • 为什么要选择 Electron
    • 安装 Electron
    • 桌面CSDN实战
    • Electron 基础配置
    • Electron 进程
      • 主进程
      • 渲染进程
      • 主进程与渲染进程的区别
      • 主进程与渲染进程的通信
    • Electron 跨平台问题
    • Electron 部署
      • 打包应用程序
      • 发布应用程序
    • Electron 跨端原理
    • 总结

什么是 Electron

Electron 是一种基于 Node.js 和 Chromium 开发的开源框架,用于构建跨平台桌面应用程序。

Electron 提供了许多跨平台的功能,例如窗口管理、菜单、对话框和托盘图标等。它还可以轻松地与 Node.js 模块进行集成,以便开发人员可以使用已有的 Node.js 生态系统中的库和工具。

这使得 Electron 非常适合开发具有丰富用户界面和本地操作系统集成的桌面应用程序。

由于 Electron 使用 Chromium 作为其呈现引擎,因此应用程序可以获得高性能和现代 Web 技术的支持。

同时,由于其跨平台特性,开发人员可以使用一致的开发工具和技术来构建适用于 Windows、macOS 和 Linux 等多个操作系统的应用程序。

简单点说,就是 Electron 提供一套方法,将 nodejs 和 Chromium 打包成一套跨平台桌面端应用。


为什么要选择 Electron

我们来看一下有哪些技术可以开发桌面应用:

编程语言 / 技术框架可提供的能力代表作
C#/WPF开发 Windows 应用Visual Studio
Swift开发 macOS 应用CodeEdit
C++/QT跨平台应用YY 语音
C++/CEF跨平台应用钉钉
Java/Swing跨平台应用JetBrains系列软件
JavaScript/Electron跨平台应用Visual Studio Code
Rust/Tauri跨平台应用xplorer
Dart/Flutter跨平台应用rustdesk

作为一名开发者,学习某项技术需要看投资回报率高不高,像 Windows 平台上的 C# 和 macOS 平台上的 Swift,个人觉得技术路线会比较窄,未来更多的场景是采用跨平台的技术来实现。

所以如果有 C++ 的功底,QT 和 CEF 是不错的选择,而对于前端来说,最好的选择无外乎下面三个:

  • Electron:纯 JavaScript 技术栈,生态非常成熟,前端同学快速上手,无学习成本
  • Tauri:打出来的包非常小,需要一定的 Rust 基础
  • Flutter:一套代码通吃 web、iOS、Android、macOS、Windows、Linux 六大平台

可以看到,上述三个选择的优势都非常明显,但是其他两个对于前端来说都有一定的学习成本,需要学习 rust 和 dart 语言,而 Electron 对于前端来说简直就是零成本,所以从学习成本来说 Electron 是最适合的。

从流行度上来说,相当多的桌面应用使用的就是 Electron 开发。这其中不乏大名鼎鼎、如雷贯耳的应用,例如 Postman、Notion、Skype 等,而且我敢打赌,各位的电脑上一定安装过用 Electron 开发的应用,如果你用的是 Mac 电脑,请在命令行运行下面的命令来检测本地采用 Electron 技术开发的桌面软件:

for app in /Applications/*; do;[ -d  $app/Contents/Frameworks/Electron\ Framework.framework ] && echo $app; done

我本地检测出来的应用有:

$ for app in /Applications/*; do;[ -d  $app/Contents/Frameworks/Electron\  Framework.framework ] && echo $app; done
/Applications/BaiduNetdisk_mac.app
/Applications/QQ.app
/Applications/Scratch 3.app
/Applications/Visual Studio Code.app
/Applications/Xmind.app
/Applications/aDrive.app
/Applications/lx-music-desktop.app

最后我们来看一下 Electron 比 Web 的优势在哪里:

  • 资源本地化和离线持久化:对于传统 Web 应用来说,性能卡点往往不在于解析和渲染,而在于网络请求,把资源本地化之后,可以做到应用启动后页面秒开,极大程度上减少了白屏和用户等待的时间。另外,传统 Web 的数据都是通过调用接口实时保存到服务端,无法做到离线持久化,而 Electron 可以将用户配置、缓存数据全部写入本地文件,在离线状态下依然能够正常使用软件,当恢复在线时同步到云端,例如笔记类应用。
  • 系统底层 API 调用:Web 环境本质上是浏览器提供的一个沙箱,出于安全考虑限制了很多底层能力,例如文件操作等,而在 Electron 里面,你可以调用任何操作系统提供的 API,包括 node.js 帮开发者封装好的 fs、child_process、os 等。
  • 不受限的网络通信:每一个前端开发都会遇到跨域问题,这其实是 Web 浏览器为了保证不同域下的数据安全,人为制造出来的限制,而在 Electron 环境下,你不用考虑是否跨域,所有 http 和 https 请求都畅通无阻,而且你还能对这些请求进行拦截和重定向,甚至修改任意 header 字段和响应结果。不仅如此,更底层的网络能力,例如 tcp 和 udp 也是支持的,你完全可以做一个类似于 QQ 一样的聊天软件。
  • 可定制化的窗口:传统 Web 只能给用户提供一个 tab,单调乏味,Electron 可以创建各式各样的无边框窗口,甚至可以设置成圆形或三角形的形状,例如你可能用过苹果自带的 Spotlight 或者 Alfred,只提供了一个搜索入口,快捷键唤起全局置顶的输入框,用完即走,从视觉和交互体验上都完爆 Web,除此之外,桌面应用还可以设置托盘菜单,做出类似于 QQ 消息一闪一闪的效果。

所以各位前端们还等什么,快跟着我一起学起来!


安装 Electron

为什么要特地讲一下安装呢,因为这里有一个坑

当执行 npm install electron -D 会一直卡在一个地方无法正常安装

解决办法 使用 cnpm:

npm install -g cnpm --registry=https://registry.npmmirror.com
cnpm install electron -D

桌面CSDN实战

纸上得来终觉浅,我们接下来先通过手写一个 Electron Demo 带大家入门 Electron。

我们首先来快速创建一个 Electron 项目:

$ mkdir my-electron
$ cd my-electron
$ npm init -y
$ npm install electron electron-packager --dev

接下来我们创建一个 src 目录,里面再分别创建两个子目录 main 和 renderer。

在 Electron 中有主进程渲染进程两个重要的概念,我们在主进程里面用 Node.js 代码调用 Electron 封装好的 API 来创建窗口,管理应用整个生命周期,而在渲染进程里面加载传统的 Web 界面。

因此 main 目录用于存放跟主进程相关的代码,renderer 目录用于存放跟渲染进程相关的代码。

整个桌面应用的入口在主进程里面,接下来在 main 目录中创建 index.js 作为入口。

为了让 Electron 知晓该入口,我们需要在 package.json 中做以下指定:

"main": "src/main/index.js",
"scripts": {"start": "electron ."
},

至此一个基础的 Electron 项目就搭建完毕,接下来我们可以来写我们的页面了。

在 src/main/index.js 入口文件中,我们来加载一个 CSDN :

//引入两个模块:app 和 BrowserWindow
//app 模块,控制整个应用程序的事件生命周期。
//BrowserWindow 模块,它创建和管理程序的窗口。
const { app, BrowserWindow } = require('electron')//在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口
app.whenReady().then(() => {//创建一个窗口createWindow()
})function createWindow() {const mainWindow = new BrowserWindow({ width: 800, height: 600 })//窗口加载 URLmainWindow.loadURL('https://www.csdn.net/')
}

然后在终端输入 npm start 启动项目,你会看到一个加载 CSDN 官网的窗口弹出来了
在这里插入图片描述

一般的企业桌面应用都会定义自己的专属协议,我们可能都遇到过在网页的百度网盘点击下载,会自动打开我们电脑里的百度网盘软件。这是怎么做到的呢?就是通过自定义协议。

所谓自定义协议,其实就是给应用起个独一无二的名称,然后注册到操作系统里面,凡是通过这个协议名就能唤起这个软件了,在 Electron 中注册协议只需要一行代码:

app.setAsDefaultProtocolClient('electron-desktop')

注册之后,当在浏览器中输入 electron-desktop:// 之后,会发现弹出跳转提示,点击同意就能启动并跳转到桌面应用了,通过这种协议唤起应用被称为 scheme 唤起,而且在唤起的时候还可以带上一些参数,例如:

electron-desktop://width=800&height=600

自定义协议之后,可以用 scheme 唤起桌面应用,这是非常重要的能力

这里面最关键的是需要拿到协议唤起参数,否则唤起 QQ 之后不知道要跟谁聊天,唤起百度网盘之后不知道要下载哪款资料。

scheme 唤起的行为是操作系统默认支持的,操作系统也提供了 API 来监听唤起事件并拿到唤起参数。

在 Mac 和 Windows 上获取协议唤起参数是不一样的,这是由于平台策略不同导致的,这里讲解一下 Mac。

在 Mac 上面通过监听 open-url 事件,可以拿到唤起的 scheme 参数:

app.on('open-url', (event, url) => {console.log(url) // 打印 electron-desktop://width=800&height=600
})

url 里面就是 scheme 唤起的完整地址字符串,除了开头的 electron-desktop:// 前缀之外,后面的内容是完全交给用户自定义的,例如:

  • electron-desktop://hello-CSDN
  • electron-desktop://1+1=2

这些都可以唤起,上面之所以用 width=800&height=600 完全是因为模仿 http 地址栏的 query 参数的格式,有现成的 API 方便解析参数而已。

下面我们把 open-url 的回调获取到的 scheme 参数解析出来放到全局变量 urlParams 里面:

const { app, BrowserWindow } = require('electron')const protocol = 'electron-desktop'
app.setAsDefaultProtocolClient(protocol)let urlParams = {}app.on('open-url', (event, url) => {const scheme = `${protocol}://`const urlParams = new URLSearchParams(url.slice(scheme.length))urlParams = Object.fromEntries(urlParams.entries())
})app.whenReady().then(() => {createWindow()
})function createWindow() {const mainWindow = new BrowserWindow({ width: 800, height: 600 })mainWindow.loadURL('https://www.csdn.net/')
}

协议唤起在 Mac 平台上有两点需要注意:

  • open-url 要在 ready 事件之前注册,因为有些场景是需要拿到参数之后再决定如何创建窗口的,如果放在 ready 回调里面,createWindow 可能会拿不到该参数了。
  • 在应用支持多实例场景下,如果程序未启动,会立即启动应用,在 open-url 中获取到唤起参数。如果存在正在运行的实例(可能有多个),会激活(其中一个)已经运行的程序,而不会开启新的实例,被激活的实例可以通过 open-url 回调获取唤起参数。

接下来我们来完成这个桌面 CSDN demo:

  • 打开桌面应用后立即进入 CSDN 首页
  • 支持用 csdn:// 这个 scheme 唤起应用
  • 支持用 csdn://width=500&height=300 这个 scheme 指定窗口大小
const { app, BrowserWindow } = require('electron')let mainWindowconst protocol = 'csdn'
const scheme = `${protocol}://`
app.setAsDefaultProtocolClient(protocol)let urlParams = {}handleSchemeWakeup(process.argv)app.on('open-url', (event, url) => handleSchemeWakeup(url))app.whenReady().then(() => {createWindow()
})// 创建 electron 新窗口
function createWindow() {const width = parseInt(urlParams.width) || 800const height = parseInt(urlParams.height) || 600if (mainWindow) {mainWindow.setSize(width, height)} else {mainWindow = new BrowserWindow({ width, height })mainWindow.loadURL('https://www.csdn.net/')}
}// 处理自定义协议 scheme 唤起
function handleSchemeWakeup(argv) {const url = [].concat(argv).find((v) => v.startsWith(scheme))if (!url) return// url 之间的 search 转换const searchParams = new URLSearchParams(url.slice(scheme.length))urlParams = Object.fromEntries(searchParams.entries())if (app.isReady()) createWindow()
}

到此为止,我们的桌面 CSDN 实战就完成了。

我们把传统的 Web 页面通过用 Electron 加载出来的方式叫做「套壳桌面应用」,这也是将网站做成桌面软件最快速的方式。

在开发完成后,需要将应用程序打包成可执行文件,可以使用 electron-builder 进行打包。

在命令行中运行以下命令进行安装:

npm install electron-builder --save-dev

安装完成后,可以在项目的 package.json 文件中添加以下脚本:

"scripts": {   "start": "electron .",   "build": "electron-builder" }

然后,在命令行中运行 npm run build 命令即可打包 Electron 应用程序。

相信你通过上面这个的应用已经了解了 Electron 的简单开发和打包流程,

接下来我们来学习一些 Electron 的基础理论知识和进阶用法。


Electron 基础配置

const { app, BrowserWindow } = require('electron')
let win
// 监听electron 加载完毕的时候的创建窗口等等
app.on('ready', function () {// 创建一个窗口 设置属性win = new BrowserWindow({//fullscreen: true   //全屏//frame: false,   	//让桌面应用没有边框,这样菜单栏也会消失resizable: false,   //不允许用户改变窗口大小width: 800,         //设置窗口宽高height: 600,icon: iconPath,     //应用运行时的标题栏图标minWidth: 300,     // 最小宽度minHeight: 500,    // 最小高度maxWidth: 300,    // 最大宽度maxHeight: 600,    // 最大高度// 进行对首选项的设置webPreferences:{    backgroundThrottling: false,   //设置应用在后台正常运行nodeIntegration:true,     //设置能在页面使用nodejs的APIcontextIsolation: false,  //关闭警告信息//preload: path.join(__dirname, './preload.js')}})// 这里让主进程加载一个index.htmlwin.loadFile('index.html')// 设置为最顶层//win.setAlwaysOnTop(true)//win.loadURL(`www.baidu.com`) 可以让主进程打开文件或者一个链接// 监听窗口关闭事件win.on('closed',()=>{//释放winwin = null})
})// 监听所有的窗口都关闭了
app.on('window-all-closed', () => {console.log('窗口全部都关闭了')
})

Electron 进程

Electron 应用程序有两种类型的进程:主进程和渲染进程。

主进程负责管理应用程序的生命周期和所有窗口,而渲染进程负责显示窗口内容。

通常,主进程和渲染进程是通过 ipcMainipcRenderer 模块进行通信。

使用主进程和渲染进程,你可以更好地管理应用程序和窗口,并且可以在不同的进程中处理不同的任务。

主进程

Electron 运行 package.json 的 main 脚本的进程被称为主进程 (只有一个)

主进程特点:

  • 主进程连接着操作系统和渲染进程,可以把它看做页面和计算机沟通的桥梁
  • 进程间通信、窗口管理
  • 全局通用服务
  • 一些只能或适合在主进程做的事情,例如浏览器下载、全局快捷键处理、托盘、session
  • 维护一些必要的全局状态

渲染进程

渲染进程就是我们所熟悉前端环境了,只是载体改变了,从浏览器变成了 window.

注:出于安全考虑,渲染进程是不能直接访问本地资源的,因此都需要在主进程完成。

渲染进程特点:

  • Electron 使用了 Chromium 来展示 web 页面,所以 Chromium 的多进程架构也被使用到
  • 每个 web 页面运行在它自己的渲染进程中。每个渲染进程都是相互独立的,并且只关心他们自己的网页
  • 使用 BrowserWindow 类开启一个渲染进程并将这个实例运行在该进程中,当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止
  • 渲染进程中不能调用原生资源,但是渲染进程中同样包含 Node.js 环境,所以可以引入 Node.js

主进程与渲染进程的区别

  • 主进程使用 BrowserWindow 实例创建网页
  • 每个 BrowserWindow 实例都在自己的渲染进程里运行着一个网页。当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止
  • 主进程管理所有页面和与之对应的渲染进程
  • 由于在网页里管理原生 GUI 资源是非常危险而且容易造成资源泄露,所以在网页面调用 GUI 相关的 API 是不被允许的。如果你想在网页里使用 GUI 操作,其对应的渲染进程必须与主进程进行通讯,请求主进程进行相关的 GUI 操作

把它们想象成这样 Chrome 的每个标签页及其页面,就好比 Electron 中的一个单独渲染进程。

即使关闭所有标签页,Chrome 依然存在。这好比 Electron 的主进程,能打开新的窗口或关闭这个应用。

主进程与渲染进程的通信

主线程渲染线程 通过 webContents.send 来发送 —>ipcRenderer.on 来监听

渲染线程主线程 需要通过 ipcRenderer.send 发送 —> ipcMain.on 来监听


Electron 跨平台问题

跨平台问题是在开发 Electron 应用程序时需要考虑的一个重要问题。

由于不同平台有不同的 UI 和 API,因此需要使用不同的代码来处理跨平台问题。

以下是一些常见的跨平台问题和解决方法:

  • 文件路径:在不同的操作系统上,文件路径的格式可能不同。为了解决这个问题,可以使用 Node.js 提供的 path 模块来处理文件路径。
  • 窗口大小和位置:在不同的操作系统上,窗口的大小和位置可能有所不同。为了解决这个问题,可以使用 Electron 提供的 screen 模块来获取屏幕大小和分辨率,并使用相对位置来设置窗口的大小和位置。
  • 快捷键:在不同的操作系统上,快捷键的组合键可能不同。为了解决这个问题,可以使用 Electron 提供的 globalShortcut 模块来注册快捷键,该模块可以自动适应不同的操作系统。

可以使用快捷键 Ctrl+Shift+I(Windows 和 Linux)或 Cmd+Shift+I(macOS)打开开发者工具。


Electron 部署

打包应用程序

在将应用程序部署到生产环境之前,需要将其打包为可执行文件。

以下是一些常用的工具,可以帮助我们将 Electron 应用程序打包为可执行文件:

  • electron-builder:一个基于 Electron 的打包器,支持将应用程序打包为各种格式,如 Windows、macOS 和 Linux。
  • electron-packager:另一个流行的打包器,也支持多种格式。

以下介绍一下 Electron Builder 的使用步骤和注意事项:

首先需要使用 npm 安装 Electron Builder:

npm install electron-builder --save-dev

然后我们要配置 package.json 文件,我们需要添加一些字段来配置应用程序的打包和发布。

  • build 字段:用于配置应用程序的构建选项。
  • directories 字段:用于配置应用程序的源代码和构建输出目录。
  • repository 字段:用于配置应用程序的源代码仓库地址。

以下是一个 package.json 文件的示例:

{"name":"my-electron-app","version":"1.0.0","description":"my Electron App","main":"main.js","scripts":{"start":"electron .","build":"electron-builder"},"repository":{"type":"git","url":"https://github.com/username/my-electron-app.git"},"build":{"appId":"com.example.my-electron-app","productName":"my Electron App","directories":{"output":"dist"}}
}

build 字段中,我们需要添加一些构建选项来指定应用程序的行为,以下是一些常用的构建选项:

  • appId:应用程序的 ID。
  • productName:应用程序的名称。
  • files:要打包的文件和文件夹。
  • directories:源代码和构建输出目录。
  • asar:是否将应用程序打包成 ASAR 文件。
  • macwinlinux:用于配置每个平台的构建选项。
  • dmgnsisdeb:用于配置每个平台的安装包选项。

以下是一个常见的 build 字段的示例:

{"build":{"appId":"com.example.my-electron-app","productName":"My Electron App","directories":{"buildResources": "build",   //指定打包需要的静态资源,默认是build"output": "dist",  //打包生成的目录,默认是dist},"files":["main.js","package.json","index.html","assets/**/*"],"asar":true,"mac":{"target":"dmg","icon":"assets/icon.icns""category": "public.app-category.utilities"  //应用程序安装到哪个分类下},"win":{"target":"nsis","icon":"assets/icon.ico"},"linux":{"target":"deb","icon":"assets/icon.png"},"dmg": {"background": "build/background.jfif",   //安装窗口背景图"icon": "build/icons/icon.icns",         //安装图标"iconSize": 100,                         //图标的尺寸"contents": [                            //安装图标在安装窗口中的坐标信息{"x": 380,"y": 180,"type": "link","path": "/Applications"},{"x": 130,"y": 180,"type": "file"}],"window": {                             //安装窗口的大小"width": 540,"height": 380}}}
}

package.json 文件中,可以使用以下命令来打包应用程序:

npm run build

执行此命令后,Electron Builder 将使用我们在 build 字段中配置的选项来构建应用程序,并将构建输出文件保存到 directories.output 中指定的目录。

在打包生成的文件夹中,会有一个 app.asar,它是 Electron 应用程序的主业务文件压缩包,要知道项目中哪些文件被 pack 到安装包,可以通过解压 app.asar 进行查看。

解压完 app.asar 后,里面除了项目的所有文件,还有一个 node_modules

对于 node_modules并不是所有 node_modules 中的内容都会被打包进安装包,只有 package.jsondependencies 字段中的依赖会被打包,devDependencies 字段中的依赖则不会。

这是唯一规则,跟项目实际是否使用依赖没有关系。

所以,为了减小安装包体积,建议在渲染进程中使用的外部包,都安装在 devDependencies 中,然后使用 webpack 将外部包的代码和业务代码打包到一起。

发布应用程序

将应用程序打包为可执行文件之后,我们就可以将其发布到各个平台的应用商店或者自己的网站上。

electron-updater:用于自动化发布应用程序的工具

更新应用程序的安装包应该存放在互联网的某台服务器上,每次打开应用的时候,进行自动检测,根据当前应用程序的 version 和线上版本进行匹配,当发现有新的 version 的时候,就自动下载,下载完成后,询问用户是否安装新版本。

还有一种情况就是 web 资源和 “app 壳子” 分离,web 资源放在服务器,每次都通过网络动态加载,像我们上面的桌面 CSDN 实战一样:

mainWindow.loadURL('https://www.csdn.net/')

在业务需要频繁更新的场景中,可以使用这种方式,快速无障碍地实现更新。

在这种情况下,我们可以按照上述方式打包和更新 “壳子”,也就是主进程相关;

而页面资源的打包和普通的前端项目打包无异,这里不再赘述。


Electron 跨端原理

Electron 的跨端原理并不难理解,我们在这里简单介绍一下,相信大家能很容易理解。

它通过集成浏览器内核,使用前端技术来实现不同平台下的渲染,并结合了 ChromiumNode.js 和用于调用系统本地功能的 API 三大板块。
在这里插入图片描述

  • ChromiumElectron 提供强大的 UI 渲染能力,由于 Chromium 本身跨平台,因此无需考虑代码的兼容性。最重要的是,可以使用前端三板斧进行 Electron 开发。
  • Chromium 并不具备原生 GUI 的操作能力,因此 Electron 内部集成 Node.js,编写 UI 的同时也能够调用操作系统的底层 API,例如 path、fs、crypto 等模块。
  • Native APIElectron 提供原生系统的 GUI 支持,借此 Electron 可以调用原生应用程序接口。

总结起来,Chromium 负责页面 UI 渲染,Node.js 负责业务逻辑,Native API 则提供原生能力和跨平台。


总结

Electron 确实是构建跨平台桌面应用程序的利器,建议大家学习的时候多看看官方的文档,因为Electron版本迭代太快了,不及时看官方文档真的还是有不少坑的。

简单做个小总结,本文介绍了一些 Electron 的基础知识,包括 Electron 的定义、优势、基础配置、进程、部署、跨端原理,并完成了一个桌面 CSDN 应用实战案例。

通过掌握上述这些知识,你已经可以试着开发属于你自己的 Electron 应用程序啦,快去试试吧。

相关文章:

十五分钟带你学会 Electron

文章目录 什么是 Electron为什么要选择 Electron安装 Electron桌面CSDN实战Electron 基础配置Electron 进程主进程渲染进程主进程与渲染进程的区别主进程与渲染进程的通信 Electron 跨平台问题Electron 部署打包应用程序发布应用程序 Electron 跨端原理总结 什么是 Electron E…...

设计模式-结构型模式之桥接模式

2. 桥接模式 2.1. 模式动机 设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案: 第一种设计方案是为每一种形状…...

软件测试工程师为什么要写测试用例?

软件测试工程师为什么要写测试用例?相信从事软件测试行业的从业者来讲,测试用例并不陌生。因为测试用例不仅仅是一组简单的文档,它包含前提条件、输入、执行条件和预期结果等等重要内容,并且能够完成一定的测试目的和需求。下面本…...

【DAY40】VUE练习

DOS命令: DOS(Disk Operating System)是一种操作系统,它使用命令行界面(Command Prompt)进行交互。在 DOS 中,有一些常用的命令,可以用来定位目录、创建、删除、拷贝文件和目录&…...

实模式的寄存器

实模式的寄存器有8个通用寄存器,分别为AX、BX、CX、DX、SI、DI、BP和SP。通用的意思就是它们之中的大部分可以根据需要用于多种目的。 AX: accumulator,累加寄存器 BX: base,基址寄存器 CX: count,计数寄存器 SI: Source Index&am…...

【UE 控件蓝图】通过键盘选中要点击的按钮 通过Enter键点击

上一篇【UE 控件蓝图】菜单及功能实现博客已经完成了菜单的制作,但是我们只能通过鼠标来点击菜单选项,本篇博客实现的是能够通过键盘的上下键来选中按钮,然后按下“Enter”键来实现点击按钮的效果。 效果 可以看到并没有移动鼠标也可以通过…...

SSR在天猫优品大促会场的探索实践

BBC 发现其网站加载时间每增加一秒,用户便会流失 10%。为提高页面的秒开率,我们不断探索着优化策略,仅仅在浏览器领域下的优化已经满足不了我们的极致要求,开始往服务端方向不断探索。本文将讨论业务接入SSR的几个问题&#xff1a…...

WPF教程(一)---创建一个WPF程序基础知识

1.前言: 这篇主要讲WPF的开发基础,介绍了如何使用Visual Studio 2019创建一个WPF应用程序。 首先说一下学习WPF的基础知识: 1) 要会一门.NET所支持的编程语言--例如C#。 2) 会一点“标准通用标记语言”:WPF窗体程序使用的XAML语…...

【C++ 四】函数、指针

函数、指针 文章目录 函数、指针前言1 函数1.1 概述1.2 函数定义1.3 函数调用1.4 值传递1.5 函数常见样式1.6 函数声明1.7 函数分文件编写1.8 函数默认参数1.9 函数占位参数1.9 函数重载1.9.1 函数重载概述1.9.2 函数重载注意事项 2 指针2.1 指针基本概念2.2 指针变量定义和使用…...

虚拟人与娱乐传媒融合,推动综艺新模式

经过多年的更新迭代和市场的推动,虚拟人技术正在逐渐迈向成熟:3D虚拟形象的制作变得越来越精致且真实,并且出现了越来越多功能丰富使用便捷的动捕设备。因此,包括综艺影视在内的诸多领域,开始尝试将虚拟人技术融入行业…...

Linux_红帽8学习笔记分享_5

Linux_红帽8学习笔记分享_5 文章目录 Linux_红帽8学习笔记分享_51. UMASK反掩码1.1如何查看反掩码umask1.2 UMASK反掩码的作用1.2.1对于目录来说1.2.2对于文件来说 1.3如何修改UMASK反掩码1.4普通用户反掩码的测试 2.whereis的使用3. SUID权限弥补(主要针对文件,所有者执行位变…...

网络编程及项目思路

计算机和计算机之间通过网络进行数据传输 常见的软件架构: C/S:客户端/服务器 画面可以做的非常精美,用户体验好需要开发客户端,也需要开发服务端用户需要下载和更新的时候太麻烦 B/S:浏览器/服务器 不需要开发客户端,只需要…...

GD(兆易创新)系列FLASH进行FPGA和ZYNQ配置固化相操作

写在前面 本文主要针对使用GD(兆易创新)系列的FLASH做启动配置片时,遇到的相关问题进行简单整理复盘,避免后人踩坑。 本人操作固化芯片型号为:ZYNQ7045、690T(复旦微替代型号V7 690T)。 7系列…...

通过一个小例子来看一下C语言指针 p、*p、p、*p、*p分别代表什么

前言 在C语言中,指针是非常重要的概念。指针是一个变量,其值为另一个变量的地址。使用指针可以直接访问内存中的数据,这使得C语言非常灵活和强大。在学习C语言时相比大家都已经知道了&和*的区别了,但是你知道*&p和&*…...

【内摹访谈】谈谈AI爆发前夜的B端设计

本文来自摹客产品设计团队(MPD)的设计专栏“内摹访谈”。专栏介绍:专栏名称来源于西方美学理论「内摹仿说」,意指审美活动与摹仿活动紧密相连,审美不只针对表象动作,其核心在于由物及我,从表观带…...

Redis—AOF持久化

一、AOF定义 保存写操作命令到日志的持久化方式,就是 Redis 里的 AOF(Append Only File) 持久化功能 定义:以日志的形式记录每个操作,记录写指令不记录读指令,只许追加⽂件不允许修改,AOF保存的是appendonly.aof⽂件…...

OpenCV实例(五)指纹识别

OpenCV实例(五)指纹识别 1.指纹识别概述1.1概述1.2原理 2.指纹识别算法2.1特征提取2.2MCC匹配方法2.3尺度不变特征变换(SIFT) 3.显示指纹的关键点4.基于SIFT的指纹识别 作者:Xiou 1.指纹识别概述 1.1概述 指纹识别&…...

第二章 法的内容与形式

目录 第一节 法的内容与形式的概念 一、法的内容与形式的含义 二、法的内容和形式的关系 第二节 法律权利与法律义务 一、权利和义务的概念 二、权利和义务的分类 三、权利与义务的联系 第三节 法的成文形式与不成文形式 一、历史上各种法的表现形式 二、成文法与不成文…...

外包干了四年,感觉废了..

先说一下自己的情况,大专生,18年通过校招进入湖南某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...

Git如何推送当前代码到远程仓库

第一种方法 (建立在已经配置好用户变量和ssh基础上) 在本地创建git仓库 git init 绑定远程仓库,origin是给远程仓库起的别名,也可以起其他名字,但是如果用origin,git push时可以不指出名字,如果…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...

push [特殊字符] present

push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)

Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...