Electron基础篇

news2024/11/24 18:38:16

人生有些事,错过一时,就错过一世。


 官网:简介 | Electron

Electron-大多用来写桌面端软件

 


Electron介绍

Electront的核心组成是Chromium、Node.js以及内置的Native API,其中Chromium为Electron提供强大的UI能力,可以在不考虑兼容的情况下利用强大的Web生态来开发界面;Node.js让Electron有了底层的操作能力,比如像文件的读写,然后集成C++等等,还可以使用大量的NPM包来帮助大家来完成项目需求;最后内置的Native API解决了跨平台的问题,首先它提供了统一的原生界面,比如像窗口、托盘,其次是系统能力,比如像我们的Notification,最后是应用的基础能力,比如像软件更新,崩溃监控等等,而通过这三者的组合,我们开发桌面应用变得十分的高效。

基础介绍

1、Electron是什么?
Electron 是 GitHub 开发的一个开源框架。它允许开发者使用Web技术构建跨平台桌面应用。

在这里插入图片描述

高效:通过Web技术写UI  
能力:底层能力  
能力&体验:跨平台&原生能力

桌面技术选型
1、为什么开发桌面端?
① 提供更快捷的入口,让自己的产品占据用户的桌面;
② 软件需要离线可用;
③ 需要调用到系统能力,比如像通知用户,然后结合打印机去完成自己的业务等等
④ 安全需求,比如在金融或企业级应用领域下,我们会更偏向于做一个桌面端

2、技术
1)Native(C++/C#/Objective-C)
各平台的原生语言写的应用在高性能、原生体验、包体积小、门槛高、迭代速度慢。

2)QT
基于C++的跨平台开发框架(Mac、Windows、IOS、Android、Linux、嵌入式)应用十分广泛,像大家熟知的DropBox或者WPS,它都是用QT来写的;虽然是跨平台,但实际(高)性能还挺好,它甚至可以媲美原生(体验);QT它有着自己的QML,类似CSS,也有不错的社区和生态,所以迭代速度会比Native会快一些,但是整体门槛还是比较高,而且人才在市场上比较稀缺。

3)Flutter
Flutter是移动端非常火的,它的整体的目标是跨端(iOS、Android、Mac、Windows、Linux、Web),PC端在发展中(Mac>Linux、Windows),在Linux和Windows上是基本不可用的状态,基建也特别少,所以目前来说是不太适用用做业务的,但是可以保持关注。

4)NW.js
Web技术代表包括NW.js和Electron,NW.js它跟Electron特别像,它一样是跨平台(Mac、Windows、Linux),基于Web来做桌面端,V0.14.7支持XP(XP市场份额约为15%),NW.js做的比较好的它支持了一个源码的加密,然后支持Chrome的扩展;它有不错的社区,但是它也有这Electron一样的缺陷,就是包体积会比较大、性能一般,代表作有微信开发工具。

5)Electron
它是一个跨平台框架(Mac、Windows、Linux、不支持XP),有着非常活跃的社区,如下图作为案例。在包体积中,因为Electron将整个Chromium都打进去了,所以哪怕你的代码只有一行Hello World,包体积也会达到50M,同时性能相比Native和QT都会差一些。

more…

在这里插入图片描述

 技术架构与原理

1、Chromium架构:
了解Electron的架构和原理、Electron的多进程架构以及我们的Chromium和Node.js是怎么一起工作的。Electron是基于Chromium做的,如果想了解Electron得先了解Chromium架构,如下图为Chromium架构:

在这里插入图片描述

 Chromium本质是Chrome的开源版,也是一个浏览器,浏览器也是一个桌面应用,它需要去创建窗口、右键菜单、管理浏览器Tab页面还有扩展程序等等,而处理这些事项的进程,我们称它为主进程,也就是如图中的Browser,而对应每个具体页面的进程,我们称它为渲染进程,对应的就是Render。在一个浏览器里面,它会有一个Browser,多个页面,而这两个进程需要通信交互才能运转的,如果大家对Linux或者进程有一定了解,两个进程它就需要跨进程通信,也就是所谓的IPC。我们主进程的RendererProcessHost以及Render进程的RenderProcess就是专门用来处理IPC事件。接下来将一下渲染进程具体内容,首先是RenderView,我们最熟悉的页面就是在RenderView中,基于Webkit排版展示出来的。最后只剩下一个ResourceDispatcher,是用来处理我们的资源请求,当我们的页面需要请求资源的时候,会通过ResourceDispatcher,然后创建一个请求ID,然后转发到我们的IPC,在我们的Browser进程里处理然后返回。本质上图带给我们有三点分别是:
