- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试 ko.mapping.fromJS(http://knockoutjs.com/documentation/plugins-mapping.html)
鉴于下面的代码和期望,有人可以向我解释为什么实际输出不同吗?
var obj = { name: "frederick", minions: [{id:1, name:'Alice'},{id:2, name:'Bob'}] }
var model = {
'minions': {
key: function(data) { return ko.utils.unwrapObservable(data.id); }
}
}
var vm = ko.mapping.fromJS(obj, model);
vm.name.subscribe(x=>console.log("Changed name"));
vm.minions.subscribe(x => console.log("changed minions"));
vm.minions()[0].id.subscribe(x => console.log("changed id [0]"));
vm.minions()[0].name.subscribe(x => console.log("changed name [0]"));
vm.minions()[1].id.subscribe(x => console.log("changed id [1]"));
vm.minions()[1].name.subscribe(x => console.log("changed name [1]"));
obj.minions[0].name = 'Charlie';
ko.mapping.fromJS(obj, vm);
预期日志记录:
changed name [0]
实际记录:
changed name [0]
changed minions
问题:由于没有向数组添加或删除记录,为什么我会看到“Changed minions”?这些事件是否总是冒泡,或者仅在数组和直接子对象(/行)的情况下?(或者我在模型中犯了错误?我可以“修复”这个问题吗?)
最佳答案
幕后发生的事情是这样的:
var a = { a: 1 };
var b = { b: 2 };
var arr1 = [a, b];
var obsArray = ko.observableArray(arr2);
obsArray.subscribe(_ => console.log("change"));
var arr2 = [a, b];
// Logs change, since
// arr1 !== arr2
// even though:
// arr1[0] === arr2[0] and
// arr1[1] === arr2[1]
obsArray([a, b]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
我想说解决这个问题的最简单方法是检查订阅方法中的“平等”,但这主要是因为我不太了解映射插件......
我如何解决这个问题:
observableArray
和回调函数的辅助函数。equalityCheck
,它接受两个数组作为输入并返回 true
或 false
要将传递给 knockout 订阅的新值与前一个值进行比较,它需要存储对前一个值的引用。
这意味着您的语法将从:
vm.minions.subscribe(x => console.log("changed minions"));
至:
customSubscribe(vm.minions, x => console.log("changed minions"));
可能还有一种方法可以通过插件或扩展器来解决此问题...
const obsArraySubThatChecksInner = (arr, cb) => {
let prevValues = arr();
// Check if items are equal without checking the array reference
const equalityCheck = (arr1, arr2) => {
return arr1.length === arr2.length &&
arr1.every((item, i) => item === arr2[i]);
}
return arr.subscribe(newValues => {
// Make a copy to prevent mutations in cb
const newArray = newValues.slice();
if (!equalityCheck(prevValues, newValues)) {
cb(newValues);
};
prevValues = newArray;
});
};
var obsArr = ko.observableArray([1, 2, 3]);
var regularSub = obsArr.subscribe(vals => console.log("Regular sub:", JSON.stringify(vals)));
var specialSub = obsArraySubThatChecksInner(
obsArr, vals => console.log("Special sub:", JSON.stringify(vals))
);
// Is "similar", so will only trigger the regular sub.
obsArr([1, 2, 3]);
// Is different, so will trigger both
obsArr([1, 2]);
obsArr.push(3);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
将您的数据放在 fiddle 中:https://jsfiddle.net/nk074pb3/
关于javascript - 使用 ko.mapping.fromJS 的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43779310/
我使用 knockoutJS,当我使用“fromJS”时出现以下错误 TypeError: Cannot call method 'fromJS' of undefined 我的 JavaScript
我正在尝试使用 komapping 插件将属性转换为可观察的。 我确实有相同类型的对象数组,如下所示: var data =[{ b1: "v1", b2: "b21" }, { b1: "v2",
我想从我的 API 加载大约 10k 条记录 - 这是一个相当大的 JSON,但它并没有那么大,我想将它作为不可变对象(immutable对象)保存到 redux 状态: case GET_ALL:
Immutable.fromJS 的描述是: Deeply converts plain JS objects and arrays to Immutable Maps and Lists. 但这是错
不可变的 js - fromJS:处理文件上传(文件对象数组)似乎不可能转换为不可变的 fromJS做得很好即使是嵌套结构 喜欢: javascript const nested = [ { id:
我创建了一个自定义 fromJS 函数,以便当我将对象转换为不可变对象(immutable对象)时,结果将仅包含 OrderedSet 和 Map(而不是列表和 Map)。 除了在下面的情况下,对象中
我是 typescript 的新手。我一直在尝试将 knockout.mapping 与它一起使用,但是,我无法让它工作。 我已经安装了 knockout 和 knockout.mapping 的库,
当下面的对象被映射时,空""数组中的值在 observable 数组中映射为 false: var d2 = { "values": [{"9", false, "", true, null,
我希望能够查看我的不可变对象(immutable对象)以进行调试。我发现通过单击条目等来查看对象非常困难。理想情况下,我想要的是与 formJS 功能相反的东西 所以, const immutable
我的根 knockout 模型包含 VisitEntries 的集合,每个条目都有一个名为 RoomProfile 的对象。当用户创建访问条目(将房间添加到其访问列表)时,应加载该房间的配置文件数据并
我在我的应用程序中使用 KnockoutJS。今天我遇到错误 Uncaught TypeError: Cannot read property 'fromJS' of undefined在浏览器控制台
我有一个定义为 ko.observableArray([]) 的值,并使用 ko.mapping.fromJS 将来自 ajax 的数据附加到其中。但是,当我再次使用 ko.mapping.fromJ
我正在尝试使用 knockout 映射,但它没有像我预期的那样工作。在这里,我创建了我能做的最简单的 fiddle ,但它不起作用。 我错过了什么吗? https://jsfiddle.net/p48
我想将一些新的计算属性附加到从 REST 服务返回的复杂 json 对象。这可以通过 KnockoutJS 的 Mapping 插件轻松实现。 但这次我决定选择 AngularJS。有没有类似knoc
我一直收到错误:Uncaught TypeError: Cannot read property 'fromJS' of undefined这个想法是有 2 个页面,其中是 ui 表示,另一个是 he
我已经更新了一个表,其中包含我模型中的每个条目,并且在删除和添加到数组时触发了两个事件。 hideElement 调用 jquery“fadeOut”,showElement 调用 jquery“fa
使用 ko.mapping.fromJS() 创建的可观察数组具有可观察元素。我怎样才能让它表现得更像 ko.observableArray() ,其中数组是可观察的但数组的元素不是?谢谢。 最佳答案
我知道有一个函数 ko.utils.unwrapObserable() 但它似乎没有解开由 ko.mapping.fromJS() 映射的可观察对象 全部: console.log(listing);
我有一个复杂的对象,我想传递给ko.mapping.fromJS,我的问题是我只希望一个字段是可观察的,但其他属性要么是 null 要么是 non -根据我尝试过的方法存在。 我创建了一个 jsFid
我正在尝试 ko.mapping.fromJS(http://knockoutjs.com/documentation/plugins-mapping.html) 鉴于下面的代码和期望,有人可以向我解
我是一名优秀的程序员,十分优秀!