我可以将函数作为属性传递给Web组件吗?

时间:2018-06-14 20:40:29

标签: web-component custom-element native-web-component

我正在尝试为input元素创建本机Web组件。我希望该组件具有自定义验证功能,类似于聚合物的纸张输入自定义验证器功能。我不确定我是否可以将自定义验证器函数作为属性传递给(web组件)输入元素的实例。任何建议,将不胜感激。

3 个答案:

答案 0 :(得分:3)

属性是字符串,而不是函数。您可以将函数作为字符串传递,然后使用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>

答案 1 :(得分:2)

最好通过属性传递函数,因为所有属性都是字符串。

如果必须将其作为属性传递,则需要将该字符串转换为函数。然后问题就变成了这个功能的范围。

如果您假设该函数在范围内是全局的,那么您可以将该字符串用作window对象的属性名称。要执行代码,您可以执行此操作:

window[fnName]();

但这是非常有限的,因为你可能想要调用你自己的类或对象的成员函数。

您可以在名称func="myObj.fnName()"中使用点符号,如果您不担心使用eval的警告,您可以执行以下操作:

的eval(el.getAttribute(&#39; FUNC&#39;));

当然,让你开放各种可能的注射攻击。但是,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}});

然后任何关心你事件的人都会听。

答案 2 :(得分:0)

只需将其传递给构造函数即可。 您的自定义元素声明:

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实例化它。