gpt4 book ai didi

typescript - 将分层 JSON 映射到 TypeScript-KnockoutJS 类型对象

转载 作者:搜寻专家 更新时间:2023-10-30 20:37:42 24 4
gpt4 key购买 nike

让我们提前致谢:)

好的,所以我正在尝试使用 knockout.mapping 插件从匹配的 JSON 数据中加载/映射分层的 TypeScript/KnockoutJS 类型类,层次结构可以达到第 N 级。

我知道我可以执行以下操作以从 JSON 数据映射/加载顶级类。

var qry = ko.mapping.fromJS(jsData, {}, new Query());

但是我不知道如何将复杂的 N 级分层 JSON 数据映射/加载到一组 TypeScript/KnockoutJS 类并建立父/子关系。

我读过无数文章,但除了简单的父/子示例之外,在涉及层次关系时,它们都达不到要求,而且我使用 knockout.mapping 插件找不到任何文章。

这是我希望映射/加载的 TypeScript 类的缩减定义。我是一名 C++/C# 开发人员,因此这种性质的 JavaScript 对我来说非常陌生。

typescript 对象

module ViewModel
{
export class QueryModuleViewModel {
public QueryObj: KnockoutObservable<Query>;

constructor() {
this.QueryObj = ko.observable<Query>();
}

public Initialize() {
$.getJSON("/api/query/2", null,
d => {
var qry = ko.mapping.fromJS(d, {}, new Query());
this.QueryObj(qry);
});
}
}

export class Query
{
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public RootTargetID: KnockoutObservable<number>;
public RootTarget: KnockoutObservable<QueryTarget>;

constructor()
{
this.ID = ko.observable<number>(0);
this.Name = ko.observable<string>();
this.RootTargetID = ko.observable<number>();
this.RootTarget = ko.observable<QueryTarget>();
}
}

export class QueryTarget
{
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public ParentID: KnockoutObservable<number>;
public Children: KnockoutObservableArray<QueryTarget>;
public Parent: KnockoutObservable<QueryTarget>;
public Selects: KnockoutObservableArray<QuerySelect>;
public FilterID: KnockoutObservable<number>;
public Filter: KnockoutObservable<FilterClause>;

constructor()
{
this.ID = ko.observable<number>(0);
this.Name = ko.observable<string>();
this.ParentID = ko.observable<number>(0);
this.Children = ko.observableArray<QueryTarget>();
this.Parent = ko.observable<QueryTarget>();
this.Selects = ko.observableArray<QuerySelect>();
this.FilterID = ko.observable<number>(0);
this.Filter = ko.observable<FilterClause>();
}
}

export class QuerySelect
{
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public Aggregation: KnockoutObservable<string>;
public TargetID: KnockoutObservable<number>;
public Target: KnockoutObservable<QueryTarget>;

constructor()
{
this.ID = ko.observable<number>();
this.Name = ko.observable<string>();
this.Aggregation = ko.observable<string>();
this.TargetID = ko.observable<number>();
this.Target = ko.observable<QueryTarget>();
}
}

export class FilterClause
{
public FilterClauseID: KnockoutObservable<number>;
public Type: KnockoutObservable<string>;
public Left: KnockoutObservable<string>;
public Right: KnockoutObservable<string>;
public ParentID: KnockoutObservable<number>;
public Parent: KnockoutObservable<FilterClause>;
public Children: KnockoutObservableArray<FilterClause>;
public QueryTargets: KnockoutObservableArray<QueryTarget>;

constructor()
{
this.FilterClauseID = ko.observable<number>();
this.Type = ko.observable<string>();
this.Left = ko.observable<string>();
this.Right = ko.observable<string>();
this.ParentID = ko.observable<number>();
this.Parent = ko.observable<FilterClause>();
this.Children = ko.observableArray<FilterClause>();
}
}
}

JSON 看起来像这样:

