Electron 和 Angular 项目升级

news2024/11/23 21:19:13

Electron 和 Angular 项目升级: Angular4+Electron1.7.8 升级到 Angular13+Electron2

原项目 Angular 和 Electron 版本:

  • @angular/cli: 1.4.9
  • @angular/core: 4.4.6
  • Electron: 1.7.8

升级后 Angular 和 Electron 版本:

  • Angular: 13.3.1
  • Electron: 21.2.1

流程:

angular-electron 这是一个结合 Angular 和 Electron 的项目。以此为基准环境,不需要从头构建。这个项目的 Angular13 对应的 electron 为 v18,再手动到升级 electron21.2.1,不升级也没有问题。将之前项目的核心代码复制过来,查看每一个文件,找出所有的问题。原项目文件结构如图:

升级前项目目录结构

将 src 复制到对应目录下。主进程文件 main.ts 放置再 app 文件夹中。
原先主进程文件 main.ts 在项目根目录下,主进程 main.ts 中使用的静态资源在 src/assets 中。现在主进程 main.ts 更换位置,所以主进程中使用的静态资源需要放置在 app 中,并且打包编译后需要用到。
现目录文件结构如图:

升级后项目目录结构

然后开始检查代码,首先发现的是一些语法问题,这些因语法检查而发生错误的代码,并不代码写得不对。比如变量命令需要遵循驼峰规则,字符串需要单引号,语句结束需要分号等待。这样错误应该暂时忽略。而报错的原因是,新项目的 package.json 会安装一些 eslint 相关的插件解析语法问题,建议删除这些插件或者不安装这些插件。如果保留这些插件,则代码需要符合 TypeScript 语法规则。根据 Angular 更新指南 和Electron 重大更改,以及 Angular 中文官网 和 Electron 官网 检查所有文件后,总结问题如下:
Angular 问题:

Q1: import { Http } from '@angular/http'; 报错找不到模块“@angular/http”或其相应的类型声明。ts(2307)
A1: 如果使用了旧版的 HttpModule 和 Http 服务,请切换到 HttpClientModule 和 HttpClient 服务。HttpClient 简化了默认的 ergonomics(不再需要映射(map)到JSON),并且现在支持类型化的返回值和拦截器。修改为 import { HttpClient } from '@angular/common/http';

Q2: import { Renderer } from "@angular/core"; 报错 ““@angular/core”” 没有导出的成员“Renderer”。 你是否指的是“Renderer2”?ts(2724)。
A2: 无论在哪里使用了 Renderer,现在都使用 Renderer2。

Q3: import { Observable } from 'rxjs/Rx'; 找不到模块“rxjs/Rx”或其相应的类型声明。ts(2307)。
A3: 修改为 import { Observable } from 'rxjs'; Subscription、Subject、Observable 类似。

Q4: import { RequestOptions, Headers } from '@angular/http'; 找不到模块“@angular/http”或其相应的类型声明。ts(2307)。
A4: 已被 HttpRequest, HttpHeaders 代替。 import { HttpHeaders } from '@angular/common/http';

Q5: this.http.post().map((res:any)=>res.json()).catch((error: any) => Observable.throw())
A5: this.http.post().pipe(catchError((error: HttpErrorResponse) => { return throwError(error || 'Server error'); })); 不再需要映射(map)到JSON,请看这里 making-a-jsonp-request。

Q6: renderer.listenGlobal() Renderer2 没有 listenGlobal 方法。
A6: 使用 renderer.listen() 函数来实现全局事件。

Q7: this.renderer.invokeElementMethod(this.el.nativeElement, "focus"); Renderer2 没有 invokeElementMethod 方法。
A7: does not use invokeElementMethod,以下是链接中代码。

invokeElementMethod(eleRef: ElementRef, method: string) {
    if (isPlatformBrowser(this.platformId)) {
        eleRef.nativeElement[method]();
    }
}
this.invokeElementMethod(this.el.nativeElement, "focus");

