NativeScript 单向数据绑定不更新视图
NativeScript one-way databinding doesn't update view
这对我来说似乎是一个非常简单的案例,但我显然遗漏了一些东西。我有一个模型要绑定到视图。然后我使用 Http 调用加载模型。为什么视图不更新?我认为这就是单向绑定的全部意义。
我已经确认我正在从 http 调用中取回我期望的数据。
更新
我在屏幕上添加了一个按钮,数据绑定实际上会在按钮按下时使用两个字段的 http 加载数据更新屏幕,即使按钮方法只设置其中一个值。所以要么 NativeScript 中存在错误,要么我没有做错什么。
更新 2 只需单击按钮即可触发绑定。我已将代码修改为有一个空的点击处理程序,只需单击按钮即可将其绑定。
打字稿
import { Component, ChangeDetectionStrategy, OnInit } from "@angular/core";
import { Job } from "../../shared/customer/job";
import { Http, Headers, Response } from "@angular/http";
import { Observable } from "rxjs/Rx";
@Component({
selector: "my-app",
templateUrl: "pages/job-details/job-details.html",
changeDetection: ChangeDetectionStrategy.OnPush
})
export class JobDetailsComponent implements OnInit {
job: Job;
salesAssociateName: string = "x";
constructor(private http: Http) {
this.job = new Job();
}
ngOnInit() {
this.getJob(1234);
}
getJob(leadId: number) {
var url = "https://url-not-for-you/job?franchiseeid=48&leadid=" + leadId;
var headers = this.createRequestHeader();
this.http.get(url, { headers: headers }).map(response => response.json())
.do(data => this.setData(data[0]))
.subscribe(
() => this.success(),
(error) => this.error()
);
}
private createRequestHeader() {
let headers = new Headers();
headers.append("AuthKey","blah");
headers.append("AuthToken", "blee");
return headers;
}
setData(job) {
this.job.FullName = job["FullName"];
this.job.SalesAssociateName = job["SalesAssociateName"];
this.salesAssociateName = this.job.SalesAssociateName;
console.log("Found job for customer: " + job["FullName"]);
}
success() {
// nothing useful
}
error() {
alert("There was a problem retrieving your customer job.");
}
changeSA() {
}
}
html
<StackLayout>
<Label [text]="job.FullName"></Label>
<Label [text]="salesAssociateName"></Label>
<Button text="Push" (tap)="changeSA()"></Button>
</StackLayout>
您的代码将按预期使用默认的 ChangeDetectionStrategy。但是,您已将策略更改为 onPush
为了使您的绑定在默认 changeStrategy 中按预期工作删除以下行
changeDetection: ChangeDetectionStrategy.OnPush
或改为
changeDetection: ChangeDetectionStrategy.Default
更多关于 Angular-2 ChangeDetectionStrategy here and here
如果您仍然想使用 onPush 而不是默认策略,那么您的属性应该声明为 @input() 并且一旦做出更改(在您的情况下是 setData ) 标有 markForCheck()
您的绑定在点击按钮触发时有效的原因是
应用程序状态更改可以通过以下方式触发:
- 事件 - 点击、滑动、
- XHR - 从远程服务器获取数据
- 计时器 - 例如设置超时()
出于测试目的,如果有人对如何使用 onPush 实现场景感兴趣,这里有一个示例代码:
import { Component, ChangeDetectionStrategy, ChangeDetectorRef, OnInit, NgZone, Input } from "@angular/core";
import { Http, Headers, Response } from "@angular/http";
import { Observable as RxObservable } from "rxjs/Rx";
import "rxjs/add/operator/map";
import "rxjs/add/operator/do";
@Component({
selector: "my-app",
templateUrl: "app.component.html",
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements OnInit {
@Input() public job: any = { salesAssociateName: "default job" };
@Input() public salesAssociateName: string = "default name";
constructor(private http: Http, private change:ChangeDetectorRef) { }
ngOnInit() {
this.getJob();
}
getJob() {
var url = "http://httpbin.org/get";
var headers = this.createRequestHeader();
this.http.get(url, { headers: headers })
.map(response => response.json())
.do(data => {
this.setData();
}).subscribe(
() => this.success(),
(error) => this.error()
);
}
private createRequestHeader() {
let headers = new Headers();
return headers;
}
setData() {
this.job.salesAssociateName = "NEW job SalesAssociateName";
this.salesAssociateName = "NEW job FullName";
this.change.markForCheck();
}
success() {
alert("success");
}
error() {
alert("There was a problem retrieving your customer job.");
}
}
这对我来说似乎是一个非常简单的案例,但我显然遗漏了一些东西。我有一个模型要绑定到视图。然后我使用 Http 调用加载模型。为什么视图不更新?我认为这就是单向绑定的全部意义。
我已经确认我正在从 http 调用中取回我期望的数据。
更新 我在屏幕上添加了一个按钮,数据绑定实际上会在按钮按下时使用两个字段的 http 加载数据更新屏幕,即使按钮方法只设置其中一个值。所以要么 NativeScript 中存在错误,要么我没有做错什么。
更新 2 只需单击按钮即可触发绑定。我已将代码修改为有一个空的点击处理程序,只需单击按钮即可将其绑定。
打字稿
import { Component, ChangeDetectionStrategy, OnInit } from "@angular/core";
import { Job } from "../../shared/customer/job";
import { Http, Headers, Response } from "@angular/http";
import { Observable } from "rxjs/Rx";
@Component({
selector: "my-app",
templateUrl: "pages/job-details/job-details.html",
changeDetection: ChangeDetectionStrategy.OnPush
})
export class JobDetailsComponent implements OnInit {
job: Job;
salesAssociateName: string = "x";
constructor(private http: Http) {
this.job = new Job();
}
ngOnInit() {
this.getJob(1234);
}
getJob(leadId: number) {
var url = "https://url-not-for-you/job?franchiseeid=48&leadid=" + leadId;
var headers = this.createRequestHeader();
this.http.get(url, { headers: headers }).map(response => response.json())
.do(data => this.setData(data[0]))
.subscribe(
() => this.success(),
(error) => this.error()
);
}
private createRequestHeader() {
let headers = new Headers();
headers.append("AuthKey","blah");
headers.append("AuthToken", "blee");
return headers;
}
setData(job) {
this.job.FullName = job["FullName"];
this.job.SalesAssociateName = job["SalesAssociateName"];
this.salesAssociateName = this.job.SalesAssociateName;
console.log("Found job for customer: " + job["FullName"]);
}
success() {
// nothing useful
}
error() {
alert("There was a problem retrieving your customer job.");
}
changeSA() {
}
}
html
<StackLayout>
<Label [text]="job.FullName"></Label>
<Label [text]="salesAssociateName"></Label>
<Button text="Push" (tap)="changeSA()"></Button>
</StackLayout>
您的代码将按预期使用默认的 ChangeDetectionStrategy。但是,您已将策略更改为 onPush
为了使您的绑定在默认 changeStrategy 中按预期工作删除以下行
changeDetection: ChangeDetectionStrategy.OnPush
或改为
changeDetection: ChangeDetectionStrategy.Default
更多关于 Angular-2 ChangeDetectionStrategy here and here
如果您仍然想使用 onPush 而不是默认策略,那么您的属性应该声明为 @input() 并且一旦做出更改(在您的情况下是 setData ) 标有 markForCheck()
您的绑定在点击按钮触发时有效的原因是 应用程序状态更改可以通过以下方式触发:
- 事件 - 点击、滑动、
- XHR - 从远程服务器获取数据
- 计时器 - 例如设置超时()
出于测试目的,如果有人对如何使用 onPush 实现场景感兴趣,这里有一个示例代码:
import { Component, ChangeDetectionStrategy, ChangeDetectorRef, OnInit, NgZone, Input } from "@angular/core";
import { Http, Headers, Response } from "@angular/http";
import { Observable as RxObservable } from "rxjs/Rx";
import "rxjs/add/operator/map";
import "rxjs/add/operator/do";
@Component({
selector: "my-app",
templateUrl: "app.component.html",
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements OnInit {
@Input() public job: any = { salesAssociateName: "default job" };
@Input() public salesAssociateName: string = "default name";
constructor(private http: Http, private change:ChangeDetectorRef) { }
ngOnInit() {
this.getJob();
}
getJob() {
var url = "http://httpbin.org/get";
var headers = this.createRequestHeader();
this.http.get(url, { headers: headers })
.map(response => response.json())
.do(data => {
this.setData();
}).subscribe(
() => this.success(),
(error) => this.error()
);
}
private createRequestHeader() {
let headers = new Headers();
return headers;
}
setData() {
this.job.salesAssociateName = "NEW job SalesAssociateName";
this.salesAssociateName = "NEW job FullName";
this.change.markForCheck();
}
success() {
alert("success");
}
error() {
alert("There was a problem retrieving your customer job.");
}
}