HTMLInputElement.value 的设置器

Rem*_*iak 2 javascript getter-setter

我想使用自定义设置器订阅所有输入中属性的所有更改value

Object.defineProperty(HTMLInputElement.prototype, 'value', {
    set: function(newValue) {
       // do some logic here

       // WHAT PUT HERE to call "super setter"?
    }
});
Run Code Online (Sandbox Code Playgroud)

如果我使用this.value = newValue;我得到的结果Maximum call stack size exceeded是相当正确的,但是......

没关系。我应该怎样称呼才能以value正确的方式改变?这里是 JSFIDDLE有更详细的解释。

小智 8

是的,这可以使用 JavaScript 来实现:

\n
(function (realHTMLInputElement) {\n    Object.defineProperty(HTMLInputElement.prototype, \'value\', {\n        set: function (value) {\n            // Do some logic here\n            return realHTMLInputElement.set.call(this, value);\n        },\n    });\n}(Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, \'value\')));\n
Run Code Online (Sandbox Code Playgroud)\n

我们使用 IIFE 传入 for 的原始定义value,然后从新定义中调用原始 set 函数。

\n

如果将其与,\xc2\xb9input上的捕获事件处理程序结合起来document,您将收到所有更改的通知,无论是通过代码(通过上述内容)还是由用户。

\n

\r\n
\r\n
(function (realHTMLInputElement) {\n    Object.defineProperty(HTMLInputElement.prototype, \'value\', {\n        set: function (value) {\n            // Do some logic here\n            return realHTMLInputElement.set.call(this, value);\n        },\n    });\n}(Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, \'value\')));\n
Run Code Online (Sandbox Code Playgroud)\r\n
function yourCustomLogic(input, value) {\n    console.log(`${input.id ? "Input #" + input.id : "An input"} set to "${value}"`);\n}\n\n// Catch programmatic changes\n(function (realHTMLInputElement) {\n    Object.defineProperty(HTMLInputElement.prototype, "value", {\n        set: function (value) {\n            // Do some logic here\n            yourCustomLogic(this, value);\n            return realHTMLInputElement.set.call(this, value);\n        },\n    });\n})(Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value"));\n\n// Catch end-user changes\ndocument.addEventListener(\n    "input",\n    (event) => {\n        if (event.target.tagName === "INPUT") {\n            yourCustomLogic(event.target, event.target.value);\n        }\n    },\n    true  // Capture handler\n);\n\ndocument.getElementById("example").value = "Updated by code.";
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

使用捕获阶段处理程序(而不是冒泡阶段)的原因有两个:

\n
    \n
  1. 官方地说,input它不会冒泡,尽管大多数(全部?)当前的浏览器都会冒泡,无论规范如何规定

    \n
  2. \n
  3. 它可以防止停止传播的事件处理程序在事件到达之前停止该事件。document

    \n
  4. \n
\n