【发布时间】:2021-09-14 01:36:09
【问题描述】:
我刚刚将一个 Angular 项目从版本 11 升级到 12,包括更新到 @ng-bootstrap/ng-bootstrap(从 v6 到 v10)。
升级非常顺利,没有任何困难的改变,但是我现在面临一个与 Bootstrap 手风琴有关的奇怪问题。我注意到它在页面上不断重新渲染,导致最大调用堆栈错误。
更新:我已确定导致此问题的确切版本。它是 8.0.3 版本,仅包含用于动画的 bug fixes。
animations: don't reflow in 'ngbRunTransition' (#3962) (f699999), closes #3954 #3952
animations: make sure 'ngbRunTransition' runs inside the zone (#3957) (a006a62), closes #3950
carousel: respect [animation]="false" (#3964) (9afae34), closes #3961
我一加载页面就会出现以下错误。奇怪的是它发生后我可以与之互动。
zone.js:182 Uncaught RangeError: Maximum call stack size exceeded
at SafeSubscriber.__tryOrUnsub (Subscriber.js:191)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)
at EventEmitter_.next (Subject.js:39)
at EventEmitter_.emit (core.js:25935)
at checkStable (core.js:28594)
at onLeave (core.js:28722)
at Object.onInvoke (core.js:28678)
at ZoneDelegate.invoke (zone.js:371)
有一些非常奇怪的行为是关于它如何根据手风琴中有多少项目而出错。
1-3 项
出错后,您可以与手风琴进行交互,就好像没有错误一样。
4 项
出错后,它按预期渲染前两个面板,渲染一个空白的 3 面板,然后不渲染第 4 个面板。当您单击任何面板时,它会呈现 4th,您可以与手风琴进行交互,就好像没有错误一样。第三个面板保持空白且无法点击。
5 项
出错后,您可以与手风琴进行交互,就好像没有错误一样。
6 项
它根本不渲染,但在 html 中留下 2 个选项卡(面板)
<ngb-accordion _ngcontent-serverapp-c144="" role="tablist" activeids="acc-event_description" class="accordion" ng-reflect-active-ids="acc-event_description" aria-multiselectable="true"><!--container--><div><div role="tab"><!--container--></div><!--container--></div><div><div role="tab"><!--container--></div><!--container--></div><!--bindings={
"ng-reflect-ng-for-of": "[object Object],[object Object"
}--></ngb-accordion>
我注意到的另一个奇怪的行为是,当页面上的另一个元素更新时,它会导致手风琴多次更新。此行为在更新之前一直存在。
更新:经过一番思考,我认为这个错误是项目中另一个问题的症状。是否有常见的模式/代码/实现会导致这种奇怪的行为?即使在旧版本的手风琴中也确实会出现连续重新渲染,但是它发生的程度不足以导致最大调用堆栈错误。
疑难解答
- 我已验证,当我进行开发/产品构建以及使用 Angular Universal (SSR) 时,此错误会以完全相同的方式持续存在。
- 我可以通过不在面板上设置
id来避免错误,但是当我单击面板时,组件会以非常快的速度连续重新渲染,并自动增加它分配的id(它更新得如此之快以至于之后一秒钟,它已经将 ids 增加到超过100)。当我没有设置id时,手风琴不起作用,单击面板只会更新其id。 - 我尝试设置
[animation]="false",但没有任何影响 - 我已尝试导入
NgbModule而没有其他任何内容,以及导入特定NgbAccordionModule的另一种方法,但它没有任何区别 - 我已尝试仅将手风琴组件作为其自己的模块加载(因此不受任何其他代码的影响),它仍然具有相同的行为。
我尝试使用 Angular devbug 工具,但是因为它们无法在页面加载后立即运行(自动)我无法及时运行分析器。
我已经建立了一个示例项目,其中包含组件的外观并且它工作正常,所以我的项目中发生了一些事情现在导致了这种情况,但我似乎无法解决。
这就是组件的样子 - https://stackblitz.com/edit/angular-tp9ldq
我可以避免它的唯一方法是将面板硬编码到 HTML 中。我不能这样做,因为它们是动态获取的。我已经尝试将它们硬编码到组件中(就像堆栈闪电战链接一样),但它仍然出错。
这是我正在使用的依赖项,这里有什么明显需要升级的地方吗?当我运行ng update 时,它说一切似乎都井然有序。
"dependencies": {
"@angular/animations": "~12.2.5",
"@angular/common": "~12.2.5",
"@angular/compiler": "~12.2.5",
"@angular/core": "~12.2.5",
"@angular/forms": "~12.2.5",
"@angular/localize": "~12.2.5",
"@angular/platform-browser": "~12.2.5",
"@angular/platform-browser-dynamic": "~12.2.5",
"@angular/platform-server": "~12.2.5",
"@angular/router": "~12.2.5",
"@auth0/angular-jwt": "^5.0.2",
"@bugsnag/js": "^7.4.0",
"@bugsnag/plugin-angular": "^7.4.0",
"@ng-bootstrap/ng-bootstrap": "^10.0.0",
"@nguniversal/express-engine": "^12.1.0",
"@techiediaries/ngx-qrcode": "^9.1.0",
"@types/url-parse": "^1.4.3",
"bootstrap": "^4.5.0",
"core-js": "^3.17.3",
"express": "^4.17.1",
"hammerjs": "^2.0.8",
"jquery": "^3.3.1",
"less": "4.1.1",
"lodash": "^4.17.21",
"logrocket": "^1.0.3",
"moment": "^2.24.0",
"ngx-barcode": "^0.3.0",
"ngx-connection-service": "^7.0.3",
"ngx-cookie": "^5.0.2",
"ngx-cookie-backend": "^5.0.2",
"popper.js": "^1.14.7",
"rxjs": "~6.6.7",
"sanitize-html": "^2.5.0",
"tslib": "^2.3.1",
"url-parse": "^1.4.7",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~12.2.5",
"@angular-eslint/builder": "12.4.1",
"@angular-eslint/eslint-plugin": "12.4.1",
"@angular-eslint/eslint-plugin-template": "12.4.1",
"@angular-eslint/schematics": "12.4.1",
"@angular-eslint/template-parser": "12.4.1",
"@angular/cli": "~12.2.5",
"@angular/compiler-cli": "~12.2.5",
"@angular/language-service": "~12.2.5",
"@nguniversal/builders": "12.1.0",
"@types/core-js": "^2.5.5",
"@types/express": "^4.17.13",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"@types/lodash": "^4.14.172",
"@types/node": "^16.9.0",
"@types/sanitize-html": "^2.3.2",
"@types/stripe-checkout": "^1.0.4",
"@types/stripe-v3": "^3.1.25",
"@typescript-eslint/eslint-plugin": "4.28.2",
"@typescript-eslint/parser": "4.28.2",
"codelyzer": "^6.0.2",
"eslint": "^7.26.0",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "^5.1.1",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-firefox-launcher": "^2.1.0",
"karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"karma-junit-reporter": "^1.2.0",
"karma-spec-reporter": "0.0.32",
"npm-run-all": "^4.1.5",
"protractor": "^7.0.0",
"rimraf": "^3.0.2",
"ts-node": "^10.2.1",
"tslint": "^6.1.3",
"typescript": "~4.3.5"
},
这是我的 Angular 项目的构建部分
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/frontend/browser",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": ["src/assets", "src/.well-known"],
"allowedCommonJsDependencies": ["lodash", "@bugsnag/js", "ngx-barcode", "url-parse", "sanitize-html"],
"styles": ["node_modules/bootstrap/dist/css/bootstrap.min.css", "src/styles.less"],
"scripts": [
"./node_modules/jquery/dist/jquery.slim.min.js",
"./node_modules/popper.js/dist/umd/popper.min.js"
]
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all",
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
]
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
【问题讨论】:
-
你有没有用 angular-dev 工具查看过它,也许有一个特定的事件不断冒泡,导致循环? (angular.io/guide/devtools) 如果你创建一个生产版本也是一样的吗?
-
@EricKrg 我已经用我今天做的进一步故障排除更新了这个问题。
标签: angular typescript rendering angular-bootstrap