Javascript foreach绑定中的Knockout$root上下文错误

Javascript foreach绑定中的Knockout$root上下文错误,javascript,html,knockout.js,typescript,Javascript,Html,Knockout.js,Typescript,当我使用foreach数据绑定时,它似乎打破了$root上下文的敲除 发生这种情况时,此引用一个元素(用户),该元素是viewmodel(页面)的子元素,也是foreach元素(请求)的父元素,而它应该引用viewmodel(页面) 我在foreach之外引用$root,没有问题-它在正确的上下文中调用正确的方法 HTML的工作位置: <div id="home-page-view" class="view" data-bind="if: status() == AppStatus.Hom

当我使用
foreach
数据绑定时,它似乎打破了
$root
上下文的敲除

发生这种情况时,
引用一个元素(
用户
),该元素是viewmodel(
页面
)的子元素,也是foreach元素(
请求
)的父元素,而它应该引用viewmodel(
页面

我在foreach之外引用
$root
,没有问题-它在正确的上下文中调用正确的方法

HTML的工作位置:

<div id="home-page-view" class="view" data-bind="if: status() == AppStatus.Home">
        <button data-bind="click: $root.switchState">Switch To Friend Requests</button>
</div>
public switchState() {
        if (this.status() == AppStatus.Home) {
            this.status(AppStatus.FriendRequests); //this refers to viewmodel (page)
        } else {
            this.status(AppStatus.Home);
        }
    }
<div id="friend-requests-view" class="view" data-bind="if: status() == AppStatus.FriendRequests">
    <h1>Friend Requests</h1>
    <p>View your pending friend requests.</p>

    <div data-bind="with: user">
        <div data-bind="foreach: requests">
            <div>
                <h2 data-bind="text: firstName"></h2>
                <p data-bind="text: lastName"></p>
            </div>
            <div>
                <input type="button" value="Accept" data-bind="click: $root.acceptFriendRequest" />
                <input type="button" value="Deny" data-bind="click: $root.rejectFriendRequest" />
            </div>
        </div>
    </div>
</div>
public acceptFriendRequest(newFriend: UserModel) {
        this.respondToFriendRequest(true, newFriend);
}

public rejectFriendRequest(notFriend: UserModel) {
        this.respondToFriendRequest(false, notFriend);
}
但是,在foreach中,像
data bind=“click:$root.acceptFriendRequest”
这样绑定的按钮成功地调用了它们的方法,但是
指的是
用户
,而不是
页面

HTML的断开位置:

<div id="home-page-view" class="view" data-bind="if: status() == AppStatus.Home">
        <button data-bind="click: $root.switchState">Switch To Friend Requests</button>
</div>
public switchState() {
        if (this.status() == AppStatus.Home) {
            this.status(AppStatus.FriendRequests); //this refers to viewmodel (page)
        } else {
            this.status(AppStatus.Home);
        }
    }
<div id="friend-requests-view" class="view" data-bind="if: status() == AppStatus.FriendRequests">
    <h1>Friend Requests</h1>
    <p>View your pending friend requests.</p>

    <div data-bind="with: user">
        <div data-bind="foreach: requests">
            <div>
                <h2 data-bind="text: firstName"></h2>
                <p data-bind="text: lastName"></p>
            </div>
            <div>
                <input type="button" value="Accept" data-bind="click: $root.acceptFriendRequest" />
                <input type="button" value="Deny" data-bind="click: $root.rejectFriendRequest" />
            </div>
        </div>
    </div>
</div>
public acceptFriendRequest(newFriend: UserModel) {
        this.respondToFriendRequest(true, newFriend);
}

public rejectFriendRequest(notFriend: UserModel) {
        this.respondToFriendRequest(false, notFriend);
}
即使在HTML中,它的前4行
status()
也隐含地引用了正确的
$root

这里发生了什么事情使得
这个
引用了
页面。用户
而不是
页面
?考虑到在其他上下文中,
指的是
页面
,似乎
$root
应该总是指回
页面

MCVE:

<div id="home-page-view" class="view" data-bind="if: status() == AppStatus.Home">
        <button data-bind="click: $root.switchState">Switch To Friend Requests</button>
</div>
public switchState() {
        if (this.status() == AppStatus.Home) {
            this.status(AppStatus.FriendRequests); //this refers to viewmodel (page)
        } else {
            this.status(AppStatus.Home);
        }
    }
<div id="friend-requests-view" class="view" data-bind="if: status() == AppStatus.FriendRequests">
    <h1>Friend Requests</h1>
    <p>View your pending friend requests.</p>

    <div data-bind="with: user">
        <div data-bind="foreach: requests">
            <div>
                <h2 data-bind="text: firstName"></h2>
                <p data-bind="text: lastName"></p>
            </div>
            <div>
                <input type="button" value="Accept" data-bind="click: $root.acceptFriendRequest" />
                <input type="button" value="Deny" data-bind="click: $root.rejectFriendRequest" />
            </div>
        </div>
    </div>
</div>
public acceptFriendRequest(newFriend: UserModel) {
        this.respondToFriendRequest(true, newFriend);
}

public rejectFriendRequest(notFriend: UserModel) {
        this.respondToFriendRequest(false, notFriend);
}
Page.html

<!DOCTYPE html>
<head>
    <meta charset="utf-8" />

    <script type="text/javascript" src="/Scripts/jquery-2.1.4.js"></script>
    <script type="text/javascript" src="/Scripts/jquery-ui-1.11.4.js"></script>
    <script type="text/javascript" src="/Scripts/knockout-3.3.0.js"></script>
    <script type="text/javascript" src="/Scripts/knockout.mapping-latest.js"></script>
    <script type="text/javascript" src="app.js"></script>
    <script type="text/javascript" src="DTO/DTOs.js"></script>
</head>

<body>
    <div id="home-page-view" class="view" data-bind="if: status() == AppStatus.Home">
        <button data-bind="click: $root.switchState">Switch To Friend Requests</button>
    </div>

    <div id="friend-requests-view" class="view" data-bind="if: status() == AppStatus.FriendRequests">
        <h1>Friend Requests</h1>
        <p>View your pending friend requests.</p>

        <div data-bind="with: user">
            <div data-bind="foreach: requests">
                <div>
                    <h2 data-bind="text: firstName"></h2>
                    <p data-bind="text: lastName"></p>
                </div>
                <div>
                    <input type="button" value="Accept" data-bind="click: $root.acceptFriendRequest" />
                    <input type="button" value="Deny" data-bind="click: $root.rejectFriendRequest" />
                </div>
            </div>
        </div>
    </div>
</body>
</html>

切换到好友请求
好友请求
查看您待定的好友请求

应用程序ts

/// <reference path="Scripts/typings/jquery/jquery.d.ts" />
/// <reference path="Scripts/typings/jqueryui/jqueryui.d.ts" />
/// <reference path="Scripts/typings/knockout/knockout.d.ts" />
/// <reference path="Scripts/typings/knockout.mapping/knockout.mapping.d.ts" />


var page: App;

$(document).ready(function () {
    $.ajaxSetup({ cache: false });
    page = new App();
    ko.applyBindings(page);
});


class App {

    public user: KnockoutObservable<UserModel>;
    public status: KnockoutObservable<AppStatus> = ko.observable(AppStatus.Home);

    constructor() {
        this.user = ko.observable(new UserModel());
        var us: User = {firstName: "Chip", lastName: "Dipson" };
        this.user(ko.mapping.fromJS(us));
        this.user().requests.push(new UserModel());
    }

   public switchState() {
        if (this.status() == AppStatus.Home) {
            this.status(AppStatus.FriendRequests);
        } else {
            this.status(AppStatus.Home);
        }
    }

    public acceptFriendRequest(newFriend: UserModel) {
        this.respondToFriendRequest(true, newFriend); //this is wrong
    }

    public rejectFriendRequest(notFriend: UserModel) {
        this.respondToFriendRequest(false, notFriend); //this is wrong
    }

    private respondToFriendRequest(accepted: boolean, requester: UserModel) {
      //do some ajax stuff
    }
}

enum AppStatus {
    Home, FriendRequests
}
class User {
    firstName: string;
    lastName: string;

    requests: User[];
}

class UserModel {
    firstName: KnockoutObservable<string> = ko.observable("");
    lastName: KnockoutObservable<string> = ko.observable("");

    requests: KnockoutObservableArray<UserModel> = ko.observableArray<UserModel>(null);
}
//
/// 
/// 
/// 
var页面:App;
$(文档).ready(函数(){
$.ajaxSetup({cache:false});
页面=新应用程序();
ko.应用绑定(第页);
});
类应用程序{
公共用户:可观察的淘汰;
公共状态:KnockoutObservable=ko.observable(AppStatus.Home);
构造函数(){
this.user=ko.observable(新的UserModel());
var us:User={firstName:“Chip”,lastName:“Dipson”};
this.user(ko.mapping.fromJS(us));
this.user().requests.push(新的UserModel());
}
公共状态(){
if(this.status()==AppStatus.Home){
this.status(AppStatus.FriendRequests);
}否则{
this.status(AppStatus.Home);
}
}
公共acceptFriendRequest(newFriend:UserModel){
this.respondToFriendRequest(真的,新朋友);//这是错误的
}
公共拒绝FriendRequest(notFriend:UserModel){
this.respondToFriendRequest(false,notFriend);//这是错误的
}
private respondToFriendRequest(已接受:布尔值,请求者:用户模型){
//做一些ajax的东西
}
}
枚举应用状态{
家,朋友
}
DTOs.ts

/// <reference path="Scripts/typings/jquery/jquery.d.ts" />
/// <reference path="Scripts/typings/jqueryui/jqueryui.d.ts" />
/// <reference path="Scripts/typings/knockout/knockout.d.ts" />
/// <reference path="Scripts/typings/knockout.mapping/knockout.mapping.d.ts" />


var page: App;

$(document).ready(function () {
    $.ajaxSetup({ cache: false });
    page = new App();
    ko.applyBindings(page);
});


class App {

    public user: KnockoutObservable<UserModel>;
    public status: KnockoutObservable<AppStatus> = ko.observable(AppStatus.Home);

    constructor() {
        this.user = ko.observable(new UserModel());
        var us: User = {firstName: "Chip", lastName: "Dipson" };
        this.user(ko.mapping.fromJS(us));
        this.user().requests.push(new UserModel());
    }

   public switchState() {
        if (this.status() == AppStatus.Home) {
            this.status(AppStatus.FriendRequests);
        } else {
            this.status(AppStatus.Home);
        }
    }

    public acceptFriendRequest(newFriend: UserModel) {
        this.respondToFriendRequest(true, newFriend); //this is wrong
    }

    public rejectFriendRequest(notFriend: UserModel) {
        this.respondToFriendRequest(false, notFriend); //this is wrong
    }

    private respondToFriendRequest(accepted: boolean, requester: UserModel) {
      //do some ajax stuff
    }
}

enum AppStatus {
    Home, FriendRequests
}
class User {
    firstName: string;
    lastName: string;

    requests: User[];
}

class UserModel {
    firstName: KnockoutObservable<string> = ko.observable("");
    lastName: KnockoutObservable<string> = ko.observable("");

    requests: KnockoutObservableArray<UserModel> = ko.observableArray<UserModel>(null);
}
类用户{
名字:字符串;
lastName:string;
请求:用户[];
}
类用户模型{
名字:KnockoutObservable=ko.observable(“”);
lastName:KnockoutObservable=ko.observable(“”);
请求:knockoutobservearray=ko.observearray(null);
}

A
单击
绑定是一个函数,而不是一段代码。这意味着$root没有提供执行上下文,它只是帮助您定位函数。如果要设置执行上下文,则需要
bind
it:

<input type="button" value="Accept" data-bind="click: $root.acceptFriendRequest.bind($root)" />

A
单击
绑定是一个函数,而不是一段代码。这意味着$root没有提供执行上下文,它只是帮助您定位函数。如果要设置执行上下文,则需要
bind
it:

<input type="button" value="Accept" data-bind="click: $root.acceptFriendRequest.bind($root)" />


就是这样。谢谢就是这样。谢谢