Input要素のネイティブWebコンポーネントを作成しようとしています。コンポーネントに、ポリマーの紙入力カスタムバリデーター機能と同様のカスタム検証機能を持たせたかったのです。 (Webコンポーネント)入力要素のインスタンスに属性としてカスタムバリデーター関数を渡すことができるかどうかわかりません。任意の提案をいただければ幸いです。
属性は文字列であり、関数ではありません。関数を文字列として渡してから、eval()
関数を使用してevaluateすることができます。セキュリティ上の理由から、これはグッドプラクティスとは見なされません。
別の解決策は、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 */
}
次に、document.createElement
の代わりにnew
演算子を使用してコンポーネントをインスタンス化します。
インスタンス化:
const customInputEl = new CustomInput((inputString) => {
// your validation code
})
関数をコンポーネントに渡したい場合は、とにかくjavascriptを介して関数をインスタンス化することを意味する必要があります。