{
"ID": 2,
"Name": "Northwind 2",
"RootTargetID": 2,
"RootTarget": {
"ID": 2,
"Name": "Customers",
"ParentID": null,
"FilterID": 2,
"Queries": [],
"Children": [],
"Parent": null,
"Selects": [
{
"ID": 3,
"Name": "CompanyName",
"Aggregation": "None",
"TargetID": 2,
"Target": null
},
{
"ID": 4,
"Name": "ContactName",
"Aggregation": "None",
"TargetID": 2,
"Target": null
}
],
"Filter": {
"FilterClauseID": 2,
"Type": "AND",
"Left": null,
"Right": null,
"ParentID": null,
"QueryTargets": [],
"Parent": null,
"Children": [
{
"FilterClauseID": 3,
"Type": "NE",
"Left": "Country",
"Right": "Germany",
"ParentID": 2,
"QueryTargets": [],
"Parent": null,
"Children": []
},
{
"FilterClauseID": 4,
"Type": "NE",
"Left": "Country",
"Right": "Mexico",
"ParentID": 2,
"QueryTargets": [],
"Parent": null,
"Children": []
}
]
}
}
}

最佳答案

好的,经过大量的头发拉扯和无数次测试后,我现在更进一步了。

下面是我正在努力实现的一个几乎可行的示例,唯一的问题是它似乎没有正确映射,即使单步执行代码似乎表明它正在正确加载。只有当我将它与我的绑定(bind)一起使用时,它才会在 RootTaget.Filter.Type 上抛出一个空的未引用绑定(bind),该绑定(bind)应该填充一个值。

我仍在努力找出原因,但我欢迎就可能的错误提出建议。 :)

现已修复并可正常工作

半工作 typescript

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

module ViewModel
{
export class Query {
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public RootTargetID: KnockoutObservable<number>;
public RootTarget: KnockoutObservable<QueryTarget>;

constructor(json: any) {
this.ID = ko.observable<number>(0);
this.Name = ko.observable<string>();
this.RootTargetID = ko.observable<number>();
this.RootTarget = ko.observable<QueryTarget>();

var mapping = {
'RootTarget': {
create: function (args) {
return new QueryTarget(args.data, null);
}
}
};

ko.mapping.fromJS(json, mapping, this);

}
}

export class QueryTarget {
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public ParentID: KnockoutObservable<number>;
public Children: KnockoutObservableArray<QueryTarget>;
public Parent: KnockoutObservable<QueryTarget>;
public Selects: KnockoutObservableArray<QuerySelect>;
public FilterID: KnockoutObservable<number>;
public Filter: KnockoutObservable<FilterClause>;

constructor(json: any, parent: QueryTarget) {
this.ID = ko.observable<number>(0);
this.Name = ko.observable<string>();
this.ParentID = ko.observable<number>(0);
this.Children = ko.observableArray<QueryTarget>();
this.Parent = ko.observable<QueryTarget>(parent);
this.Selects = ko.observableArray<QuerySelect>();
this.FilterID = ko.observable<number>(0);
this.Filter = ko.observable<FilterClause>();

var mapping = {
'Children': {
create: function (args) {
return new QueryTarget(args.data, this);
}
},
'Selects': {
create: function (args) {
return new QuerySelect(args.data, this);
}
},
'Filter': {
create: function (args) {
return new FilterClause(args.data, null);
}
}
};

ko.mapping.fromJS(json, mapping, this);
}
}

export class QuerySelect {
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public Aggregation: KnockoutObservable<string>;
public TargetID: KnockoutObservable<number>;
public Target: KnockoutObservable<QueryTarget>;

constructor(json: any, parent: QueryTarget) {
this.ID = ko.observable<number>();
this.Name = ko.observable<string>();
this.Aggregation = ko.observable<string>();
this.TargetID = ko.observable<number>();
this.Target = ko.observable<QueryTarget>(parent);

ko.mapping.fromJS(json, {}, this);
}
}

export class FilterClause {
public FilterClauseID: KnockoutObservable<number>;
public Type: KnockoutObservable<string>;
public Left: KnockoutObservable<string>;
public Right: KnockoutObservable<string>;
public ParentID: KnockoutObservable<number>;
public Parent: KnockoutObservable<FilterClause>;
public Children: KnockoutObservableArray<FilterClause>;

constructor(json: any, parent: FilterClause) {
this.FilterClauseID = ko.observable<number>();
this.Type = ko.observable<string>();
this.Left = ko.observable<string>();
this.Right = ko.observable<string>();
this.ParentID = ko.observable<number>();
this.Parent = ko.observable<FilterClause>(parent);
this.Children = ko.observableArray<FilterClause>();

var mapping = {
'Children': {
create: function (args) {
return new FilterClause(args.data, this);
}
}
};

ko.mapping.fromJS(json, mapping, this);
}
}

export class QueryModuleViewModel
{
public QueryObj: Query;

constructor() {

var json = {
"ID": 2,
"Name": "Northwind 2",
"RootTargetID": 2,
"RootTarget": {
"ID": 2,
"Name": "Customers",
"ParentID": null,
"FilterID": 2,
"Queries": [],
"Children": [],
"Parent": null,
"Selects": [
{
"ID": 3,
"Name": "CompanyName",
"Aggregation": "None",
"TargetID": 2,
"Target": null
},
{
"ID": 4,
"Name": "ContactName",
"Aggregation": "None",
"TargetID": 2,
"Target": null
}
],
"Filter": {
"FilterClauseID": 2,
"Type": "AND",
"Left": null,
"Right": null,
"ParentID": null,
"QueryTargets": [],
"Parent": null,
"Children": [
{
"FilterClauseID": 3,
"Type": "NE",
"Left": "Country",
"Right": "Germany",
"ParentID": 2,
"QueryTargets": [],
"Parent": null,
"Children": []
},
{
"FilterClauseID": 4,
"Type": "NE",
"Left": "Country",
"Right": "Mexico",
"ParentID": 2,
"QueryTargets": [],
"Parent": null,
"Children": []
}
]
}
}
}

//$.getJSON("/api/query/2", null,
// d => {
// this.QueryObj = new Query(d);
// })

this.QueryObj = new Query(json);
}
}
}

