【问题标题】:TypeError: Cannot read property '_router' of null in NativeScriptTypeError:无法在 NativeScript 中读取 null 的属性“_router”
【发布时间】:2016-06-12 08:20:52
【问题描述】:

我正在使用 NativeScript+AngularJS2+TypeScript 开发一个 android 应用程序。关注他们的文档 - http://docs.nativescript.org/angular/tutorial/ng-chapter-0

在成功登录后用户需要重定向到List 页面时卡住了。现在关注他们的路由部分 - http://docs.nativescript.org/angular/tutorial/ng-chapter-3#35-routing

按照他们的文档做所有事情。这是我的代码 -

app.component.ts

import {ListPage} from "./pages/list/list.component";
import {Component} from "@angular/core";
import {RouteConfig} from "@angular/router-deprecated";
import {NS_ROUTER_DIRECTIVES, NS_ROUTER_PROVIDERS} from "nativescript-angular/router";
import {LoginPage} from "./pages/login/login.component";

@Component({
  selector: "main",
  directives: [NS_ROUTER_DIRECTIVES],
  providers: [NS_ROUTER_PROVIDERS],
  template: "<page-router-outlet></page-router-outlet>"
})
@RouteConfig([
  { path: "/Login", component: LoginPage, name: "Login", useAsDefault: true },
  { path: "/List", component: ListPage, name: "List" }
])
export class AppComponent {}

user.service.ts

import {Injectable} from "@angular/core";
import {User} from "./user";
import {ConfigService} from "../config";
import firebase = require("nativescript-plugin-firebase");

@Injectable()
export class UserService {

    register(user: User, config: ConfigService) {

        console.log('Email entered : '+user.email);
        console.log('Password entered : '+user.password);
        console.log("API url going to use is : "+config.apiUrl);

        firebase.init(<any>{
            persist: true, // Allow disk persistence. Default false.
            url: config.apiUrl
        }).then(
            function (instance) {
                console.log("firebase.init done");
            },
            function (error) {
                console.log("firebase.init error: " + error);
            }
        );

        return firebase.createUser({
            email: user.email,
            password: user.password
          }).then(
              function (response) {
                console.log(response);
                return response;
              }
          )

    }

    login(user: User, config: ConfigService) {

        firebase.init({
            persist: true, // Allow disk persistence. Default false.
            url: config.apiUrl
        }).then(
            function (instance) {
                console.log("firebase.init done");
            },
            function (error) {
                console.log("firebase.init error: " + error);
            }
        );

        return firebase.login({
            type: firebase.LoginType.PASSWORD,
            email: 'eddyverbruggen@gmail.com',
            password: 'firebase'
          }).then(
              function (response) {
                console.log(response);
                return response;
              }
          )

    }

}

login.component.ts

import {Router} from "@angular/router-deprecated";
import {Component} from "@angular/core";
import {User} from "../../shared/user/user";
import {UserService} from "../../shared/user/user.service";
import {ConfigService} from "../../shared/config";
import {HTTP_PROVIDERS} from "@angular/http";
import firebase = require("nativescript-plugin-firebase");

@Component({
    selector: "my-app",
    providers: [UserService, HTTP_PROVIDERS,ConfigService],
    templateUrl: "pages/login/login.html",
    styleUrls: ["pages/login/login-common.css", "pages/login/login.css"]
})

export class LoginPage {
    user: User;
    isLoggingIn = true;
    config:any;

    constructor(private _router: Router, private _userService: UserService) {
        this.user = new User();
        this.config = new ConfigService();
    }

    submit() {
        if (this.isLoggingIn) {
            this.login();
        } else {
            this.signUp();
        }
    }


    login() {

        var result = this._userService.login(this.user,this.config);

        result.then(
            function (result) {
                console.log("Login Successs");
                // the result object has these properties: uid, provider, expiresAtUnixEpochSeconds, profileImageURL, token
                var response = JSON.stringify(result);
                console.log('Login Response : '+response);

                // Route to list page
                this._router.navigate(["List"]);
            },
            function (errorMessage) {
                console.log("Login Error");
                console.log(errorMessage);
            }
        );
    }

    signUp() {
        var result = this._userService.register(this.user,this.config);

        result.then(
            function (result) {
                // dialogs.alert({
                //  title: "User created",
                //  message: "userid: " + result.key,
                //  okButtonText: "Nice!"
                // })
                console.log('User Object Info : '+JSON.stringify(result));
                console.log('User Created with user id - '+result.key);
                alert("Your account was successfully created.");

                this.toggleDisplay();
            },
            function (errorMessage) {
                // dialogs.alert({
                //  title: "No user created",
                //  message: errorMessage,
                //  okButtonText: "OK, got it"
                // })
                console.log('No user created. Got error message insted - '+errorMessage);
                alert("Unfortunately we were unable to create your account.")
            }
        );


    }

    toggleDisplay() {
        this.isLoggingIn = !this.isLoggingIn;
    }
}

除了执行this._router.navigate(["List"]);from 文件login.component.ts 时,一切正常,我收到以下错误

JS: EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property '_router' of null

无法理解究竟是什么错误。

问候

【问题讨论】:

    标签: typescript angular2-routing nativescript


    【解决方案1】:

    我希望这个问题与上下文范围问题有关。我认为您应该先尝试捕获范围,然后再进入当时的范围。我通常将其存储在一个名为 that 的变量中,见下文(并查看 cmets):

    login() {
    
        var result = this._userService.login(this.user,this.config);
        var that = this; //store the current context 
        result.then(
            function (result) { //context (this has changed)
                console.log("Login Successs");
                // the result object has these properties: uid, provider, expiresAtUnixEpochSeconds, profileImageURL, token
                var response = JSON.stringify(result);
                console.log('Login Response : '+response);
    
                // Route to list page
                that._router.navigate(["List"]); //reference _router from the original scope
            },
            function (errorMessage) {
                console.log("Login Error");
                console.log(errorMessage);
            }
        );
    }
    

    【讨论】:

    • 感谢您的快速回复。有效。我也在考虑范围问题。但是,作为 nativescript 和 typescript 的新手,无法弄清楚如何解决它。
    【解决方案2】:

    是的,正如 George Edwards 指出的那样,您可以动态绑定 this。另一种选择是使用箭头函数,它允许您在函数内保留调用者的范围,这样您就不需要总是记住写var that = this

    login() {
    
        var result = this._userService.login(this.user,this.config);
        result.then(
            // Within the arrow function 'this' now refers to the lexical context rather than changing depending upon how the function is called.
            (result) => {
                console.log("Login Successs");
                // the result object has these properties: uid, provider, expiresAtUnixEpochSeconds, profileImageURL, token
                var response = JSON.stringify(result);
                console.log('Login Response : '+response);
    
                // Route to list page
                this._router.navigate(["List"]); //reference _router from the original scope
            },
            // Arguably clearer
            (errorMessage) => {
                console.log("Login Error");
                console.log(errorMessage);
            }
        );
    }
    

    【讨论】:

    • 感谢这项新技术。我听说过 ES6 的这个箭头函数,但从未使用过。在您给定的代码中,您可以将 that._router.navigate(["List"]); 更改为 this._router.navigate(["List"]); 。我认为这是一个错字。
    猜你喜欢
    • 2020-01-29
    • 2022-01-12
    • 2021-12-04
    • 2021-12-17
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多