2015-10-19 4 views
1

У меня возникли проблемы с компонентами knockoutjs, я следую примеру в official knockout component documentation.Вызов компонента на главной странице в knockoutjs

Как я могу назвать свой компонент виджета на главной странице? Я думаю, что я могу помещать код в неправильные места.

Код: 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()); 
+2

Просто добавьте '<как-или-нелюбовь>' для вашего HTML. – Dandy

+0

@ Dandy: Не повезло –

+3

В примере используется 'require.js' для загрузки viewmodel и шаблона, но вы не используете его в своем html. – Dandy

ответ

2

Похоже, вы потеряли немного, когда documentation объясняет, как загрузить компоненты из внешних файлов с помощью requirejs.

Я думаю, что может помещать код в неправильных местах

Да, вы действительно неуместны часть кода. Давайте вас обратно на треке:)

Во-первые, код в вашем widget.js принадлежит в вашем main.js вместе с вызовом ko.components.register.

Во-вторых, разметка у вас есть в widget.html, для модели представления, принадлежит index.html.

В-третьих,, вам, похоже, не хватает кода и разметки для самого виджета.

Взгляните на рабочий пример ниже. Я поставил файл, в который каждый бит кода входит в комментарии над кодом.

Вы не необходимо определить имена модулей, передавая их в качестве первого аргумента в requirejsdefine функции, как у меня есть:

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

Это только там, чтобы работать в Stack Snippet , requirejs использует соглашение, основанное на пути к файлам, если имя модуля не входит в комплекте, например requirejs будет искать файл с именем widget.js в папке файлов когда дано имя модуля files/widget. Пожалуйста, прочитайте requirejs docs.

// 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()); 
 
})
<!-- 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>

+1

Это неправильный подход, если вы используете 'require.js', помещая каждую вещь в один файл. «Widget.html» не следует включать в файл 'index.html', и он не должен быть определен как модуль. Текстовый плагин 'require.js 'загружает и при необходимости вводит его. – Dandy

+2

@Dandy все в одном файле, чтобы получить пример работы в фрагменте. Если вы посмотрите на документацию OP, то что OP имеет в * widget.html * на самом деле не компонентную разметку, это разметка, вызывающая компонент. Так что да, это должно быть в * index.html *. –

+0

Ответ кажется правильным, но он находится в одном файле. не уверен, какая часть идет туда. –