Моя проблема:
Я пытаюсь написать небольшое приложение Knockout JS в Magento 2, я изо всех сил пытаюсь инициализировать приложение, так как, когда я ko.applyBindings(AppViewModel, document.getElementById("koTest"));
его использую, он ломает Knockout, используемый Magento, и выдает эту ошибку:
Uncaught Error: You cannot apply bindings multiple times to the same element.
Я подозреваю, что это из-за:
Я подозреваю, что это потому, что Magento 2 уже использует ko.applyBindings()
внутри app/code/Magento/Ui/view/base/web/js/lib/knockout/bootstrap.js
. И поскольку это не определяет узел, я не могу использовать ko.applyBindings
снова.
Если я не использую ko.applyBindings(AppViewModel, document.getElementById("koTest"))
в своем коде, то мое приложение не инициализируется.
Это заставляет меня думать, что мне нужно каким-то образом использовать ko.applyBindings()
in knockout / bootstrap.js, но я не знаю, как, кто-нибудь может помочь? У меня мало опыта с нокаутом.
Мой код
<script type="text/javascript">
require([
'ko'
], function(ko) {
// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
this.firstName = ko.observable("Bert");
this.lastName = ko.observable("Bertington");
this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this);
this.capitalizeLastName = function() {
var currentVal = this.lastName();
this.lastName(currentVal.toUpperCase());
};
}
ko.applyBindings(AppViewModel, document.getElementById("koTest"));
});
</script>
<!-- This is a *view* - HTML markup that defines the appearance of your UI -->
<div id="koTest">
<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>
<p>Full name: <strong data-bind="text: fullName"></strong></p>
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<p>Full name: <input data-bind="value: fullName" /></p>
<button data-bind="click: capitalizeLastName">Capitalise</button>
</div>
источник
Ответы:
Простой метод, где вам не нужно использовать HTML-шаблоны
Благодаря Vinai Kopp я наконец получил ответ на этот вопрос, он намного проще, чем мой предыдущий хакерский обходной путь (я чистил узлы). Все, что вам нужно сделать, это определить
'ko'
как зависимость и добавить свой код в функцию возврата.Ниже приведен простой пример, который отображает некоторый текст, переданный через JSON.
app/code/VENODR/MODULE/view/frontend/templates/knockout-example.phtml
Здесь мы сообщаем Magento область действия наших компонентов (это должно соответствовать
data-bind: "scope: 'example-scope'"
и передавать любые дополнительные данные. Это может быть базовый URL, простое сообщение, почти все, что вы хотите. Я передал строку (PHP echo) в качестве примераИ вот мы пишем наш Javascript.
app/code/VENDOR/MODULE/view/frontend/web/js/knockout-example.js
Результат
---------------------
Метод, в котором вам нужно использовать шаблоны HTML
Если вы хотите использовать систему шаблонов HTML в Magento2 / Knockout (которая, как я полагаю, вам понадобится для каких-либо значительных частей работы), вам нужно внести несколько изменений по сравнению с моим упрощенным ответом (ниже).
Если вам не нужна функциональность шаблона, прокрутите вниз до моего старого упрощенного ответа.
Файлы, которые я использую для этого примера:
app/design/frontend/VENDOR/THEME/Magento_Cms/templates/knockout.phtml
app/design/frontend/VENDOR/THEME/Magento_Cms/web/js/knockout-example.js
app/design/frontend/VENDOR/THEME/Magento_Cms/web/template/test.html
Файл шаблона PHTML
Единственное изменение в нашем шаблоне PHTML - это вызов
getTemplate()
функции:Файл JS (компонент)
Есть несколько изменений, которые необходимо внести в файл JS, я подробно опишу их ниже.
1 - Ваша функция возврата теперь должна расширять модуль uiComponent:
2 - Вам нужно добавить
initialize
функцию и вызватьthis._super()
.this._super()
вызовет функцию родительского компонента с тем же именем. Так что в данном случае я думаю , что он будет вызыватьinitialize
изuiComponent
.3 - Необязательно - Здесь вы также можете установить некоторые значения по умолчанию для вашего компонента, я думаю, что это хорошая практика, которой нужно следовать, поскольку с вашим компонентом легко работать. При повторном использовании вы можете сохранить значения по умолчанию или, если вы хотите изменить его, вы можете вызвать его с новыми аргументами без изменения компонента.
Например, если вы смотрите на значения по умолчанию в JS она устанавливает
exampleMessage
на'Hello?'
еще страница делает текст какHello Magento Stack Exchange!
. Это потому, что я перезаписалexampleMessage
файл PHTML при вызове компонента.HTML-шаблон
Я все еще копаюсь и смотрю, на что способны HTML-шаблоны, я предполагаю, что здесь можно использовать функции, упомянутые в документации по Knockout JS, что делает их довольно гибкими.
Я только что добавил текст lorem ipsum, я, скорее всего, предоставлю еще один вопрос / ответ, как только выясню, что могут делать шаблоны HTML.
Результат и перезапись по умолчанию
Как упоминалось ранее, вы можете видеть, что я переписал
exampleMessage
в шаблоне, вы можете видеть, как он работает, когда текст читаетсяHello Magento Stack Exchange
.Если я удалю переопределение в файле шаблона
exampleMessage
, вернется к значению по умолчаниюHello?
. Мне действительно нужно удалитьvar/view_preprocessed
иpub/static/frontend
после изменения этого, хотя. Я предполагаю, что Magento кешировал значение.источник
https://github.com/seeni9589/Magento2/tree/master/Smart/Feedback
Пользовательская форма обратной связи с нокаутом JS. Надеюсь, поможет.
источник