我想使用 Knockout.js If
绑定(bind)但包含动画。我使用单个 View 模型容器来允许将大量单独的 View 加载到同一容器中。如果我在"template"上使用 visibility
绑定(bind),则绑定(bind)将被隐藏,并且所有绑定(bind)都会抛出错误,因为它们的 View 模型当前未加载。我担心如果所有内容都加载完毕,这些 View 模型将开始减慢页面速度。
来自 knockout If
文档:
The if binding, however, physically adds or removes the contained markup in your DOM, and only applies bindings to descendants if the expression is true.
knockout 动画过渡文档使用 jQuery 的显示/隐藏函数创建自定义绑定(bind)。但是,这些也会隐藏/显示 DOM 元素。
简而言之,我正在尝试学习两件事之一。
在 jQuery 中删除/添加 DOM 元素以便可以在自定义绑定(bind)中使用的适当方法是什么?
或者
knockout 中的 if
绑定(bind)如何工作,以便我可以对其进行逆向工程?
澄清编辑:
进一步阐明代码的设置方式。提出此问题的网站的管理部分将包含一个编辑所有标准内容页面以及访问业务报告的位置。
Html"template"就这样存储(需要明确的是,这些不是 knockout 模板,而是包含数据绑定(bind)的 html 文件。这可以通过令人信服的理由进行更改。)
Admin
Page Edit
User Edit
etc
Reports
Product
User
etc
我们的 JavaScript 与此类似
BaseViewModel.js:
Content view model
AdminEditViewModels.js:
UserEditViewModel
ContentEditViewModel
[1 view model per item]
AdminReportsViewModels.js
[similar to above]
单击链接时,主页内容 View 模型将加载到基本 View 模型中,并通过激发此问题的绑定(bind)使其可见。然后每个 View 模型都有自己的 Load 来触发 ajax 调用。
self.ViewOrders = function () {
self.Content("Orders");
self.ContentVM(new AdminOrdersViewModel());
self.ContentVM().Load();
}
目前只有大约 9 个不同的"template",我们已尽最大努力对它们进行标准化,但它们很可能会增长。绑定(bind)只会阻止每个"template"向控制台抛出错误。
最佳答案
使用您提到的 fadeIn/fadeOut 示例,我尝试创建一个对元素执行淡入淡出的绑定(bind),然后通过将该内容包装在新的 div 中来初始化元素内部内容的“if”绑定(bind)。然后,if 绑定(bind)会传递一个新的可观察属性,该属性使用 jQuery 的 fade 函数的回调进行设置。它感觉有点老套,并且可能不适用于过于复杂的场景,但也许您或 SO 社区可以对其进行改进。
var viewModel = function(){
var self = this;
self.showContent = ko.observable(false);
self.content = ko.observable("content goes here");
}
//Uses the IF binding to remove the element's content from the DOM, but also fades before/after.
ko.bindingHandlers.fadedIf = {
init: function (element, valueAccessor, allBindingsAccessor, data, bindingContext) {
// Initially set the element to be instantly visible/hidden depending on the value
var value = valueAccessor();
//If the value is a normal function make it a computed so that it updates properly
if (!ko.isObservable(value)) {
value = ko.computed({ read: valueAccessor });
}
//attach our observable property to the accessor so that it can be used in the update function
valueAccessor.domShown = ko.observable(ko.unwrap(value));
//Wrap any contents of the element in a new div, and then bind that div using the "if" binding.
//This way the element and its event hooks for fading in/out never leaves the dom, but all content does.
//it also prevents applying multiple bindings to the same element.
var contentWrapper = $(element).children().wrapAll(document.createElement("div")).parent()[0];
ko.applyBindingAccessorsToNode(contentWrapper, { 'if': function () { return valueAccessor.domShown } }, bindingContext);
},
update: function (element, valueAccessor) {
// Whenever the value subsequently changes, slowly fade the element in or out
var value = valueAccessor();
if (ko.unwrap(value)) {
valueAccessor.domShown(true); //restore the element to the DOM
$(element).fadeIn();
} else {
$(element).fadeOut({
complete: function () {
valueAccessor.domShown(false); //remove the element from the DOM
}
});
}
}
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="border: 1px solid blue; width:600px; margin:auto; padding: 32px; text-align:center;">
Show Content<input type="checkbox" data-bind="checked: showContent">
<br/>
<div data-bind="fadedIf: showContent">
<div style="background-color: silver; padding: 20px;">
<h3 data-bind="text: content"></h3>
</div>
</div>
</div>
关于javascript - 如何为 Knockout.js 的 If 绑定(bind)添加动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43352138/