KnockoutJS foreach 绑定在所选项目周围添加轮廓
KnockoutJS foreach binding add outline around selected items
我有一个显示为按钮的淘汰可观察项目数组:
<div class="btn-group" data-bind="foreach: myList">
<button data-bind="css: Sel == false ? 'btn btn-white' : 'btn btn-dark', click:$root.makeChange, text:$data.Id, attr:{'id':'h_'+$data.Id}"></button>
</div>
我需要为其添加轮廓
对于 Sel
设置为 true
的项目。
我试过使用 outline: 2px solid black; outline-offset: 1px;
但它会在每个按钮周围添加轮廓,而不是为组添加轮廓,并且轮廓的右线绘制在下一个按钮后面。
我也尝试过使用边框,并用 JS 添加它们,但是我没有按钮和边框之间的 space。
outline
属性 感觉是解决这个问题的正确方法,但它只允许概述单个元素,并且只允许完整的轮廓。
这意味着活动元素必须包裹在一个容器中,并且该容器必须接收轮廓。
这可以通过计算可观察值来完成,该可观察值会变成一个平面列表:
[
{text: 'Mon', active: true},
{text: 'Tue', active: true},
{text: 'Wed', active: true},
{text: 'Tue', active: false},
{text: 'Fri', active: false},
{text: 'Sat', active: true},
{text: 'Sun', active: true}
]
进入嵌套:
[
[
{text: 'Mon', active: true},
{text: 'Tue', active: true},
{text: 'Wed', active: true}
],
[
{text: 'Tue', active: false},
{text: 'Fri', active: false},
],
[
{text: 'Sat', active: true},
{text: 'Sun', active: true}
]
]
取决于哪个项目是 active
。
以下是我将如何在淘汰赛中实现它。
- 一个
Button
视图模型,它跟踪自己的 active
状态并允许切换它
- 包含按钮和动态计算的
buttonGroups
的 ButtonList
视图模型。
- 基于此创建
.btn-group
和 .btn-group.active
div 的视图。
下面的互动示例:
function Button(params) {
this.text = params.text;
this.active = ko.observable(params.active);
this.toggle = () => this.active(!this.active());
}
function ButtonList(params) {
this.buttons = ko.observableArray(params.buttons.map(b => new Button(b)));
this.buttonGroups = ko.pureComputed(() => {
const groups = [];
let prev = null, group = null;
this.buttons().forEach(b => {
if (b.active() !== prev) {
group = [];
groups.push(group);
prev = b.active();
}
group.push(b);
});
return groups;
});
}
const vm = new ButtonList({
buttons: [
{text: 'Mon', active: true},
{text: 'Tue', active: true},
{text: 'Wed', active: true},
{text: 'Tue', active: false},
{text: 'Fri', active: false},
{text: 'Sat', active: true},
{text: 'Sun', active: true}
]
});
ko.applyBindings(vm);
.btns {
display: flex;
}
.btn-group {
display: flex;
outline-offset: 2px;
}
.btn-group.active {
outline: 2px solid black;
}
.btn-group > * {
width: 50px;
padding: 5px;
margin: 0;
text-align: center;
}
.btn-group > .active {
background-color: black;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="btns" data-bind="foreach: buttonGroups">
<div class="btn-group" data-bind="foreach: $data, css: {active: $data[0].active}">
<div data-bind="click: toggle, text: text, css: {active: active}"></div>
</div>
</div>
我有一个显示为按钮的淘汰可观察项目数组:
<div class="btn-group" data-bind="foreach: myList">
<button data-bind="css: Sel == false ? 'btn btn-white' : 'btn btn-dark', click:$root.makeChange, text:$data.Id, attr:{'id':'h_'+$data.Id}"></button>
</div>
我需要为其添加轮廓 Sel
设置为 true
的项目。
我试过使用 outline: 2px solid black; outline-offset: 1px;
但它会在每个按钮周围添加轮廓,而不是为组添加轮廓,并且轮廓的右线绘制在下一个按钮后面。
我也尝试过使用边框,并用 JS 添加它们,但是我没有按钮和边框之间的 space。
outline
属性 感觉是解决这个问题的正确方法,但它只允许概述单个元素,并且只允许完整的轮廓。
这意味着活动元素必须包裹在一个容器中,并且该容器必须接收轮廓。
这可以通过计算可观察值来完成,该可观察值会变成一个平面列表:
[
{text: 'Mon', active: true},
{text: 'Tue', active: true},
{text: 'Wed', active: true},
{text: 'Tue', active: false},
{text: 'Fri', active: false},
{text: 'Sat', active: true},
{text: 'Sun', active: true}
]
进入嵌套:
[
[
{text: 'Mon', active: true},
{text: 'Tue', active: true},
{text: 'Wed', active: true}
],
[
{text: 'Tue', active: false},
{text: 'Fri', active: false},
],
[
{text: 'Sat', active: true},
{text: 'Sun', active: true}
]
]
取决于哪个项目是 active
。
以下是我将如何在淘汰赛中实现它。
- 一个
Button
视图模型,它跟踪自己的active
状态并允许切换它 - 包含按钮和动态计算的
buttonGroups
的ButtonList
视图模型。 - 基于此创建
.btn-group
和.btn-group.active
div 的视图。
下面的互动示例:
function Button(params) {
this.text = params.text;
this.active = ko.observable(params.active);
this.toggle = () => this.active(!this.active());
}
function ButtonList(params) {
this.buttons = ko.observableArray(params.buttons.map(b => new Button(b)));
this.buttonGroups = ko.pureComputed(() => {
const groups = [];
let prev = null, group = null;
this.buttons().forEach(b => {
if (b.active() !== prev) {
group = [];
groups.push(group);
prev = b.active();
}
group.push(b);
});
return groups;
});
}
const vm = new ButtonList({
buttons: [
{text: 'Mon', active: true},
{text: 'Tue', active: true},
{text: 'Wed', active: true},
{text: 'Tue', active: false},
{text: 'Fri', active: false},
{text: 'Sat', active: true},
{text: 'Sun', active: true}
]
});
ko.applyBindings(vm);
.btns {
display: flex;
}
.btn-group {
display: flex;
outline-offset: 2px;
}
.btn-group.active {
outline: 2px solid black;
}
.btn-group > * {
width: 50px;
padding: 5px;
margin: 0;
text-align: center;
}
.btn-group > .active {
background-color: black;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="btns" data-bind="foreach: buttonGroups">
<div class="btn-group" data-bind="foreach: $data, css: {active: $data[0].active}">
<div data-bind="click: toggle, text: text, css: {active: active}"></div>
</div>
</div>