Q8: import { ComponentFactoryResolver } from "@angular/core"; “ComponentFactoryResolver”已弃用。ts(6385) let subFactory = this._cfr.resolveComponentFactory(data.component);let componentRef: any = this.detailHost.viewContainerRef.createComponent(subFactory);
A8: 一个简单的注册表,它将 Components 映射到生成的 ComponentFactory 类,该类可用于创建组件的实例。用于获取给定组件类型的工厂,然后使用工厂的 create() 方法创建该类型的组件。Angular 不再需要组件工厂。请使用可以直接使用 Component 类的其他 API。弃用可以不改或者修改为: let componentRef: any = this.detailHost.viewContainerRef.createComponent(data.component);

Q9: @ViewChild(DetailContentDirective) detailHost: DetailContentDirective; createView() 输出 this.detailHost 为 undefined, 应该为 {viewContainerRef: ViewContainerRef_},低版本 angular 中可能会在 ngAfterViewInit() 之前完成。
A9: 官方文档中指出,视图查询是在 ngAfterViewInit() 回调函数被调用之前设置的。因此,不应该依赖在 ngAfterViewInit() 之前访问视图查询。

Q10: import 'zone.js/dist/zone-mix' 报错 Module not found: Error: Can’t resolve ‘fs’。
A10: 修改为 import 'zone.js'

Q11: import 'rxjs/add/operator/map'; 报错 Module not found: Error: Package path ./add/operator/map is not exported from package。
A11: map catch 与 http 返回值有关,将 http 的 response 的数据通过 map 映射为 json,选择不通过 map 映射。

Q12: this.router.events.filter 类型“Observable<Event_2>”上不存在属性“filter”。ts(2339)。
A12: 修改后:

import { filter } from 'rxjs/operators';
this.router.events.pipe(
    filter(event => event instanceof NavigationEnd)
).subscribe(() => {});

Q13: Observable.fromEvent().subscribe((event) => {}); 类型“typeof Observable”上不存在属性“fromEvent”。ts(2339)。
A13: import { fromEvent } from 'rxjs'; 直接导入 fromEvent,不需要通过 Observable。

Electron 问题:

Q1: menu.popup(win) 类型“BrowserWindow”与类型“PopupOptions”不具有相同的属性。ts(2559)。
A1: menu.popup(browserWindow?: BrowserWindow, options?: PopupOptions); => popup(options?: PopupOptions)。

Q2: dialog.showOpenDialog({ title: "选择目录", properties: ['openDirectory'] }, (files) => {}) 类型“{ title: string; properties: string[]; }”的参数不能赋给类型“BrowserWindow”的参数。对象文字可以只指定已知属性,并且“properties”不在类型“BrowserWindow”中。ts(2345)。
A2: 结构修改后代码:

dialog.showOpenDialog(mainWindow, {
  properties: ['openFile', 'openDirectory']
}).then(result => {
  console.log(result.canceled)
  console.log(result.filePaths)
}).catch(err => {
  console.log(err)
})

Q3: require('electron-reload')(__dirname, {});
A3: 修改代码后重新加载程序: require('electron-reloader')(module);

Q4: 渲染进程中 import { remote } from 'electron'; 模块““electron””没有导出的成员“remote”。ts(2305) this.remote = window.require('electron').remote; 类型“typeof CrossProcessExports”上不存在属性“remote”。ts(2339) remote.shell(),remote.app(),remote.dialog()。包括 import { app } from 'electron';import { shell } from 'electron';
A4: remote 模块在 Electron 12 废弃,并将在 Electron 14 被移除 由@electronic/remote 模块替代。在主进程中执行 import { app, shell, dialog } from 'electron';,相关用法 1.remote.app.getPath() 改为 app.getPath()。2.shell.openItem() 改为 shell.openPath()。3.remote.dialog; dialog.showOpenDialog() 改为 dialog.showOpenDialogSync(),并且需要在主进程执行。

Q5: 所有渲染进程(angular)中使用 import * as fs from 'fs';let fs = require('fs');import * as fs from 'fs-extra';,fs.readFileSync 和 fs.writeFile 方法报错。
A5: 所有 fs.readFileSync 和 fs.writeFile 操作需要在主进程执行。

Q6: 当引入 jquery 与 webuploader 时,<script src="./assets/js/jquery-3.3.1.min.js"></script><script src="./assets/js/webuploader/webuploader.js"></script>,报错 webuploader 找不到 $。
A6: 由于 Electron 主进程修改了 module 对象,引入 jquery 失败,在引入jquery 之前 <script>delete window.module;</script>

