NativeScript中出现TypeError: document.createElement is not a function错误求助
Looks like you're hitting a classic environment mismatch issue here—NativeScript runs in a native mobile context, not a browser, so the document object your RxJS code is trying to access doesn't exist. Let's break down the problem and fix it with two practical approaches.
Why This Error Happens
Your current RxJS setup uses Observable.interval(1) without specifying a scheduler, which defaults to a browser-focused scheduler that tries to create DOM elements for timing. NativeScript can't support this, hence the error. On top of that, there's a typo in your timeElapsed calculation (Date.now() - Date.now() will always return 0—easy mistake!).
Approach 1: Fix the RxJS Implementation
We'll adjust the RxJS code to use NativeScript-compatible schedulers and correct the timing logic:
import { Component } from "@angular/core"; import { Observable, Scheduler } from "rxjs"; import { Label } from 'ui/label'; // Use proper RxJS operator imports instead of bare module imports import 'rxjs/add/observable/defer'; import 'rxjs/add/scheduler/animationFrame'; import 'rxjs/add/observable/interval'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/takeWhile'; const timeElapsed = Observable.defer(() => { const start = Scheduler.animationFrame.now(); // Explicitly use animationFrame scheduler and fix elapsed time calculation return Observable.interval(0, Scheduler.animationFrame) .map(() => Scheduler.animationFrame.now() - start); }); const duration = (totalMs) => timeElapsed .map(elapsedMs => elapsedMs / totalMs) .takeWhile(t => t <= 1); const amount = (d) => (t) => t * d; const elasticOut = (t) => Math.sin(-13.0 * (t + 1.0) * Math.PI / 2) * Math.pow(2.0, -10.0 * t) + 1.0; @Component({ selector: "ns-app", template: ` <StackLayout class="wrapper" (tap)="onTap($event)"> <Label class="thelabel1" text="Hello" [height]="blah$ | async"></Label> <Label class="thelabel2" text="Hello" [height]="blah$ | async"></Label> </StackLayout> `, styles: [] }) export class TestComponent { blah$: Observable<number> = Observable.of(25); onTap() { this.blah$ = duration(2000) .map(elasticOut) .map(amount(150)); } }
Key fixes here:
- Explicitly use
Scheduler.animationFrameforintervalto avoid browser-specific code - Correct the elapsed time calculation to use the scheduler's
now()method (more accurate for animations) - Use standard RxJS operator imports (
rxjs/add/...) instead of bare module imports
Approach 2: Use NativeScript's Native Animation API (Recommended)
NativeScript has a built-in Animation module optimized for mobile environments—no need to rely on RxJS for this use case. It also supports built-in easing curves like elasticOut out of the box:
import { Component, ViewChild, ElementRef } from "@angular/core"; import { Animation } from "ui/animation"; import { Label } from 'ui/label'; @Component({ selector: "ns-app", template: ` <StackLayout class="wrapper" (tap)="onTap($event)"> <Label #label1 class="thelabel1" text="Hello" height="25"></Label> <Label #label2 class="thelabel2" text="Hello" height="25"></Label> </StackLayout> `, styles: [] }) export class TestComponent { @ViewChild("label1") label1: ElementRef; @ViewChild("label2") label2: ElementRef; onTap() { // Define animations for both labels const animations = [ { target: this.label1.nativeElement, height: 175, // 25 base height + 150 animation delta duration: 2000, curve: "elasticOut" // NativeScript's built-in elastic easing curve }, { target: this.label2.nativeElement, height: 175, duration: 2000, curve: "elasticOut" } ]; const animation = new Animation(animations); animation.play().catch(err => console.error("Animation error:", err)); } }
This approach is simpler, avoids RxJS compatibility issues, and leverages NativeScript's optimized native animation layer for smoother performance on iOS and Android.
Final Notes
Stick with NativeScript's native APIs for mobile-specific tasks like animations whenever possible—they're designed to work seamlessly with the platform. If you do need RxJS, always ensure you're using schedulers that don't rely on browser DOM APIs.
内容的提问来源于stack exchange,提问作者MadNeox

