使用Knockout JS进行Ajax查询

时间:2013-11-22 09:37:50

标签: knockout.js

我尝试使用Knockout JS在表格中显示项目列表。这类似于典型的搜索界面,用户在其中键入查询,界面显示搜索引擎返回的结果列表。我首先通过AJAX调用从服务器检索它们,然后尝试绑定它们。这非常适用于第一个查询。但是当我尝试第二个查询(以及后续查询)时,每个结果项表示10次(重复),然后对于第3个查询,每个项目显示30次(依此类推)。以下是代码。

<body >
<p>
  <input type="search" id="skynet-query" name="q" placeholder="scientific search" autofocus />
  <input type="submit" id="skynet-submit" value="Ignite!" onclick="getAttachments(document.getElementById('skynet-query').value)" />
</p>
<article data-bind="foreach: seats">   
        <h3>
            <input data-bind="attr:{value: papers().id }" type="checkbox" name="article-to-basket" />
            <a data-bind="attr:{href: papers().url }, text: papers().title"> </a>
        </h3>
        <address class="authors" data-bind="text: papers().authors"/>
</article>
</body>

以下是脚本部分

<script>

 var array = new Array();

function getAttachments(keyword) {

  var request = $.ajax({
    type: "GET",
    datatype: "json",
    url: "get-papers?q="+keyword+"&format=json&full-articles=true&kw-count=10&article-count=10&task-type=m1"
  });

  request.done(function (response) {

    for (i=0;i<response.articles.length; i++){
        array[i] = new PaperData(response.articles[i]);
    }
    ko.cleanNode(document);
    ko.applyBindings(new ReservationsViewModel());
    console.log("DONE");
  });

}

function PaperData(papers) {
    var self = this;
    self.papers = ko.observable(papers);
}

function ReservationsViewModel() {
    //var self = this;
    self.seats = ko.observableArray(array);

}

</script>

有人可以帮我找到这段代码有什么问题吗?

这就是我的数据模型的样子

 {
    articles: [
    {
    "is-saved": false,
    title: "title",
    abstract: "Abstract",
    date: "2005-01-01 00:00:00",
    "publication-forum": "forum",
    "publication-forum-type": "article",
    authors: "Authors",
    keywords: "keyword1, keyword2, keywordn",
    id: "4f5a318e573ce53e03000015"
    }
    ]

    }

1 个答案:

答案 0 :(得分:1)

你的击倒方法并不完全正确。

  • 您在屏幕上显示的每个值都应该是与您的视图模型相关联的可观察对象。
  • 例如,带有名称的输入元素是不必要的 - value绑定负责更新视图模型。您永远不必按名称处理<input>
  • 不要使用内联事件处理程序,例如onclick。不在Knockout而不是其他任何地方。
  • 不要使用全局变量。您的问题来自于使用全局array变量,实际上该变量应该是您的视图模型上的可观察数组。
  • 不要因为某些事情发生变化而清除所有内容并从头开始重建整个视图模型。 Knockout将处理任何部分更新。

这是一种改进的方法。

<p>
  <input type="search" data-bind="value: query" placeholder="scientific search" autofocus />
  <input type="submit" data-bind="click: getAttachments" />
</p>
<article data-bind="foreach: seats">   
    <h3>
        <input data-bind="value: id, checked: selected" type="checkbox" />
        <a data-bind="attr: {href: url}, text: title"></a>
    </h3>
    <address class="authors" data-bind="text: authors"/>
</article>

function PaperData(data) {
    ko.utils.extend(this, data);
    this.selected = ko.observable(false);
}
PaperData.create = function (data) {
    return new PaperData(data);
};

function ReservationsViewModel() {
    var self = this;

    self.query = ko.observable();
    self.seats = ko.observableArray();

    self.queryParams = {
        "q": self.query,
        "format": "json",
        "full-articles": true,
        "kw-count": 10,
        "article-count": 10,
        "task-type": "m1"
    };

    self.getAttachments = function () {
        $.get("get-papers", ko.toJS(self.queryParams))
        .then(function (response) {
            return ko.utils.arrayMap(response.articles, PaperData.create);
        })
        .done(self.seats);
    };
}

ko.applyBindings(new ReservationsViewModel());

注释

  • 您可以使用.then()动态转换Ajax响应数据。
  • 您可以使用.done()将转换后的结果写入observable。
  • 使queryParams成为视图模型的单独属性,您可以动态调整其他查询参数,就像"q"所示。
  • 您可以使用ko.utils.extend将属性从一个对象传输到另一个对象。或者,您可以使用映射插件。