KnockoutJS如果声明有效

时间:2013-02-13 01:59:10

标签: javascript knockout.js

我有以下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>

我希望根据他们所绑定的observableArray打印每个索引来创建div。 (在这种情况下:4个div,因为所有索引应该等于或大于0)

我真正得到的是:空白。

这是JSFiddle链接:http://jsfiddle.net/qrwBE/

如果我将if语句更改为ex:if: $index != 0,我将打印绑定到数组的所有4个元素,但我不太明白为什么在这种情况下第一个元素(索引0)正在与其他3个元素一起印刷。

我是否错误地使用if语句?

对正在发生的事情的解释以及关于javascript等的任何其他评论都非常受欢迎。

2 个答案:

答案 0 :(得分:3)

所以这里要检查的项目有很多:

为什么你的foreach循环不显示带有索引值的div?

答案是因为你$index()是一个可观察的,它是函数。所以你必须像我上面演示的那样使用它。 if: $index != 0工作的原因是因为在javascript中,评估为0的事物是假的,任何非零评估为真(就像你熟悉这些语言一样在c / c ++中。

所以这意味着当你写if: $index != 0时你真正说的是,函数$index not null or undefined?是真的,所以它会继续从你的模板输出div。

重构建议:

如果observableArray为空,foreach绑定将自动处理不呈现div标记。这意味着你可以完全删除if check,这也可以修复你的问题。

<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: {} }
    ])
})};

在这里,您将返回一个observable,其中包含一个名为innate的属性,它是一个可观察的数组。为什么不删除它包含在一个observable中,因为它只会使访问数组的语法更加时髦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 note。

这是一个函数声明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

尝试使用之后才会为其分配功能

安全下注,保持一致,不要将这些与appraoches混合搭配写作函数。

答案 1 :(得分:1)

在绑定中执行javascript表达式时,需要获取属性的值:

http://jsfiddle.net/wiredprairie/EWrsF/

if: $index() > 0

使用中:

<script id="starTemplate" type="text/html">
    <!-- ko if: $index() >  0 -->
    <div data-bind="text: star, attr: { class: Class }, style: Style"></div>
    <!-- /ko -->
</script>

我承认你不理解你的其余代码(因为你正在使用的变量名和模式很难理解)。