Q7: <div><button>Action 1</button> <button>Action 2</button></div> 页面上两个button 之间的空格消失。
A7: <div ngPreserveWhitespaces><button>Action 1</button> <button>Action 2</button></div>。https://angular.cn/api/core/Component#preserving-whitespace

以上是一些主要问题,或许还有一些不那么重要的问题,但是可能也会引起程序错误。
问题分为 Angular 升级带来的问题,Electron 升级带来的问题,包括 Angular 升级引起第三方模块不兼容的问题。还有一些 css 样式可能会变化,以及一些 TypeScript 语法问题。

框架升级是一件非常麻烦的事,特别是跨许多大版本升级,需要注意的事项很多,如果项目很大,升级后需要完整测试。

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

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

相关文章

一次服务器被入侵的处理过程分享

一、服务器入侵现象 近期有一个朋友的服务器(自己做了网站)好像遭遇了入侵&#xff0c;具体现象是&#xff1a; 服务器 CPU 资源长期 100%&#xff0c;负载较高。 服务器上面的服务不能正常提供服务。 ​ 朋友处理了一会没有解决&#xff0c;我开始想说我不是搞安全的&#xf…

【Visual Studio】报错 LNK2019,使用 C++ 语言,配合 Qt 开发串口通信界面

知识不是单独的&#xff0c;一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏&#xff1a;Visual Studio。 文章目录 问题解决方案Ref. 问题 使用 C 语言&#xff0c;配合 Qt 开发串口通信界面时&#xff0c;报错代码 LNK2019。 复制以下错误信息&#xff0c;方便别…

15、SQL注入之Oracel,MongoDB等注入

这里写目录标题 引言补充上篇文章Json注入案例分析 简要学习各种数据库的注入特点Access数据库Mssql数据库PostgreSQL数据库Oracle数据库MongoDB数据库 简要学习各种注入工具的使用指南 引言 mysql的注入方法跟其它的数据库注入方法是差不多的&#xff0c;是可以举一反三的&am…

【Pandas】pandas用法解析(下)

一、生成数据表 二、数据表信息查看 三、数据表清洗 四、数据预处理 ———————————————— 目录 五、数据提取 1.按索引提取单行的数值 2.按索引提取区域行数值 3.重设索引 4.设置日期为索引 5.提取4日之前的所有数据 6.使用iloc按位置区域提取数据 7…

elasticsearch8.5.2 报错(SearchPhaseExecutionException: all shards failed)

一、问题 logstash突然无法对elasticsearch服务进行读写操作了&#xff0c;提示elasticsearch的地址有问题&#xff0c;检测elasticsearch发现端口存在。查看日志发现有报错。 二、问题原因 有一些索引的数据损坏了 三、解决 官网文档&#xff1a;https://www.elastic.co/…

记录HBuilderX将uniapp项目运行到华为手机

解压并运行刚从官网下载的HBuilder X&#xff0c;新建一个项目 一、电脑下载【华为手机助手】并安装 下载地址&#xff1a; https://consumer.huawei.com/cn/support/hisuite/ 二、华为手机设置 1、手机准备&#xff1a;华为&#xff08;没有插入手机卡&#xff09;&#x…

《网络安全》0-100 零基础

网络安全基础 什么是网络安全 网络安全是指保护计算机网络不受未经授权的攻击、损伤、窃取或破坏的一系列措施。它包括保护计算机系统、网络和数据的完整性、可用性和保密性&#xff0c;以及防止未经授权的访问、使用、披露、破坏、修改、记录或丢失数据。 网络安全是保护信息…

探秘华为交换机:端口类型全解析

在下列情况下&#xff0c;判断的一般方法是什么&#xff1f; 1.交换机某个端口下的用户丢包。 2.交换机下的所有用户都在丢失数据包。 3、用户反映网速缓慢 检查网络电缆&#xff0c;重做水晶头&#xff0c;检查用户的计算机网卡&#xff0c;并重新启动交换机。 这几种做法都能…

在 PyTorch 中实现可解释的神经网络模型

动动发财的小手&#xff0c;点个赞吧&#xff01; 目的 深度学习系统缺乏可解释性对建立人类信任构成了重大挑战。这些模型的复杂性使人类几乎不可能理解其决策背后的根本原因。 ❝ 深度学习系统缺乏可解释性阻碍了人类的信任。 ❞ 为了解决这个问题&#xff0c;研究人员一直在…

