直接从事件处理程序中的目标元素访问敲除绑定值

Access knockout bound value directly from target element in event handler

本文关键字:访问 元素 绑定 目标 事件处理 程序      更新时间:2023-09-26

我在实现用鼠标悬停调用的自定义工具提示绑定时遇到了一些困难,所以我需要一个事件处理程序来显示工具提示。现在,工具提示的内容可以是静态字符串,可观察到的内容可以更改,但工具提示模块本身是一个单例。此外,页面上可以有多个工具提示元素,因此工具提示show函数只接收要显示的事件和内容。对我来说,最简单的方法是,如果我可以单独在侦听器中从事件目标访问实际绑定值

现在我知道有ko.dataFrom函数,但对于静态变量,我看不到任何地方的实际绑定值(即init函数中valueAccessor()返回的值),只有整个视图模型。

这里有一些简化的代码来说明它:

<span class="icon help" data-bind="tooltip: 'some static string'"></span>

(但正如我所说,在工具提示绑定背后也可能有一个可观察到的)

ko.bindingHandlers.tooltip = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        element.addEventListener("mouseover", ko.bindingHandlers.tooltip.showTooltip);
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            element.removeEventListener("mouseover", ko.bindingHandlers.tooltip.showTooltip);
        });
    },
    showTooltip: function(event) {
        var data = ko.dataFor(this);
        tooltip.show(event, data);
    }
}

现在的问题是,"数据"只包含视图绑定到的整个视图模型。但在哪里可以找到"一些静态字符串"?

我也尝试过使用"ko.contextFor",但$root、$data和$rawData都是一样的。我确信我在这里忽略了一些东西,或者如果不将字符串添加到数据属性或类似的东西中,这是不可能的,我希望避免这种情况。

这里的根本问题是,您不应该试图重用事件处理程序,或者至少,如果您要绑定它的话。

我只想把showTooltip移到init:

ko.bindingHandlers.tooltip = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var showTooltip = function(event) {
            tooltip.show(event, ko.unwrap(valueAccessor()));
        };
        element.addEventListener("mouseover", showTooltip);
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            element.removeEventListener("mouseover", showTooltip);
        });
    }
};

小函数非常便宜

实时示例(使用click而不是mouseover,并仅附加到文档中):

var tooltip = {
  show: function(event, value) {
    var div = document.createElement('div');
    div.innerHTML = "tooltip: " + value;
    document.body.appendChild(div);
  }
};
ko.bindingHandlers.tooltip = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var showTooltip = function(event) {
            tooltip.show(event, ko.unwrap(valueAccessor()));
        };
        element.addEventListener("click", showTooltip);
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            element.removeEventListener("click", showTooltip);
        });
    }
};
var vm = {
  items: [
    {text: "one", tooltip: "uno"},
    {text: "two", tooltip: "due"},
    {text: "three", tooltip: "tre"},
    {text: "four", tooltip: "quattro"}
  ]
};
ko.applyBindings(vm, document.body);
// To prove the observables work, update one after a delay
setTimeout(function() {
  vm.items[2].tooltip = "TRE";
}, 100);
<div data-bind="foreach: items">
  <div data-bind="text: text, tooltip: tooltip"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

或者,使用bind:

ko.bindingHandlers.tooltip = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var boundHandler = ko.bindingHandlers.tooltip.showTooltip.bind(
            null,
            valueAccessor
        );
        element.addEventListener("click", boundHandler);
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            element.removeEventListener("click", boundHandler);
        });
    },
    showTooltip: function(valueAccessor, event) {
        tooltip.show(event, ko.unwrap(valueAccessor()));
    }
};

var tooltip = {
  show: function(event, value) {
    var div = document.createElement('div');
    div.innerHTML = "tooltip: " + value;
    document.body.appendChild(div);
  }
};
ko.bindingHandlers.tooltip = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var boundHandler = ko.bindingHandlers.tooltip.showTooltip.bind(
            null,
            valueAccessor
        );
        element.addEventListener("click", boundHandler);
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            element.removeEventListener("click", boundHandler);
        });
    },
    showTooltip: function(valueAccessor, event) {
        tooltip.show(event, ko.unwrap(valueAccessor()));
    }
};
var vm = {
  items: [
    {text: "one", tooltip: "uno"},
    {text: "two", tooltip: "due"},
    {text: "three", tooltip: "tre"},
    {text: "four", tooltip: "quattro"}
  ]
};
ko.applyBindings(vm, document.body);
// To prove the observables work, update one after a delay
setTimeout(function() {
  vm.items[2].tooltip = "TRE";
}, 100);
<div data-bind="foreach: items">
  <div data-bind="text: text, tooltip: tooltip"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

请注意绑定值在事件参数前面的位置。