在knockoutjs中调用主页面上的组件

时间:2015-10-19 07:08:45

标签: javascript html html5 knockout.js knockout-3.0

我在使用knockoutjs组件时遇到了一些问题,我正在关注official knockout component documentation中的示例。

如何在主页面上调用我的小部件组件?我想我可能会把代码放在错误的地方。

代码:的index.html

<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script type="text/javascript" src="js/libs/knockout/knockout-3.3.0.js" ></script>
        <script type="text/javascript" src="js/widget.js" ></script>
    </head>
    <body>
        <div>TODO write content</div>
    </body>
</html>

main.js

ko.components.register('like-or-dislike', {
    viewModel: { require: 'files/widget' },
    template: { require: 'text!files/widget.html' }
});

alert(ko.components.isRegistered('like-or-dislike'));

widget.html

<ul data-bind="foreach: products">
    <li class="product">
        <strong data-bind="text: name"></strong>
        <like-widget params="value: userRating"></like-widget>
    </li>
</ul>

widget.js

function Product(name, rating) {
    this.name = name;
    this.userRating = ko.observable(rating || null);
}

function MyViewModel() {
    this.products = [
        new Product('Garlic bread'),
        new Product('Pain au chocolat'),
        new Product('Seagull spaghetti', 'like') // This one was already 'liked'
    ];
}

ko.applyBindings(new MyViewModel());

1 个答案:

答案 0 :(得分:2)

documentation解释如何使用requirejs从外部文件加载组件时,看起来有点失踪。

  

我想我可能会把代码放在错误的地方

是的,你确实错误地放了一些代码。让我们回到正轨:)

首先 widget.js 中的代码与ko.components.register的调用一起属于 main.js

其次,您在 widget.html 中的标记对于您的视图模型属于 index.html

第三,您似乎错过了小部件本身的代码和标记。

看看下面的工作示例。我在代码上方的注释中放了每个代码所属的文件。

需要通过将模块名称作为第一个参数传入 requirejs define函数来定义模块名称,如下所示:

define("files/widget",...
define("main",...

这只适用于Stack Snippet。如果未提供模块名称, requirejs 使用基于文件路径的约定,例如requirejs将在名为文件的文件夹中查找名为 widget.js 的文件给出模块名称files/widget。请阅读requirejs docs

&#13;
&#13;
// This goes in widget.html, only the html. 
// This example uses the define function only to work in this snippet.
define("text!files/widget.html", [], function() {
  return '<div class="like-or-dislike" data-bind="visible: !chosenValue()">\
            <button data-bind="click: like">Like it</button>\
            <button data-bind="click: dislike">Dislike it</button>\
        </div>\
        <div class="result" data-bind="visible: chosenValue">\
            You <strong data-bind="text: chosenValue"></strong> it\
        </div>'
});

// This goes in in widget.js, you must use the define function. 
define("files/widget", [], function() {
  return function(params) {
    // Data: value is either null, 'like', or 'dislike'
    this.chosenValue = params.value;

    // Behaviors
    this.like = function() {
      this.chosenValue('like');
    }.bind(this);
    this.dislike = function() {
      this.chosenValue('dislike');
    }.bind(this);
  }
});

// all of the below goes into main.js
require.config({
  paths: {
    "knockout": "http://knockoutjs.com/downloads/knockout-3.3.0",
    "text": "https://rawgit.com/requirejs/text/master/text"
  }
});

define("main", ["knockout"], function(ko) {
  ko.components.register('like-or-dislike', {
    viewModel: {
      require: 'files/widget'
    },
    template: {
      require: 'text!files/widget.html'
    }
  });

  function Product(name, rating) {
    this.name = name;
    this.userRating = ko.observable(rating || null);
  }

  function MyViewModel() {
    this.products = [
      new Product('Garlic bread'),
      new Product('Pain au chocolat'),
      new Product('Seagull spaghetti', 'like') // This one was already 'liked'
    ];
  }

  ko.applyBindings(new MyViewModel());
})
&#13;
<!-- this goes in the body of index.html -->
<ul data-bind="foreach: products">
  <li class="product">
    <strong data-bind="text: name"></strong>
    <like-or-dislike params="value: userRating"></like-or-dislike>
  </li>
</ul>

<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.19/require.min.js" data-main="main"></script>
&#13;
&#13;
&#13;