① Chromium是多进程架构,包括Browser和多个Render;
② 进程间是需要IPC通信;
③ 我们Web关注到的只是很小一部分
2、Electron架构:
接下来我们来看一下Electron的大体架构,如下图:

在这里插入图片描述

 

由于Electron使用了Chromium来展示Web页面,所以Chromium的多进程架构也会被使用到Electron,在Electron中也分为主进程、渲染进程,但是跟Chromium不一样的有两点:① 我们在各个进程里暴露了一些Native API;② 我们引入了Node.js,于是我们在Electron中,可以使用Chromium和Node,比如我们可以通过Node去管理窗口,然后在页面中我们可以使用Node库。其实这很不容易的,因为在主线程中同一个时间下,只能运行一个事件循环,但是Node.js它的事件循环是基于libuv,但Chromium基于message bump,这就是Electron原理的重点就是如何整合事件循环:①Chromium的messagebump用libuv实现一次,比如像NW.js就是这么做的。②Node.js集成到Chromium。

可以简单的理解为Electron为web项目套上了Node.js环境的壳,使得我们可以调用Node.js的丰富的API。这样我们可以用JavaScript来写桌面应用,拓展很多我们在web端不能做的事情。
在这里插入图片描述

 

Electron 快速上手

1、 初始化工程

创建 Electron 工程方式与前端项目别无二致,创建一个目录,然后用 npm 初始化:

mkdir hello-electron && cd hello-electron
npm init -y
 

生成之后的 package.json 应该长这样。

{
  "name": "hello-electron",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

2、安装依赖

npm install --save-dev electron
 

安装过程中,electron 模块会去 Github 下载 预编译二进制文件,然而下载速度大家都懂的,可能会出现下载失败的情况。这里可以使用 taobao 的镜像源来下载。

npm config set electron_mirror http://npm.taobao.org/mirrors/electron/
npm config set electron_custom_dir "8.1.1"
 

为了更方便的启动我们的程序,可以新增一条命令。

{
  "scripts": {
    "start": "electron ."
  }
}

接下来,就让我们愉快地编码吧。

3、创建 HTML

在 Electron 中,每个窗口都可以加载本地或者远程 URL,这里我们先创建一个本地的 HTML 文件。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Electron <span id="electron-version"></span>
  </body>
</html>

这里你可能会注意到, span 标签里面是空文本,后面我们会动态插入 Electron 的版本。

4、创建入口文件
类似于 Node.js 启动服务,Electron 启动也需要一个入口文件,这里我们创建 index.js 文件。在这个入口文件里,需要去加载上面创建的 HTML 文件,那么如何加载呢? Electron 提供了两个模块:

-- app 模块,它控制应用程序的事件生命周期。
-- BrowserWindow 模块,它创建和管理应用程序 窗口。
入口文件是 Node.js 环境,所以可以通过 CommonJS 模块规范来导入 Electron 的模块。同时添加一个 createWindow() 方法来将 index.html 加载进一个新的 BrowserWindow 实例。
 

// index.js
const { app, BrowserWindow } = require('electron');
function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })
  win.loadFile('index.html')
}
 

那么在什么时候调用createWindow方法来打开窗口呢?在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口。可以通过使用app.whenReady() API 来监听此事件。

 // index.js
app.whenReady().then(() => {
  createWindow()
})

这样一来就可以通过以下命令打开Electron应用程序了!

// 这里会自动去找package.json的main字段对应的文件运行
// 当然 你也可以将命令放进 script 里面
npx electron .

 

运行完打开的应用程序如下图所示。
图片

5、管理窗口的声明周期
虽然现在可以打开一个浏览器窗口,但还需要一些额外的模板代码使其看起来更像是各平台原生的。应用程序窗口在每个 OS 下有不同的行为,Electron 将在 app 中实现这些约定的责任交给开发者们。可以使用 process.platform属性来为不同的操作系统做处理。

