我正在尝试为输入元素创建一个本机 Web 组件。我希望该组件具有自定义验证功能,类似于聚合物的纸张输入自定义验证器功能。我不确定是否可以将自定义验证器函数作为属性传递给(Web 组件)输入元素的实例。任何建议,将不胜感激。
3 回答
属性是字符串,而不是函数。您可以将 aa 函数作为字符串传递,然后使用该函数对其进行评估eval()
。出于安全原因,这不被认为是一种好的做法。
另一种解决方案是将其作为 Javascript 属性传递给自定义元素:
function validate( value ) { return Number.isInteger( value) }
myCustomElement.validation = validate
或者,使用箭头函数:
myCustomElement.validation = v => Number.isInteger( va )
class CustomInput extends HTMLElement {
constructor() {
super()
var sh = this.attachShadow( { mode: 'open' } )
sh.appendChild( tpl.content.cloneNode( true ) )
var div = sh.querySelector( 'div' )
div.addEventListener( 'input', () => {
if ( !this.validate( Number( div.textContent ) ) )
div.classList.add( 'error' )
else
div.classList.remove( 'error' )
} )
}
}
customElements.define( 'custom-input', CustomInput )
integer.validate = v => Number.isInteger( v )
<template id="tpl">
<style>
:host {
display: inline-block ;
min-width: 150px ;
border: 1px solid cyan ;
}
div.error {
color: red ;
}
</style>
<div contenteditable></div>
</template>
<custom-input id="integer"></custom-input>
最好通过属性传入函数,因为所有属性都是字符串。
如果必须将其作为属性传递,则需要将该字符串转换为函数。然后问题成为该功能的范围。
如果您假设该函数在范围内是全局的,那么您可以使用该字符串作为window
对象的属性名称。要执行代码,您可以这样做:
window[fnName]();
但这是非常有限的,因为您可能想要调用自己的类或对象的成员函数。
您可以在名称中使用点符号,func="myObj.fnName()"
如果您不担心使用警告,eval
您可以执行以下操作:
eval(el.getAttribute('func'));
当然,这会让您对各种可能的注入攻击持开放态度。但是,img
标签和script
标签也是如此。
您可以尝试更安全并执行以下操作:
设置不带()
:
`func="myObj.fnName"`
您尝试拨打电话的代码如下所示:
var parts = el.getAttribute('func').split('.');
var obj = window;
var found = parts.some( part => {
var next = obj[part];
if (next) {
obj = next;
return true;
}
});
if (found) {
obj();
}
但这也会阻止您传入任何参数。
这种复杂性正是 AngularJS、React、Vue 等存在的原因。这也是我避免通过属性传入函数的原因。
如果您通过属性传递它,那么您的代码可能如下所示:
el.callme = globalfunc; // or
el.callme = this.localFunc; // or
el.callMe = (some params) => { /* do something */ };
或者你想要的任何其他东西。
活动
现在说了所有这些,我还建议做大多数本机组件所做的事情。那就是在需要做某事时,或者当某事发生变化而外界可能对这些变化感兴趣时调度一个事件。
在你的元素中,你只需调用
this.dispatchEvent(new CustomEvent('event name', {bubbles: true, detail: {your detail}});
然后任何关心您的活动的人都会倾听它。
只需将其传递给构造函数即可。 您的自定义元素声明:
class CustomInput extends HTMLElement {
constructor(validator) {
super()
this.validate = validator
}
/* Your Custom Input Methods */
}
然后通过new
运算符而不是document.createElement
.
实例化:
const customInputEl = new CustomInput((inputString) => {
// your validation code
})
如果你想将一个函数传递给组件,那一定意味着你无论如何都要通过 javascript 实例化它。