我有以下 JavaScript:
function RandomViewModel() {
var self = this;
self.RnadomSquaresK = ko.observableArray([
randomSquare(),
randomSquare(),
]);
}
var randomSquare = function() { return ko.observable({
innate: ko.observableArray([
{ star: "test1", Class: "starList", Style: {} },
{ star: "test2", Class: "starList", Style: {display:'inline'} },
{ star: "test3", Class: "starList", Style: {} },
{ star: "test4", Class: "starList", Style: {} }
])
})};
ko.applyBindings(new RandomViewModel());
它基本上是创建一个由两个 observableArray 组成的 observableArray,每个都有 4 个元素。
我有以下 html:
<script id="starTemplate" type="text/html">
<!-- ko if: ($index >= 0) -->
<div data-bind="text: $index, attr: { class: Class }, style: Style"></div>
<!-- /ko -->
</script>
<div class="starList" data-bind="template: { name: 'starTemplate', foreach: RnadomSquaresK()[0]().innate }"></div>
我期望创建 div,并根据它们绑定(bind)到的 observableArray 打印它们的每个索引。 (在本例中:4 个 div,因为所有索引都应等于或大于 0)
我实际得到的是:空白。
这是 JSFiddle 链接:http://jsfiddle.net/qrwBE/
如果我将 if 语句更改为 ex: if: $index != 0
,我会打印绑定(bind)到数组的所有 4 个元素,但我不太明白为什么在这种情况下第一个元素(索引 0)与其他 3 个元素一起打印。
我是否错误地使用了 if
语句?
非常欢迎对正在发生的事情进行解释,以及有关 javascript 等的任何其他评论。
最佳答案
所以这里有很多项目需要检查:
为什么 foreach 循环不显示其中包含索引值的 div?
答案是因为你$index()
是一个可观察量,它们是函数。所以你必须像我上面演示的那样使用它。原因if: $index != 0
之所以有效,是因为在 javascript 中,计算结果为 0 的内容为 false,任何非零计算结果为 true(如果您熟悉这些语言,就像在 c/c++ 中一样。
所以这意味着当你写if: $index != 0
时你真正说的是函数 $index not null or undefined?
这是正确的,因此它将继续从您的模板输出 div。
重构建议:
如果 observableArray 为空,foreach 绑定(bind)将自动处理不渲染 div 标签的问题。这意味着您可以完全删除 if 检查...这也可以解决您的问题。
<script id="starTemplate"a type="text/html">
<div data-bind="text: $index, attr: { class: Class }, style: Style"></div>
</script>
模型更改:
让我们检查一下这个函数:
var randomSquare = function() { return ko.observable({
innate: ko.observableArray([
{ star: "test1", Class: "starList", Style: {} },
{ star: "test2", Class: "starList", Style: {display:'inline'} },
{ star: "test3", Class: "starList", Style: {} },
{ star: "test4", Class: "starList", Style: {} }
])
})};
这里您返回一个可观察的对象,其中包含一个名为 innate 的属性,它是一个可观察的数组。为什么不直接删除包含在可观察对象中的内容,因为它只会使访问数组的语法变得更时髦 RnadomSquaresK()[0]().innate
与其这样,不如采用以下方法:
var randomSquare = function() { return {
innate: ko.observableArray([
{ star: "test1", Class: "starList", Style: {} },
{ star: "test2", Class: "starList", Style: {display:'inline'} },
{ star: "test3", Class: "starList", Style: {} },
{ star: "test4", Class: "starList", Style: {} }
]});
})};
这将简单地访问它:RnadomSquaresK()[0].innate
何时使某些东西可观察
请记住,如果您打算在可观察的状态发生变化时向 UI 或 js 中的订阅者函数发出警报,那么您只需要将某些东西设为可观察的。否则,只需将其设置为复制值(普通的旧 js 变量)。
将函数声明与函数表达式混合的危险(提升问题): 这纯粹是一个js笔记。
这是一个函数声明function RandomViewModel() { }
这是一个函数表达式var randomSquare = function() { };
解释器处理它们的方式略有不同。第一个(声明)将被提升到其父作用域的顶部。因此在后续代码中调用RandomViewModel()
将完美地工作,因为由于解释器,它是在其他所有内容之前定义的。
但是,第二个(表达式)只会将变量名称提升到顶部,但它的赋值将保留在原来的位置,这意味着您的代码将等效于:
function RandomViewModel() { }
var randomSquare;
randomSquare = function() { };
这对于您的情况来说效果很好。但是,随着您的模型变得更加复杂并且彼此之间的耦合更加紧密,您最终可能会遇到类似以下场景的问题:
function RandomViewModel() {
var x = randomSquare(); //<-- would throw an undefined exception here
alert(x);
}
var model = new RandomViewModel();
var randomSquare = function() { return 5; };
发生这种情况是因为口译员提升了您的 var randomSquare
到范围的顶部,但直到尝试在 RandomViewModel
中使用它之后才为其分配函数。
安全打赌,保持一致,不要混合搭配这些来编写函数。
关于javascript - KnockoutJS if 语句有效性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14845242/