(1)关闭所有窗口时退出应用(Windows & Linux)
在 Windows 和 Linux 上,关闭所有窗口通常会完全退出一个应用程序。 app 模块可以监听所有窗口关闭的事件 window-all-closed,在事件回调里可以调用 app.quit() 退出应用。

// index.js
app.on('window-all-closed', function () {
  // darwin 为 macOS
  if (process.platform !== 'darwin') app.quit()
})
 

(2)没有窗口打开则打开一个新窗口(macOS)
用过 macOS 的人应该都知道,一个应用没有窗口打开的时候,也是可以继续运行的,这时如果打开应用程序,就会打开新的窗口。 app 模块可以监听应用激活事件 activate,在事件回调里可以判断当前窗口数量来确定需不需要打开一个新的窗口。因为窗口无法在 ready 事件前创建,你应当在你的应用初始化后仅监听 activate 事件。通过在您现有的 whenReady() 回调中附上您的事件监听器来完成这个操作。
 

// index.js
app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})
 

6、预加载脚本

前面讲到我们会在 HTML 文件中插入 Electron 的版本号。然而,在 index.js 主进程中,是不能编辑 DOM 的,因为它无法访问到渲染进程 document 上下文,它们存在于完全不同的进程中。

     这时候,预加载脚本就可以派上用场了。预加载脚本在渲染进程加载之前加载,并有权访问两个渲染进程全局 (例如 window 和 document) 和 Node.js 环境。

(1)创建预加载脚本
创建一个名为 preload.js 的新脚本如下:

window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector);
    if (element) element.innerText = text;
  }
  
  replaceText('electron-version', process.versions.electron);
})
 

我们需要在初始化 BrowserWindow 实例的时候,传入该预加载脚本。

// 在文件头部引入 Node.js 中的 path 模块
const path = require('path')
// 修改现有的 createWindow() 函数
function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })
  win.loadFile('index.html')
}
// ...

然后重新启动程序,就可以看到 Electron 的版本了。
 

图片

 

Electron 的流程模型
前面讲到了主进程、渲染进程等概念性知识,初学者可能会对此比较迷惑,不过,进行 Electron,对这一块内容的掌握是至关重要的,后面的 IPC 进程通信,也与此有关。实际上,Electron继承了来自 Chromium 的多进程架构,作为工程师,对于浏览器进程架构有所了解,也是非常有必要的。

1、主进程
每个 Electron 应用都有一个单一的主进程,作为应用程序的入口点,比如上面的 index.js。主进程在 Node.js 环境中运行,这意味着它具有 require 模块和使用所有 Node.js API 的能力。主进程一般包括以下三大块:

-- 窗口管理:使用 BrowserWindow 模块创建和管理应用窗口。类的每个实例创建一个应用程序窗口,且在单独的渲染器进程中加载一个网页。
-- 应用生命周期:主进程可以使用 Electron 提供的 app 模块来控制应用程序的生命周期。
-- 原生 API: Electron 有着多种控制原生桌面功能的模块,例如菜单、对话框以及托盘图标。
 

2、渲染进程
每个打开的BrowserWindow都会生成一个单独的渲染进程。渲染进程负责渲染网页实际的内容。因此,渲染进程中运行的代码,几乎跟我们编写的 Web 代码别无二致。除此之外,渲染进程也无法直接访问 require或其他Node.js API。

注意:实际上渲染进程可以生成一个完整的 Node.js 环境以便于开发。在过去这是默认的,但如今此功能考虑到安全问题已经被禁用。
 

3、预加载脚本
前面上手的时候已经讲过预加载脚本了,预加载(preload)脚本会在渲染进程网页内容开始加载之前执行,并且可以访问 Node.js API。由于预加载脚本与渲染器共享同一个全局 Window 接口,因此它通过在 window 全局中暴露任意您的网络内容可以随后使用的 API 来增强渲染器。

不过我们不能在预加载脚本中直接给 window 挂载变量,因为contextIsolation是默认的。

 window.myAPI = { desktop: true }
console.log(window.myAPI) // => undefined