window.onload = () => {
ko.applyBindings(new ViewModel.QueryModuleViewModel());
};

html绑定(bind)测试

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>TypeScript Knockout Mapping Query Test</title>
<link rel="stylesheet" href="app.css" type="text/css" />

<script src="Scripts/jquery-2.0.2.js" type="text/javascript"></script>
<script src="Scripts/knockout-2.2.1.debug.js" type="text/javascript"></script>
<script src="Scripts/knockout.mapping-latest.debug.js" type="text/javascript"></script>
<script src="query.js"></script>
<!--<script src="my_js_query_test_all.js"></script>-->

</head>
<body>
<h1>TypeScript Knockout Mapping Query Test</h1>
<div data-bind="with: QueryObj">
<span data-bind="blah: console.log($context)"></span>

<p>Query Name: <input data-bind="value: Name" /></p>

<hr />
<p>Quick test of RootTarget and Filter data</p>
<p>RootTarget.ID: <input data-bind="value: RootTarget().ID" /></p>
<p>RootTarget.Name: <input data-bind="value: RootTarget().Name" /></p>

<p>TYPE: <input data-bind="value: RootTarget().Filter().Type" /></p>

<hr />
<p>RootTarget.FilterClause Hierarcy</p>
<div data-bind="with: RootTarget().Filter">
<div data-bind="template: { name: 'QueryListClauseTemplate' }"></div>
</div>

<hr />
<p>RootTarget.Selects</p>
<div data-bind="foreach: { data: RootTarget().Selects }">
<div data-bind="template: { name: 'QueryListSelectsTemplate' }"></div>
</div>

</div>

<script type="text/template" id="QueryListClauseTemplate">

<a title="FilterClause.Type" href="#" data-bind="text: Type" />

<div data-bind="foreach: { data: Children }">
<div data-bind="template: { name: 'QueryListClauseTemplate' }"></div>
</div>
</script>

<script type="text/template" id="QueryListSelectsTemplate">
<a title="Select.Name" href="#" data-bind="text: Name" />
</script>

</body>
</html>

关于typescript - 将分层 JSON 映射到 TypeScript-KnockoutJS 类型对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17553963/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com