我已经高低搜索了这个答案,但是对于我的生活来说,我不能弄清楚我在做什么与官方例子不同,除了我认为我的用例有点更复杂:
http://knockoutjs.com/documentation/component-binding.html
基本上,我正在尝试创建可重用的UI元素。行为将基本上通过“params”对象传递给它们。我希望多个元素能够存在于单个页面上,然而,这是我遇到困难的地方。
我正在使用browserify捆绑我的代码并拥有以下内容(为简洁起见,某些条目被截断):
的index.html
<div data-bind='component: { name: "toggle" , params: {
enabledText: "Parental controls are enabled",
disabledText: "Parental controls are disabled"
}}'></div>
<div data-bind='component: { name: "toggle" , params: {
enabledText: "Same component, different behavior: enabled",
disabledText: "Same component, different behavior: disabled"
}}'></div>
main.js
var ko = window.ko = require('knockout'),
toggle = require('./components/toggle/toggle');
ko.components.register('toggle', toggle);
function Container() {
}
var con = new Container();
ko.applyBindings(con);
组件/肘/ toggle.js
var ko = require('knockout'),
template = require('./toggle.html');
function vm(params) {
var self = this;
self.enabled = ko.observable(false);
self.label = ko.computed(function() {
return self.enabled() ? params.enabledText : params.disabledText;
});
}
module.exports = { viewModel: vm, template: template };
最后,在components / toggle / toggle.html中:
<input type='checkbox' data-bind='checked: enabled' id='switch-checkbox' class='switch-input' />
<label for='switch-checkbox' class='switch-input-label'>
<span data-bind='text: label'></span>
</label>
我遇到的问题是组件都适当地出现在页面上,但点击第二个组件会激活第一个组件(并且对seconD没有任何作用)。我是Knockout的新手并且显然遗漏了一些东西,但我无法弄清楚如何解决我的问题。任何帮助都会非常感激!
奇怪的是标签是唯一的,表明为每个HTML实体实例化的组件(视图模型)实际上是唯一的...但是,看来敲门的“已检查”绑定只能绑定到第一个。
编辑:我知道习惯上包含一个例子,所以这里有一个关于codepen的例子。我为使用浏览器代码道歉,但希望它仍然可读:答案 0 :(得分:7)
当您加载此组件的多个实例时,id
标记上的input
属性和构成您组件的for
标记上的label
属性是不再是页面的独特之处。
您基本上有两个input
标记,其中id
和label
个标记位于一个id
。第二个组件上的label for="switch-checkbox"
从第一个组件而不是第二个组件中获取input id="switch-component"
。
虽然淘汰组件很棒,但遗憾的是组件实例之间没有隔离。
要解决此问题,您需要确保每个组件实例中id
和for
的值对整个页面都是唯一的。
我在此工作中包含了一个片段。
var uid = function(){
var seed = 1;
return {
new: function(p){
return p + (seed++);
}
}
}();
var template =
"<input type='checkbox' data-bind='checked: enabled, attr: {id:id}' class='switch-input' />\n<label data-bind='attr: {for: id}' class='switch-input-label'>\n <span data-bind='text: label'></span>\n</label>\n";
var viewModel = function vm(params) {
var self = this;
self.id = uid.new('switch-checkbox-');
self.enabled = ko.observable(false);
self.label = ko.computed(function() {
return self.enabled() ? params.enabledText : params.disabledText;
});
}
var component = {
viewModel: viewModel,
template: template
};
ko.components.register('toggle', component);
var vm = {};
ko.applyBindings(vm);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
position: relative;
height: 100%;
min-height: 100%;
}
.switch-input {
display: none;
}
.switch-input-label {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
position: relative;
display: inline-block;
cursor: pointer;
font-weight: 500;
text-align: left;
margin: 16px;
padding: 16px 0 16px 44px;
}
.switch-input-label:before,
.switch-input-label:after {
content: '';
position: absolute;
margin: 0;
outline: 0;
top: 50%;
transform: translate(0, -50%);
transition: all 0.3s ease;
}
.switch-input-label:before {
left: 1px;
width: 34px;
height: 14px;
background-color: #9e9e9e;
border-radius: 8px;
}
.switch-input-label:after {
left: 0;
width: 20px;
height: 20px;
background-color: #fafafa;
border-radius: 50%;
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.14), 0 2px 2px 0 rgba(0, 0, 0, 0.098), 0 1px 5px 0 rgba(0, 0, 0, 0.084);
}
.switch-input:checked + .switch-input-label:before {
background-color: #a5d6a7;
}
.switch-input:checked + .switch-input-label:after {
background-color: #4caf50;
transform: translate(80%, -50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind='component: { name: "toggle" , params: {
enabledText: "Parental controls are enabled",
disabledText: "Parental controls are disabled"
}}'></div>
<div data-bind='component: { name: "toggle" , params: {
enabledText: "Same component, different behavior: enabled",
disabledText: "Same component, different behavior: disabled"
}}'></div>
<div data-bind='component: { name: "toggle" , params: {
enabledText: "Same component, another instance: enabled",
disabledText: "Same component, another instance: disabled"
}}'></div>