Electron这样做是为了将预加载脚本与渲染进程的主要运行环境隔离开来的,以避免泄漏任何具特权的 API 到网页内容代码中。(比如有些人会把ipcRenderer.send的方法暴露给web 端,这将允许网站发送任意的 IPC 消息)

我们也可以关闭contextIsolation,不过不建议这么做。
new BrowserWindow({
  // ...
  webPreferences: {
      // ...
    contextIsolation: false
  }
})
 

最好使用contextBridge 模块来安全地实现交互:

const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
  desktop: true
})
console.log(window.myAPI)// => { desktop: true }
 

Electron IPC 通信

Electron 有主进程和渲染进程,之间会有许多通信,这样就涉及到了进程间通信(IPC,InterProcess Communication)。在Electron中,主线程和渲染进程之间进行通信,只要是用到以下两个模块:

-- ipcMain : ipcMain是一个 EventEmitter的实例。当在主进程中使用时,它处理从渲染器进程(网页)发送出来的异步和同步信息。从渲染器进程发送的消息将被发送到该模块。
-- ipcRenderer: ipcRenderer是一个 EventEmitter的实例。你可以使用它提供的一些方法从渲染进程 (web 页面) 发送同步或异步的消息到主进程。也可以接收主进程回复的消息。

1、渲染进程给主线程发送消息,主线程回复

(1)普通脚本监听
普通脚本引入 electron 的 ipcRenderer 模块,实现发送消息。

在 HTML 文件添加 renderer.js 脚本

const { ipcRenderer } = require('electron')
ipcRenderer.on('main-message-reply', (event, arg) => {
  console.log(arg);
});
ipcRenderer.send('message-from-renderer', '渲染进程发送消息过来了');
 

在 index.js 入口文件引入 ipcMain 模块,并修改 BrowserWindow 的实例化参数,开启渲染进程的 Node.js 环境。

const { ipcMain } = require('electron')
function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      // 这里开启后 渲染进程就可以用 NodeJS 环境
      // 可以引如 Electron 相关模块
      nodeIntegration: true,
      contextIsolation: false,
    },
  });
  mainWindow.loadFile('index.html');
}

ipcMain.on('message-from-renderer', (event, arg) => {
  console.log(arg);
  // 接收到消息后可以回复
  event.reply('main-message-reply', '主进程回复了')
})

启动应用,可以在命令行看到渲染进程发过来的消息了。

图片

 图片

 (2)预加载脚本暴露接口
在预加载脚本中,可以暴露一些全局的接口给到渲染进程,然后渲染进程调用,从而达到通信的目的。这种方式类似于微信 SDK,不用侵入到前端脚本去监听事件,较为安全。

// preload.js
const { contextBridge, ipcRenderer } = require('electron')

// 这里暴露一个全局myAPI变量
contextBridge.exposeInMainWorld('myAPI', {
  getMessage(args) {
      ipcRenderer.send('message-from-proload', args);
      consoloe.log('前端调用了:', args)
  }
})
 

renderer.js直接调用暴露出来的接口。

// renderer.js
window.myAPI.getMessage('postMessage');
 

index.js主进程监听预加载脚本发送过来的信息。

ipcMain.on('message-from-proload', (event, arg) => {
  console.log(arg);
  // 接收到消息后可以回复
  event.reply('main-message-reply', '主进程回复了')
})
 

2、主线程给渲染进程发送消息

renderer.js改为如下代码,监听主线程发送过来的消息。

const { ipcRenderer } = require("electron");

ipcRenderer.on("message", (event, arg) => {
  console.log("主进程主动推消息了:", arg);
});
 

主线程往渲染进程发送消息,需要用到 webContents。 webContents是一个 EventEmitter,负责渲染和控制网页,是BrowserWindow对象的一个属性。修改一下index.js 文件。

function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: true,
      contextIsolation: false,
    },
  });

  const contents = mainWindow.webContents;
  mainWindow.loadFile('index.html');
  contents.openDevTools(); //打开调试工具

  contents.on("did-finish-load", () => {
    //页面加载完成触发的回调函数
    contents.send("main-message-reply", "我看到你加载完了,给你发个信息");
  });
}


 

