Javascript 同一视图中的多个敲除组件

Javascript 同一视图中的多个敲除组件,javascript,knockout.js,Javascript,Knockout.js,我到处寻找这个问题的答案,但我一辈子都无法找出我所做的与官方示例的不同之处,除了我认为我的用例有点复杂之外: 基本上,我正在尝试创建可重用的UI元素。行为基本上是通过“params”对象传递给他们的。但是,我希望在一个页面上能够存在多个元素,这正是我遇到困难的地方 我正在使用browserify捆绑我的代码,并具有以下内容(为了简洁起见,某些条目被截断): index.html <div data-bind='component: { name: "toggle" , params: {

我到处寻找这个问题的答案,但我一辈子都无法找出我所做的与官方示例的不同之处,除了我认为我的用例有点复杂之外:

基本上,我正在尝试创建可重用的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>
components/toggle/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>

我遇到的问题是,这两个组件都适当地出现在页面上,但单击第二个组件会激活第一个组件(第二个组件不会执行任何操作)。我是新手,很明显我遗漏了一些东西,但我不知道如何解决我的问题。任何帮助都将不胜感激

奇怪的是,标签是适当唯一的,这表明为每个HTML实体实例化的组件(视图模型)实际上是唯一的……然而,knockout的“选中”绑定似乎只绑定到第一个

编辑:我知道通常会包括一个例子,所以这里有一个关于codepen的例子。我很抱歉使用了browserified代码,但希望它仍然可读:


当您加载此组件的多个实例时,
input
标记上的
id
属性和
标签上的
for
属性将不再是该页面的唯一属性

实际上,您有两个
input
标记,它们具有相同的
id
和两个
label
标记,目标是一个
id
。第二个组件上的
标签
从第一个组件而不是第二个组件拾取
input id=“switch component”

尽管敲除组件很棒,但不幸的是,组件实例之间没有dom隔离

要解决此问题,您需要确保组件的每个实例中的
id
for
的值对于整个页面是唯一的

我已经包括了这项工作的下面一个片段

var uid=function(){
var种子=1;
返回{
新:功能(p){
返回p+(seed++);
}
}
}();
变量模板=
“\n\n\n\n”;
var viewModel=函数vm(参数){
var self=这个;
self.id=uid.new('switch-checkbox-');
自启用=可观测(假);
self.label=ko.computed(函数(){
返回self.enabled()?params.enabledText:params.disabledText;
});
}
变量分量={
viewModel:viewModel,
模板:模板
};
ko.组件。寄存器('切换',组件);
var vm={};
ko.应用绑定(vm)
*{
保证金:0;
填充:0;
框大小:边框框;
}
html{
位置:相对位置;
身高:100%;
最小高度:100%;
}
.开关输入{
显示:无;
}
.开关输入标签{
-webkit用户选择:无;
-moz用户选择:无;
-ms用户选择:无;
-o-用户选择:无;
用户选择:无;
位置:相对位置;
显示:内联块;
光标:指针;
字号:500;
文本对齐:左对齐;
利润率:16px;
填充:16px 0 16px 44px;
}
.开关输入标签:之前,
.开关输入标签:后{
内容:'';
位置:绝对位置;
保证金:0;
大纲:0;
最高:50%;
转换:翻译(0,-50%);
过渡:所有0.3秒缓解;
}
.开关输入标签:之前{
左:1px;
宽度:34px;
高度:14px;
背景色:#9e9e9e;
边界半径:8px;
}
.开关输入标签:后{
左:0;
宽度:20px;
高度:20px;
背景色:#fafafa;
边界半径:50%;
盒影: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);
}
.开关输入:选中+.开关输入标签:之前{
背景色:#a5d6a7;
}
.开关输入:选中+.开关输入标签:后{
背景色:#4caf50;
转换:翻译(80%,-50%);
}


你是救命恩人!我真的希望这个答案能对其他人有所帮助,因为我花了好几个小时来思考这个问题。很高兴我能帮助巴迪:)从语义上讲,根据HTML规范,HTML id应该总是唯一的。有什么技术原因不能复制它们吗?不是真的,但这是一个有助于防止上述情况的最佳实践。如果您在文档中看到一个id,应该假定它在其他地方不存在。
<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>