使用递归模型时如何使用knockout的样式绑定

时间:2014-03-03 15:07:44

标签: knockout.js

我正在使用Knockout 3.0.0,我正在使用嵌套模型:一个形状可以包含任意数量的其他形状。

这是示例数据:

var process =
{
"type": "process",
"id": "singletask",
"name": "Default Process",
"children": [
    {"type": "task",
     "id": "Task_1",
     "name": "Task 1",
     "bounds": {
        "x": "435.0",
        "y": "175.0",
        "height": "50.0",
        "width": "110.0"
      },
      "children": []
    }
    ]
};

我构建了如下的视图模型:

function getBounds(bounds) {
    var res = {
                  "x": ko.observable(bounds.x),
                  "y": ko.observable(bounds.y),
                  "height": ko.observable(bounds.height),
                  "width": ko.observable(bounds.width)
             }
    return res;
}

/* recursively construct view model out of JSON data */
function getPartOfViewModel(data) {
    var children= [];
    $.each(data.children, function(i, e) {
        var res = getPartOfViewModel(e);
        children.push(res);
    });
    var res = {
        "type": ko.observable(data.type),
        "template": data.type + "-template",
        "id": ko.observable(data.type),
        "name": ko.observable(data.type),
        "children": children
    }

    // not all elements have bounds
    if (data.bounds) {
        $.extend(res, {"bounds":getBounds(data.bounds)});
    }
    return res;
}

var viewModel = getPartOfViewModel(process);

我认为在尝试创建计算条目时,我不能使用“this”,这有问题。 (这似乎是一个单独的问题)

HTML非常简单

<div data-bind="foreach: $data.children" class="drawingarea">
    <div data-bind="template: { name: $data.template, data: $data }"></div>
</div>

<script type="text/html" id="task-template">
    <div data-bind="css: type, style: {left: $data.bounds.x + 'px', top: bounds.top + 'px', height: $data.bounds.height + 'px', width: $data.bounds.width + 'px'}">
        <span data-bind="text: $data.bounds.x"></span>/<span data-bind="text: $data.bounds.y"></span>
        <span data-bind="text: $data.bounds.height"></span>/<span data-bind="text: $data.bounds.width"></span>
    </div>
</script>

问题是渲染的形状包含文本435.0/175.0 50.0/110.0,但没有正确的位置。我做错了什么?

完整示例:http://jsbin.com/robukuvu/1

2 个答案:

答案 0 :(得分:2)

试试这个:

data-bind="style: {left: $data.bounds.x() + 'px', top: $data.bounds.y() + 'px', height: $data.bounds.height() + 'px', width: $data.bounds.width() + 'px'}"

<强> 1 top部分中,您错过了$data前缀。

<强> 2 您的top结构中没有bounds字段,实际上您在y函数中将其命名为getBounds()

第3 由于您正在使用observable,Knockout能够处理$data.bounds.x(例如)而无需调用observable,但由于您将'px'连接到它,它会尝试将表达式作为一个整体来计算结果实际上是'px'附加到可观察函数。

这就是为什么您需要$data.bounds.x() + 'px'而不是$data.bounds.x + 'px'

答案 1 :(得分:2)

Working DEMO

您的代码很好,您只需要进行两项更改:

  1. 首先 ,对于css属性top,您要添加$data并将top替换为y。所以它应该是顶部:$data.bounds.y() + 'px'
  2. 第二, 您的对象xyheightwidth它们都是可观察对象然后在您的绑定中,无需使用(),也无需+ 'px'
  3. 最终正确的HTML代码:

    <div data-bind="css: type, style: {left: $data.bounds.x, top: $data.bounds.y, height: $data.bounds.height, width: $data.bounds.width}">