运行应用,就可以在渲染进程中打开看到消息了。
在这里插入图片描述

 

以上的通信方式均为异步,不过 Electron也提供了同步的通信方式,但是同步的方式会阻塞代码的执行,最好都使用异步通信。同步用法在这里不多作介绍。

ipcMain和ipcRenderer模块还有一些其他的通信 API,不过大抵都是类似的通信方式,需要了解的同学可以自行去查阅文档。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/882149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何仅用几分钟就能破解8个字符长的密码?

安全专家一直建议我们创建复杂的强密码&#xff0c;以保护我们的在线账户和数据免受狡猾的网络犯罪分子的攻击。“复杂”通常意味着使用大小写字母、数字&#xff0c;甚至特殊符号。但是据安全公司Hive Systems的研究显示&#xff0c;如果密码所含的字符不够多&#xff0c;密码…

解读2023年上半年财报:营收净利双增长,珀莱雅离高端还有多远?

夏季炎热&#xff0c;防晒类产品的销量暴涨。根据千牛数据&#xff0c;防晒衣今年5月全网搜索人数同比增长15%&#xff0c;加购人数同比增长29.8%&#xff0c;访问人数同比增加42%。消费者狂热的防晒需求&#xff0c;孕育着巨大的商机&#xff0c;许多企业开始瞄准这一机会。而…

python命令行参数argparse的简单使用

1、终端中执行脚本程序 pycharm的终端中执行 python xxx.py命令行中执行程序 2、获取命令行输入的参数 import sysprint(sys.argv) 3.专门处理命令行的library&#xff1a;argparse 添加optional arguments参数&#xff1a;默认是可选的&#xff0c;意味着可以不用填写 p…

08 - 追加commit和修改最新的commit message

查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;GIT常用场景- 目录 文章目录 1. 追加提交2. 修改最新的commit message 1. 追加提交 将改动追加到上一次的commit 现在我已经修改了Readme文件并且已经add、commit操作&#xff0c;但是还没有push到远程仓库&#x…

ubuntu安装jdk、emqx、nginx

一、安装jdk 要在Ubuntu上安装JDK 1.8&#xff0c;您可以按照以下步骤进行操作&#xff1a; 打开终端&#xff08;CtrlAltT&#xff09;。确保您的系统已更新&#xff1a; sudo apt update sudo apt upgrade安装OpenJDK 8&#xff1a; sudo apt install openjdk-8-jdk安装完成…

【CTFshow】——PWN签到题

文章目录 一【题目环境】二【题目类别】三【题目编号】四【题目描述】五【解题思路】六【解题过程】七【提交结果】 一【题目环境】 名称版本Ubuntu系统22.04.1 LTSLinux内核5.15.0-43-generic 二【题目类别】 此题无特殊类别&#xff0c;为入门题 三【题目编号】 PWN签到…

AI作文 - 文案创作工具

现在的AI工具越来越厉害&#xff0c;于是我也探索了一番&#xff0c;确实牛&#xff0c;下面是我探索的一些关于文案创作的功能&#xff0c; 诗词创作 视频脚本创作 歌词创作 剧本创作 文本续写 文本扩写 文本改写 撰写发言稿 心得体会 撰写演讲稿 撰写获奖感言 撰写招标书 撰…

cesium学习记录08-鼠标绘制多边形

上一篇学习了实体的一些基础知识&#xff0c;这一篇来学习鼠标绘制实体多边形的实现 1&#xff0c;结果显示 贴地&#xff1a; 不贴地&#xff1a; 2&#xff0c;方法全部代码&#xff1a; 主方法&#xff1a; /*** 绘制多边形* param {Object} option* param {Boolean} op…

数据库概述、部署MySQL服务、必备命令、密码管理、安装图形软件、SELECT语法 、筛选条件

Top NSD DBA DAY01 案例1&#xff1a;构建MySQL服务器案例2&#xff1a;密码管理案例3&#xff1a;安装图形软件案例4&#xff1a;筛选条件 1 案例1&#xff1a;构建MySQL服务器 1.1 问题 在IP地址192.168.88.50主机和192.168.88.51主机上部署mysql服务练习必备命令的使用 …

epoll数据结构

