Electron 和 Angular 项目升级

news/2024/11/24 16:38:47/

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.ppmy.cn/news/495235.html

相关文章

手机资料小摘

一、各种品牌手机中英文对照 Acer:&#xff1a;宏基 AIWA&#xff1a;爱华 alcatel&#xff08;ALC&#xff09;&#xff1a;阿尔卡特 AMOI&#xff1a;夏新 APBW&#xff1a;亚太 APPLE&#xff1a;苹果 Arcoa&#xff1a;全虹 ASUS&#xff1a;华硕 AUX&#xff1a;奥克斯 Be…

真正的手机密码大全!(整理完整版)

手机一旦设的密码忘记了怎么办&#xff1f;很多人到手机修理的地方或者厂方去解锁&#xff0c;往往收取不菲的费用&#xff0c;其实很多手机只要自己输入解锁码就可以了。以下收集整理的满全了应该。 一、各种品牌手机中英文对照 Acer:&#xff1a;宏基 AIWA&#xff1a;爱华 a…

C++基础(4)——类和对象(2)

前言 本文主要介绍了C中类和对象的基本知识。 4.2.5&#xff1a;深拷贝和浅拷贝 浅拷贝&#xff1a;编译器给我们提供的拷贝函数就是等号复制操作 深拷贝&#xff1a;自己手动重写一个拷贝构造函数&#xff0c;重新new 浅拷贝会出现的问题&#xff1a;如果使用编译器提供的…

Redis安装说明(heima)

Redis安装说明&#xff08;heima&#xff09; 笔者的redis(Linux版)的下载链接地址&#xff1a;https://download.csdn.net/download/weixin_46411355/87926624 笔者的redis图形化桌面客户端&#xff0c;下载链接地址为&#xff1a;https://download.csdn.net/download/weixin…

正在使用计算机突然停电怎么办,电脑突然断电怎么办?电脑突然断电开不了机解决教程...

在使用电脑的过程中&#xff0c;相信不少用户都遇到过电脑突然断电的情况。不正常的开关机都会对电脑产生影响。有用户电脑电脑突然断电后开不了机&#xff0c;遇到这种情况应该怎么办呢&#xff1f;下面就让小编为大家带来电脑突然断电开不了机解决教程。 第1步&#xff1a;首…

服务器因为断电启动不了

1、系统启动不起来&#xff0c;主要原因是关机的时候没有停止服务&#xff0c;直接相当于断电 系统启动的时候进度条的时候会报错内存溢出。 1.1首先进入单用户模式 进入控制台倒计时的时候按e–>e–>enter–>输入single–>b 1.2进入营救模式 关机–>编辑设置–…

计算机主机电池馈电,电脑主机电池没电引起故障怎么处理

主板的故障千奇百怪&#xff0c;虽然大部分时候电脑无法正常启动是由主板硬件损坏所导致的&#xff0c;但也有相当多莫名其妙的故障情况是因为主板电池引起的。主板电池没电了会导致主板coms(BIOS)设置保存不了&#xff0c;电脑从而会出现各种故障。下面是学习啦小编给大家整理…

计算机启动突然断电,电脑启动运行过程主机突然断电怎么办

有朋友跟小编说“我的电脑开机经常突然断电,断电以后就不能启动了,感觉就不通电了 ”,那么电脑启动运行过程主机突然断电怎么办呢?小编为大家分享了解决电脑启动运行过程主机突然断电的方法,下面大家跟着秋天网 Qiutian.ZqNF.Com小编一起来了解一下吧。 电脑启动运行过程主机…