0

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

它基本上是创建一个由两个 observableArrays 组成的 observableArray,每个 observableArrays 有 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 等的任何其他评论。

4

2 回答 2

3

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

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

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

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

重构推荐:

如果您的 observableArray 为空,foreach 绑定将自动处理不呈现 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: {} }
    ])
})};

在这里,您将返回一个 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 注释。

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

安全的赌注,保持一致,不要将这些与编写函数的方法混合和匹配。

于 2013-02-13T05:49:59.707 回答
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>

诚然,我不理解您的其余代码(因为您使用的变量名称和模式很难理解)。

于 2013-02-13T02:19:08.973 回答