目录 1.大量的fd 集合。选择什么数据结构&#xff1f;2、Epoll 数据结构Epitem 的定义Eventpoll 的定义 1.大量的fd 集合。选择什么数据结构&#xff1f; 查找频率很高的数据结构 1.红黑树 2.哈希&#xff08;扩容缩容&#xff09; 3. b/btree &#xff08;降低树的高度&#…

D. Problem with Random Tests

Problem - 1743D - Codeforces 思路&#xff1a;因为是或&#xff0c;所以答案一定会比原串更大&#xff0c;并且为了保留更多的1&#xff0c;我们可以选择原串作为其中一个串&#xff0c;另一个串则要找到第一个为0的位置&#xff0c;我们希望让这个为1&#xff0c;为了让这个…

汇编语言--操作系统入门

计算机真正能够理解的是低级语言,它专门用来控制硬件。汇编语言就是低级语言,直接描述/控制 CPU 的运行。如果你想了解 CPU 到底干了些什么,以及代码的运行步骤,就一定要学习汇编语言。 CPU 只负责计算,本身不具备智能。你输入一条指令(instruction),它就运行一次,然后…

仓库库存管理难点在哪?有哪些仓库库存管理软件?

仓库库存管理常见的难点有&#xff1a;库存数据混乱、库存成本较高、库存积压严重等问题 使用仓库管理软件&#xff0c;企业可以更好地管理库存、优化供应链、提高操作效率&#xff0c;并基于准确的数据进行决策和规划&#xff0c;从而解决许多仓库库存管理中的难题。 一、仓库…

微信开发之一键修改好友备注的技术实现

简要描述&#xff1a; 修改好友备注 请求URL&#xff1a; http://域名地址/modifyRemark 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说…

【server组件】——mysql连接池的实现原理

目录 1.池化技术 2.数据库连接池的定义 3.为什么要使用连接池 4. 数据库连接池的运行机制 5. 连接池与线程池的关系 6. CResultSet的设计 6.1构造函数 7. CDBConn的设计 6.1.构造函数 6.2.init——初始化连接 8.数据库连接池的设计要点 9.接口设计 9.1 构造函数 …

美好发展 商密见“郑” | GBASE南大通用亮相2023商用密码大会

本届大会以“密码赋能美好发展”为主题&#xff0c;全国商用密码主管部门及相关企业齐聚一堂&#xff0c;探讨产业发展趋势&#xff0c;解读政策法规&#xff0c;集中呈现我国商用密码理论、技术、产品、服务、应用等最新成果&#xff0c;吸引了300余家企业参展&#xff0c;参观…

京喜详情API接口大药房API接口详情获取jason

通过调用该API接口&#xff0c;商家可以获取商品的详细信息&#xff0c;包括商品名称、价格、库存、销量等。基于这些信息&#xff0c;商家可以根据自身的营销策略进行推广和销售 京喜商品详情API接口具有高度的可定制性。商家可以根据自身的需求来选择获取的信息内容&#xff…

论文解读 | 5分钟带你了解基于深度学习的点云配准的ICP算法

原创 | 文 BFT机器人 01 摘要 迭代最近点&#xff08;ICP&#xff09;及其变式为此任务提供了简单且易于实现的迭代方法&#xff0c;但这些算法可能会收敛到虚假的局部最优值。 为了解决ICP通道中的局部最优和其他困难&#xff0c;我们提出了一种基于学习的方法&#xff0c;名…

自适应巡航辅助ACC

1.自适应巡航辅助功能描述 自适应巡航控制&#xff08;Adaptive Cruise Control&#xff09;&#xff0c;它通过单目摄像头与雷达数据融合来检测前方车辆距离及相对速度&#xff0c;控制油门和刹车系统以实现稳定跟随前方车辆&#xff0c;且达到驾驶员设定的目标时距。在没有前…

一文带你了解10倍股票杠杆是什么?

10倍股票杠杆是一种投资策略&#xff0c;其核心原理是通过借贷的方式将投资本金放大到原始资金的十倍。假设你有1000元的投资本金&#xff0c;使用10倍杠杆&#xff0c;你可以借贷额外的9000元&#xff0c;使你的总投资金额达到10000元。 使用10倍股票杠杆的主要目的是提高投资…