跳至主要内容
版本:v8

运行时问题

空白应用程序

注意

我的应用程序没有错误。为什么它显示空白屏幕?

可能有多种原因导致这种情况。如果您无法在 Ionic 论坛 上找到解决方案,请确保

  • 没有为旧的浏览器/Android 版本包含 Polyfills。

对于使用 `@angular/[email protected]` 或更高版本的项目,Polyfills 将自动包含。对于在此之前创建的项目,需要手动启用 Polyfills。

在 `src/polyfills.ts` 中,您必须启用所有 ES6 Polyfills 以支持 Android 4.4。

或者,可以更新项目以使用最新版本的 `@angular/cli` 包和 `@angular-devkit` 包,并在 `angular.json` 的构建选项对象中包含 `es5BrowserSupport` 选项。

        "input": "src/global.scss"
}
],
- "scripts": []
+ "scripts": [],
+ "es5BrowserSupport": true
},
"configurations": {
"production": {

这将自动包含需要它们的旧浏览器的 Polyfills。

指令不起作用

注意

为什么我的自定义组件/指令不起作用?

您可以检查以下几个方面。请确保

  • 您的选择器没有任何拼写错误。
  • 您正在将选择器用作属性、元素或类。
  • 您的选择器具有正确的语法
    • `[attr]`(如果它是属性选择器)
    • `element`(如果它是元素选择器)
    • `.class`(如果它是类选择器)

以下是如何使用属性选择器的示例

@Directive({
selector: '[my-dir]' // <-- [my-dir] because it is an attribute
}) // Could be my-dir, [my-dir], .my-dir
class MyDir {
constructor() {
console.log('I'm alive!');
}
}

@Component({
// We add my-dir as an attribute to match the directive's selector
template: `<div my-dir>Hello World</div>`,

// Alternatively, if you were attaching the directive to an element it would be:
// template: `<my-dir>Hello World</my-dir>`
// and if you were attaching by class the template would be:
// template: `<div class="my-dir">Hello World</div>`

directives: [MyDir] // <-- Don't forget me! (only if your ionic-angular version is below RC0)
})
class MyPage { }

单击延迟

注意

为什么我的单击事件存在延迟?

一般来说,我们建议只将 `(click)` 事件添加到通常可点击的元素。这包括 `<button>` 和 `<a>` 元素。这将改善可访问性,因为屏幕阅读器将能够识别元素是可点击的。

但是,您可能需要将 `(click)` 事件添加到通常不可点击的元素。当您这样做时,您可能会遇到从单击元素到事件触发之间 `300ms` 的延迟。要消除此延迟,您可以将 `tappable` 属性添加到元素。

<div tappable (click)="doClick()">I am clickable!</div>

Angular 更改检测

注意

为什么我的组件初始化时,Angular 更改检测运行得非常频繁?

Angular 使用名为 zone.js 的库,该库帮助它确定何时运行更改检测。

从 zone.js `0.8.27` 开始,某些 Web 组件的 API 也会导致更改检测运行。这会带来不希望有的副作用,即当大量组件初始化时,应用程序会变慢。

要防止这种情况发生,可以禁用管理更改检测这部分的 zone.js 标志。在应用程序的 `src` 目录中,创建一个名为 `zone-flags.ts` 的文件。将以下代码放入该文件

(window as any).__Zone_disable_customElements = true;

然后,需要将 `zone-flags.ts` 文件导入应用程序的 `polyfills.ts` 文件中。请务必在导入 `zone.js` 之前导入它。

...

import './zone-flags.ts';
import 'zone.js/dist/zone'; // Included with Angular CLI

...

此更改仅影响依赖于 zone.js `0.8.27` 或更新版本的应用程序。旧版本不受此更改的影响。

注意

通过以下方式创建 Ionic 应用程序时,此标志将自动包含:

Ionic CLI。

Cordova 插件在浏览器中不起作用

在开发的某个阶段,您可能会尝试调用 Cordova 插件,但会收到警告

[Warning] Native: tried calling StatusBar.styleDefault, but Cordova is not
available. Make sure to include cordova.js or run in a device/simulator
(app.bundle.js, line 83388)

当您尝试调用本地插件,但 Cordova 不可用时,就会发生这种情况。值得庆幸的是,Ionic Native 会打印一个友好的警告,而不是错误。

在其他情况下,如果插件未通过 Ionic Native 使用,插件可能会打印一个更模糊的警告。

EXCEPTION: Error: Uncaught (in promise): TypeError: undefined is not an object
(evaluating 'navigator.camera.getPicture')

如果发生这种情况,请在真实设备或模拟器上测试插件。

提供程序的多个实例

如果您在每个组件中注入一个提供程序,因为您希望它对所有组件都可用,那么您最终将获得该提供程序的多个实例。如果您希望提供程序对子组件可用,则应在父组件中注入一次提供程序。

let id = 0;
export class MyService {
id: number;

constructor() {
this.id = id++;
}
}

@Component({
selector: 'my-component',
template: 'Hello World',
providers: [MyService], // <-- Creates a new instance of MyService :(
}) // Unnecessary because MyService is in App's providers
class MyComp {
// id is 1, s is a different MyService instance than MyApp
constructor(s: MyService) {
console.log('MyService id is: ' + s.id);
}
}

@Component({
template: '<my-component></my-component>',
providers: [MyService], // MyService only needs to be here
directives: [MyComp],
})
class MyApp {
// id is 0
constructor(s: MyService) {
console.log('MyService id is: ' + s.id);
}
}

在函数回调中访问 `this` 返回 `undefined`

某些组件(如 ion-input 上的 counterFormatterion-range 上的 pinFormatter)允许开发人员传递回调。如果您打算从回调的上下文中访问 `this`,那么绑定正确的 `this` 值很重要。使用 Angular 组件或在 React 中使用类组件时,您可能需要访问 `this`。有两种方法可以绑定 `this`

绑定 `this` 的第一种方法是在函数实例上使用 `bind()` 方法。如果您想传递一个名为 `counterFormatterFn` 的回调,那么您将编写 `counterFormatterFn.bind(this)`。

绑定 `this` 的第二种方法是在定义回调时使用 箭头函数。这是有效的,因为 JavaScript 不会为箭头函数创建新的 `this` 绑定。

有关 `this` 在 JavaScript 中的工作原理的更多信息,请参阅其 MDN 页面