淘汰组件(不)绑定到新内容
Posted
技术标签:
【中文标题】淘汰组件(不)绑定到新内容【英文标题】:Knockout components (not) binding on new content 【发布时间】:2015-01-24 02:42:41 【问题描述】:编辑的问题和示例
我试图让 Knockout 组件在初始 ko.applyBindings();
之后绑定,以便我可以动态添加自定义元素。
在我的原始帖子中,我提到了通过 ajax 加载内容,但是当使用 jQuery append
之类的东西将自定义元素添加到 DOM 时,就会出现问题。
这是一个例子:
$(function()
// Register a simple widget:
ko.components.register('like-widget',
template: '<div class="alert alert-info">This is the widget</div>'
);
// Apply bindings
ko.applyBindings();
// Wire up 'add' button:
$('#btnAdd').on('click', function()
$('#addZone').append("<like-widget></like-widget>");
);
);
<link data-require="bootstrap-css@*" data-semver="3.2.0" rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<body>
Here's a widget, declared inline:
<like-widget></like-widget>
<button id='btnAdd'>Add a new widget to the grey box:</button>
<br/><br/>
<div id='addZone' class="well">
Widgets will be appended here
</div>
<p>When you run this code, the widget custom element is indeed added to the box (see source) but the widget's template is not bound, so nothing appears. How do I get it to bind/appear?</p>
</body>
原帖
我已经成功创建了我的新组件<mynew-widget></mynew-widget>
我已经看到了在我的页面上添加它们的乐趣,并且一切都运行良好......直到我加载包含<mynew-widget></mynew-widget>
的新内容(例如,加载 AJAX 的模式弹出窗口)。什么都没有发生。
这是 Knockout 的限制还是我接线错误?
请告诉我是后者 - 因为我喜欢不必担心何时/在何处调用 ApplyBindings 以及在 DOM 的哪些部分。
经过深思熟虑,我知道淘汰赛需要注意自定义元素已添加到 DOM 中 - 但我希望它可能只是以 jQuery '$().on(...)
' 之类的方式工作。
【问题讨论】:
您需要包含您正在尝试做的事情的代码示例。照原样,我们无法帮助您调试 以上+你可能没有正确接线 好的 - 已编辑和重新调整。另外 - 我知道你可能想用 KO 本身实现 btnAdd 功能,但我只想说我不想允许完全的灵活性。 【参考方案1】:组件绑定不会神奇地发生:它会在您调用ko.applyBindings();
时发生。此时,在绑定的 html 中搜索组件,并绑定。
稍后,当您向页面动态添加新组件时,它不会被绑定,除非您显式绑定它。因此,在您的代码中,该组件被完全忽略。
如上所述,您需要做的是显式绑定它。但是必须考虑到不能绑定已经绑定的节点。但是,使用 jquery 创建节点、将其附加到 DOM 并绑定它非常容易。有一种语法可以指定视图模型和要绑定它的节点:ko.applyBindings(viewModel, node);
Here you have a full working sample in jsfiddle。这是那个小提琴中的代码:
HTML:
这是一个小部件,声明为内联:
<button id='btnAdd'>Add a new widget to the grey box:</button>
<br/><br/>
<div id='addZone' class="well">
Widgets will be appended here
</div>
ko.components.register('like-widget',
template: '<div class="alert alert-info">This is the widget</div>'
);
ko.applyBindings()
$('#btnAdd').on('click', function()
// Create your widget node
var $newWidget = $('<like-widget>');
// Append it to your "append area"
$('#addZone').append($newWidget);
// Apply bindings to the newly added node
ko.applyBindings(, $newWidget[0]);
);
注意:当调用应用绑定时,我传递了一个空对象:不要传递空值,否则会出错。如果您的模板包含视图模型,它将独立于传递的视图模型使用。
注意:$newWidget 是一个 jquery 对象。 $newWidget[0] 是 jQuery 对象的第一个(也是唯一一个)DOM 元素,如 applyBindings 所要求的
【讨论】:
好的,谢谢,这个很清楚了。您是否认为有可能以某种方式将其包装起来,以便开发人员可以仅在 HTML 中以万无一失的方式添加这些组件?例如,通过观察整体 DOM 突变并触发 applyBindings()? 可以观察到 HTML 突变 (***.com/questions/2844565/…)。但是你必须小心我上面解释的一些事情:你不能在同一个元素上应用两次绑定。这包括不对已绑定元素的子元素应用绑定。但是,当您动态添加项目时,您似乎没有这个问题。请尝试一下,如果你遇到这个问题,请告诉我。有一种技术可以避免元素及其子项绑定。以上是关于淘汰组件(不)绑定到新内容的主要内容,如果未能解决你的问题,请参考以下文章
使用 jQuery-ui 对话框的 Knockout 组件忽略绑定
将 vue js 应用程序绑定到 django 模板不显示任何内容