gpt4 book ai didi

javascript - 分配计算属性时,hasfocus 绑定(bind)不起作用

转载 作者:行者123 更新时间:2023-11-29 20:57:30 24 4
gpt4 key购买 nike

我有一个使用 Knockout 构建的可编辑网格,它遵循讨论的网格线 here .

我希望为 hasfocus 分配一个计算的可观察对象(与在上面的链接帖子中所做的相反,其中 hasfocus 绑定(bind)被分配了相同的observable as visible), 但它不起作用 - 编辑的元素没有被聚焦。

这是我的代码(这是一个 fiddle ):

$(document).ready(function() {
var viewModel = new Grid.ViewModel();
viewModel.init();
ko.applyBindings(viewModel);
});

ko.bindingHandlers.clickToEdit = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
if (element.className == "editable") {
var observable = valueAccessor();
span = document.createElement("span");
var input = document.createElement("input");

element.appendChild(span);
element.appendChild(input);

ko.applyBindingsToNode(span, {
text: observable,
visible: ko.computed(function() { return !viewModel.isEditState(); }),
});

ko.applyBindingsToNode(input, {
value: observable,
visible: viewModel.isEditState,
hasfocus: viewModel.shouldFocus, // this seems to not work (but it works if we assign it with isEditState)
});
}
},
}

var Grid = {
RowViewModel: function() {
var self = this;
self.district = ko.observable();
self.team = ko.observable();
self.factory = ko.observable();
self.isEditState = ko.observable(false);
self.shouldFocus = ko.computed(function() {
return self.isEditState();
});

self.init = function (data) {
self.district(data.District);
self.team(data.Team);
self.factory(data.Factory);
}

self.setEditState = function(){
self.isEditState(!self.isEditState());
}
},

ViewModel: function() {
var self = this;
self.data = ko.observableArray();
self.init = function() {
var data = self.getData();
self.data(data);
}
self.getData = function() {
var data = [];
var rows = [
{ District: "North", Team: "Jim", Factory: "Mars" },
{ District: "South", Team: "John", Factory: "Pluto" },
];
rows.forEach(function (element, index) {
var row = new Grid.RowViewModel();
row.init(element);
data.push(row);
});

return data;
}
},
}
td, tr > th {
text-align: center;
vertical-align: middle;
}

a {
text-decoration: none !important;
}

input {
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>


<div class="grid-container">
<table class="table table-bordered table-condensed" style="table-layout:fixed">
<thead>
<tr class="active">
<th></th>
<th>District</th>
<th>Team</th>
<th>Factory</th>
<th>Action</th>
</tr>
</thead>
<tbody data-bind="foreach: data">
<tr>
<td>
<input type="checkbox" />
</td>
<td data-bind="text: district, clickToEdit: district"></td>
<td class="editable" data-bind="clickToEdit: team"></td>
<td data-bind="text: factory, clickToEdit: factory"></td>
<td>
<a href="#" data-bind="visible: !isEditState(), click: setEditState">
<i class="glyphicon glyphicon-pencil"></i>
</a>
<a href="#" data-bind="visible: isEditState(), click: setEditState">
<i class="glyphicon glyphicon-ok"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>

兴趣线是:

self.shouldFocus = ko.computed(function() {
return self.isEditState();
});

注意:虽然我在这里只使用了 self.isEditState(),但实际上我会使用一两个以上的表达式,因此需要使用一个 computed .

最佳答案

在我提出解决方案之前,我想向您展示一个 minimal, complete, and verifiable example的问题。请注意查看正在发生的事情有多容易?

const vm = {};

vm.visible = ko.observable(false);
vm.hasFocus = ko.computed(vm.visible);
vm.toggle = () => vm.visible(!vm.visible());

ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<input data-bind="visible: visible, hasFocus: hasFocus">
<button data-bind="click: toggle">toggle</button>

从这个重建中我想:问题可能是 visiblehasFocus 更新被同时处理,没有给 DOM 足够的时间来处理这两个?毕竟,浏览器无法将焦点添加到隐藏元素...

让我们尝试使 hasFocus 计算 deferred。延迟计算在事件循环结束时运行,有点像 setImmediate(cb)或者 setTimeout(cb, 0) 会。

const vm = {};

vm.visible = ko.observable(false);
vm.hasFocus = ko.computed(vm.visible)
.extend({ deferred: true });
vm.toggle = () => vm.visible(!vm.visible());

ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<input data-bind="visible: visible, hasFocus: hasFocus">
<button data-bind="click: toggle">toggle</button>

成功!现在,knockout 会更新输入的可见性,为 DOM 提供更新时间,仅在那时添加焦点。

关于javascript - 分配计算属性时,hasfocus 绑定(bind)不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48533502/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com