Knockoutjs 嵌套 ViewModel / 组件与打字稿的绑定不起作用
Knockoutjs nested ViewModel / component binding with typescript doesn't work
我一直在努力尝试让 viewModel 中的 viewModel 在 knockout 中工作。任何帮助将非常感激。我正在使用打字稿并想要一个地址控件列表,每个控件都有自己的视图模型。
该项目仅使用一个地址控件即可完美运行,但是当将控件添加到父容器视图模型并使用组件时,子视图模型始终为空(即 {},如下面的警报语句所示):
这是我的 app.ts,完整代码在 https://github.com/richbeales/knockout-test
///<reference path="../node_modules/retyped-knockout-tsd-ambient/knockout.d.ts"/>
import * as ko from 'knockout';
import {AddressViewModel, Address} from './components/paf-widget';
ko.components.register('paf-address', {
viewModel: AddressViewModel, // { require: 'components/paf-widget' },
template: { require: 'text!components/paf-widget.html' }
});
class AddressesViewModel {
addressList: KnockoutObservableArray<AddressViewModel>;
constructor() {
this.addressList = ko.observableArray<AddressViewModel>();
}
addAddress = function () {
alert(ko.toJSON(this)); // returns {"addressList":[{}]}
var childVm = new AddressViewModel();
alert(ko.toJSON(childVm)); // returns {}
childVm.chosenAddress(new Address());
childVm.chosenAddress().Organisation = "Test";
alert(ko.toJSON(childVm)); // returns {}
var a = new Address();
a.AddressLine1 = "The Street";
alert(ko.toJSON(a)); // returns {"AddressLine1":"The Street"}
this.addressList.push(childVm);
}
}
var vm = new AddressesViewModel();
ko.applyBindings(vm);
这是我的 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bootstrap with jQuery and KnockoutJS</title>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<header>
</header>
<h1>App</h1>
Choose an Address
<pre data-bind="text: ko.toJSON(addressList, null, 2)"></pre>
<ul data-bind="foreach: {data: addressList, as: 'addrVm'}" style="list-style: none;">
<li class="addressli">
<pre data-bind="text: ko.toJSON(addrVm, null, 2)"></pre>
<div data-bind="component: {name: 'paf-address', with: addrVm }"></div>
</li>
</ul>
<button class="btn btn-primary" data-bind="click: addAddress">Add an address</button>
<footer>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.2/require.min.js" data-main="js/app"></script>
<script src="require-config.js"></script>
</body>
</html>
你遇到这个奇怪的问题是因为你多次加载 knockout 并且不一致。
第一次直接在你的index.html
然后用require.js在你的app.js
。因此,您的 AddressViewModel
使用与 AddressesViewModel
不同的 ko
实例,这就是您看到这些奇怪的空对象的原因。
最简单的修复方法是删除 index.html:
中对 KO 的直接引用
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
并在您的 paf-widget.ts
中正确包含淘汰赛,其中:
import * as ko from 'knockout';
注意:更改后请确保您的浏览器缓存已清除并正确获取新代码。
我一直在努力尝试让 viewModel 中的 viewModel 在 knockout 中工作。任何帮助将非常感激。我正在使用打字稿并想要一个地址控件列表,每个控件都有自己的视图模型。
该项目仅使用一个地址控件即可完美运行,但是当将控件添加到父容器视图模型并使用组件时,子视图模型始终为空(即 {},如下面的警报语句所示):
这是我的 app.ts,完整代码在 https://github.com/richbeales/knockout-test
///<reference path="../node_modules/retyped-knockout-tsd-ambient/knockout.d.ts"/>
import * as ko from 'knockout';
import {AddressViewModel, Address} from './components/paf-widget';
ko.components.register('paf-address', {
viewModel: AddressViewModel, // { require: 'components/paf-widget' },
template: { require: 'text!components/paf-widget.html' }
});
class AddressesViewModel {
addressList: KnockoutObservableArray<AddressViewModel>;
constructor() {
this.addressList = ko.observableArray<AddressViewModel>();
}
addAddress = function () {
alert(ko.toJSON(this)); // returns {"addressList":[{}]}
var childVm = new AddressViewModel();
alert(ko.toJSON(childVm)); // returns {}
childVm.chosenAddress(new Address());
childVm.chosenAddress().Organisation = "Test";
alert(ko.toJSON(childVm)); // returns {}
var a = new Address();
a.AddressLine1 = "The Street";
alert(ko.toJSON(a)); // returns {"AddressLine1":"The Street"}
this.addressList.push(childVm);
}
}
var vm = new AddressesViewModel();
ko.applyBindings(vm);
这是我的 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bootstrap with jQuery and KnockoutJS</title>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<header>
</header>
<h1>App</h1>
Choose an Address
<pre data-bind="text: ko.toJSON(addressList, null, 2)"></pre>
<ul data-bind="foreach: {data: addressList, as: 'addrVm'}" style="list-style: none;">
<li class="addressli">
<pre data-bind="text: ko.toJSON(addrVm, null, 2)"></pre>
<div data-bind="component: {name: 'paf-address', with: addrVm }"></div>
</li>
</ul>
<button class="btn btn-primary" data-bind="click: addAddress">Add an address</button>
<footer>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.2/require.min.js" data-main="js/app"></script>
<script src="require-config.js"></script>
</body>
</html>
你遇到这个奇怪的问题是因为你多次加载 knockout 并且不一致。
第一次直接在你的index.html
然后用require.js在你的app.js
。因此,您的 AddressViewModel
使用与 AddressesViewModel
不同的 ko
实例,这就是您看到这些奇怪的空对象的原因。
最简单的修复方法是删除 index.html:
中对 KO 的直接引用<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
并在您的 paf-widget.ts
中正确包含淘汰赛,其中:
import * as ko from 'knockout';
注意:更改后请确保您的浏览器缓存已清除并正确获取新代码。