chatgpt赋能python:Python中算法的几种描述方法

Python中算法的几种描述方法 在Python中&#xff0c;我们可以采用不同的方法来描述和实现不同的算法。本文将介绍三种常见的描述算法的方法&#xff0c;希望能够帮助读者更好地理解算法和Python编程。 方法一&#xff1a;自然语言描述 自然语言是我们最熟悉的方式来描述算法…

三层交换器与可配置的二层交换机通信配置(华为交换机)

#三层交换器与可配置的二层交换机通信配置 三层交换机配置 #进入系统视图 <Huawei>system-view #关闭系统提示信息 [Huawei]undo info-center enable #启动DHCP功能 [Huawei]dhcp enable #创建vlan 10 并配置 vlanif 地址 作为二层交换机默认网关 [Huawei]vlan 10 …

nodejs高版本降为低版本的详细解决方案

部分老旧项目需要使用低版本的node,网上很多是无效的,高版本无法直接安装低版本node,但是低版本nodejs可以安装部分高版本node,从而达到升级效果,下面这篇文章主要给大家介绍了关于nodejs高版本降为低版本的详细解决方案,需要的朋友可以参考下 1.首先通过控制面板应用卸载当前环…

如何使用 Swagger2 自动生成 RESTful API 文档

如何使用 Swagger2 自动生成 RESTful API 文档 在开发 RESTful API 的过程中&#xff0c;文档是非常重要的一部分。它可以帮助开发者了解 API 的功能和使用方法&#xff0c;同时也是接口设计和测试的重要依据。而手动编写 API 文档往往比较耗时且容易出错&#xff0c;这时候 S…

【kubernetes】部署controller-manager与kube-scheduler

前言:二进制部署kubernetes集群在企业应用中扮演着非常重要的角色。无论是集群升级,还是证书设置有效期都非常方便,也是从事云原生相关工作从入门到精通不得不迈过的坎。通过本系列文章,你将从虚拟机准备开始,到使用二进制方式从零到一搭建起安全稳定的高可用kubernetes集…

NodeJS 配置HTTPS协议证书⑩⑤

文章目录 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618;前言HTTPS ❓配置证书工具 CertbotCertbot 使用步骤总结 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&…

chatgpt赋能python:Python描述符详解

Python 描述符详解 Python 中的描述符是一种机制&#xff0c;用于控制属性&#xff08;attribute&#xff09;的访问。通过描述符&#xff0c;我们可以在属性被访问或者修改时加入特定的逻辑。 描述符是一个类&#xff0c;其中至少定义了以下三个方法&#xff1a; __get__(s…

docker入门手册

目录 1. docker基础 1. 1 docker介绍 1.2 docker架构与核心组件 1.3 docker安装和卸载 安装 卸载 docker加速器设置 -> 可选 1.4 权限问题 1.5 docker服务相关操作命令 2. docker镜像管理 2.1 镜像的搜索/获取/查看 镜像搜索 2.2 镜像别名/删除 2.3 镜像的导入…

Apache Atlas产品调研

元数据产品调研 &#x1f4a1; 思考可以构成一座桥&#xff0c;让我们通向新知识。—— 普朗克 一、什么是元数据 元数据是关于数据的数据&#xff0c;是为了描述数据的相关信息而存在的数据。 元数据是用数据管理数据&#xff0c;是快速查找数据、精确定位数据、准确理解数据…

CSS3-三大特性-继承性、层叠性、优先级

CSS三大特性 1 继承性 2 层叠性 3 优先级 1 继承性 特性&#xff1a;子元素有默认继承父元素样式的特点&#xff08;子承父业&#xff09; 可以继承的常见属性&#xff1a; 1 color 2 font-style、font-weight、font-size、font-family 3 text-indent、text-align 4 line-heigh…

io.netty学习(七)字节缓冲区 ByteBuf(下)

目录 前言 实现原理 ByteBuf 的使用案例 ByteBuf 的3种使用模式 堆缓冲模式 直接缓冲区模式 复合缓冲区模式 总结 前言 在了解了 ByteBuffer 的原理之后&#xff0c;再来理解Netty 的 ByteBuf 就比较简单了。 ByteBuf 是 Netty 框架封装的数据缓冲区&#xff0c;区别…