5

Есть ли способ настроить Knockout component на вместо элемент контейнера вместо того, чтобы вставлять его содержимое внутри элемента контейнера?Заменить элемент контейнера при использовании компонента нокаута

Например, если у меня есть пользовательский компонент, зарегистрированный в качестве my-custom-element со следующим шаблоном:

<tr> 
    <p>Hello world!</p> 
</tr> 

Можно ли использовать этот компонент, как это:

<table> 
    <tbody> 
     <my-custom-element></my-custom-element> 
    </tbody> 
</table> 

И есть конечный продукт будь то:

<table> 
    <tbody> 
     <tr> 
      <p>Hello world!</p> 
     </tr> 
    </tbody> 
</table> 

Вместо этого: (путь нокаута r Enders компонентов по умолчанию)

<table> 
    <tbody> 
     <my-custom-element> 
      <tr> 
       <p>Hello world!</p> 
      </tr> 
     </my-custom-element> 
    </tbody> 
</table> 

Based on the answer to this question, кажется, что эта функциональность встроена в шаблонизатор, который я предполагаю, что также используется при визуализации шаблонов компонентов.

Есть ли способ указать, что компонент должен быть визуализирован с помощью renderMode из replaceNode?

Я знаю о «виртуальный элемент» синтаксис, который позволяет компонентам быть определены внутри HTML комментарий:

<table> 
    <tbody> 
     <!--ko component { name: 'my-custom-element' }--><!--/ko--> 
    </tbody> 
</table> 

, но мне действительно не нравится этот синтаксис - написание реального кода комментарий чувствует, как грязный, грязный хак.

+1

Это звучит как [Rendering именованный шаблон] (http://knockoutjs.com/documentation/template-binding.html) является то, что вы ищете. Веб-компонент - это, вообще говоря, узел DOM, затенение его детей. Он не предназначен для _replaced_, так как само понятие разрушено в таком случае. – mudasobwa

ответ

4

Я представляю себе отсутствие этой опции может быть защищена как таковой, принимая во внимание природу библиотеки (там, я это сказал), и философия команда разработчиков:

Нокаут библиотека и в отличие от других ему MVC в не заставляет вас использовать определенный каркасом способ структурирования вашего приложения. Если вы рассматриваете механизм шаблонов в Knockout по сравнению со всеми другими JS-шаблонами (в Angular, underscore, усах и т. Д.), Нокаут выдается как единственный, но не «modding» собственный рендеринг HTML5. Все остальные используют пользовательский тег, будь то <% %> или {{ }}, который требует небольшого парсера JS для преобразования тегов во что-то значимое (теперь KO также имеет плагин Knockout punches, который включает в себя теги в стиле усов и, по общему признанию, KO делает «sin» a маленький бит с комментариями <!-- ko -->). KO вместо этого использует пользовательские элементы HTML 5, теги комментариев и атрибутов, полностью «vanilla».

Например, используется тип иерархии «объект (и реальная жизнь?) Типа JS/DOM: только родители могут когда-либо использовать силу своих детей, и поэтому связанный элемент не заменяется, а расширяется с детьми.Для иллюстрации:

// we cannot do this in JS 
document.getElementById('elem').remove(); //implied .remove(self) 
// instead we do this 
var elem = document.getElementById('elem'); 
container = elem.parentNode.removeChild(elem); 

В дальнейшем предпочтительный способ связывания данных с КО, проиллюстрированной также с помощью foreach связывания, является:

<div data-bind="foreach: myList"> 
    <span data-bind="text: $data"></span> 
</div> 

Предыдущий фрагмент кода будучи HTML-представление JS массив, иерархия снова виден:

var myArr = [1,2,3,4,5]; 
// we cannot do the following without reference to the array index, 
// which is not held by the object itself,  
// but a meta-property getting meaning relative to the parent 
myArr[0].splice(0,1); //remove 

Это приводит к тому, что ваш HTML-просмотр является совершенным ct репликации данных JS (и было бы интересно увидеть, как кто-то создает инструмент, который показывает уровни отступов привязки данных (с with и foreach) в документе HTML. Однако в некоторых случаях вам нужны теги комментариев, чтобы не нарушать планировку вашего HTML-кода или ваших правил CSS (вложенность), например, только текстовый компонент (i18n), который должен быть введен между текстом узлы:

<p>Some predefined text with 
<!-- ko text: 'some variable text' --><!-- /ko --> 
and more predefined text</p> 

Или, если вы не хотите пустой элемент, чтобы занять место, когда скрытые

<!-- ko if: !hidden() --><div id="myToggleableDiv"></div><!-- /ko --> 

и есть custom tags, которые являются стандартными и ад намного понятнее ; но, к сожалению, еще не готовы на 100%. Сначала выберите data-bind, <!-- ko --> второй и <custom> третий (был бы выше, если бы полностью реализован). Так или иначе, я вижу это. Что касается вашего конкретного случая, если компонент имеет модель списка, вы можете сделать:

<table data-bind="{component: {name: 'custom', params {..}}"></table> 

И включают tbody в вашей виртуальной машине, иначе, если это модель ListItem, вы можете использовать либо один из трех " синтаксисы, например, комментарий с синтаксисом

<table> 
    <tbody data-bind="foreach: mylist"> 
    <!-- ko component: {name: 'custom', params: $data} --><!-- /ko --> 
    </tbody> 
</table> 

Или отвязать ваш компонент полностью от необходимости быть вложенными внутри конкретного родителя (таблица), придерживаясь SOC principle, например:

<table> 
    <tbody data-bind="foreach: mylist"> 
    <tr data-bind="foreach: properties"> 
     <td data-bind="component: {name: 'custom', params: $data}></td> 
    </tr> 
    </tbody> 
</table> 

или с помощью пользовательского тега:

<table> 
    <tbody data-bind="foreach: mylist"> 
    <tr data-bind="foreach: properties"> 
     <td><custom params= "{data: myData"></custom></td> 
    </tr> 
    </tbody> 
</table> 

в том порядке предпочтения ..

2

Хорошие новости! В Knockout 3.3.0 они просто представили концепцию Passing markup into components. Это делается с использованием шаблона $componentTemplateNodes внутри вашего компонента.

Из связанного примера:

<template id="my-special-list-template"> 
    <h3>Here is a special list</h3> 

    <ul data-bind="foreach: { data: myItems, as: 'myItem' }"> 
     <li> 
      <h4>Here is another one of my special items</h4> 
      <!-- ko template: { nodes: $componentTemplateNodes, data: myItem } --><!-- /ko --> 
     </li> 
    </ul> 
</template> 

<my-special-list params="items: someArrayOfPeople"> 
    <!-- Look, I'm putting markup inside a custom element --> 
    The person <em data-bind="text: name"></em> 
    is <em data-bind="text: age"></em> years old. 
</my-special-list> 
Смежные вопросы