Access class function in Web Component from inline Element

女生的网名这么多〃 提交于 2020-01-24 12:54:08

问题


I want to execute a defined class function from an Element inside my Web Component:

customElements.define('first-component', class FirstComponent extends HTMLElement {
    constructor() {
        super();
     }

     log() {
        console.log('Well Done!')
     }

     connectedCallback() {
        this.innerHTML = '<button onclick="log()">Do it</button>'
     }
});

State right now: ReferenceError: log is not defined


回答1:


With parentElement, or closest()

In order to call the log() method of the custom element, you'll have to get a reference on it.

In your example, the custom element is the parent element of the <button> element, so you should call the parentElement property of the button as already stated by @Smankusors:

<button onclick="this.parentElement.log()>Do it</button>

With getRootNode()

Alternately, in a more complex DOM tree, and if a Shadow DOM is used, you can use getRootNode() combined with host to get the custom element reference.

customElements.define('first-component', class FirstComponent extends HTMLElement {
     log() {
        console.log('Well Done!')
     }

     connectedCallback() {
        this.attachShadow({mode: 'open'})
            .innerHTML = '<button onclick="this.getRootNode().host.log()">Do it</button>'
     }
})
<first-component></first-component>

With a unique identifier

You can also call the custom element by its id property (if it has one) :

customElements.define('first-component', class FirstComponent extends HTMLElement {
     log() {
        console.log('Well Done!')
     }

     connectedCallback() {
        if (!this.id)
            this.id = "_id"
        this.innerHTML = `<button onclick="${this.id}.log()">Do it</button>`
     }
})
<first-component></first-component>

With handleEvent()

For security reasons, you can avoid inline script and implement the handleEvent() method, then call inside it a specific method depending on some criterions :

customElements.define('first-component', class FirstComponent extends HTMLElement {
    log() {
        console.log('Well Done!')
    }
     
    handleEvent(ev) {
        if (ev.target.innerText == 'Do it')
            this.log()
    }

    connectedCallback() {
        this.innerHTML = '<button>Do it</button>'
        this.addEventListener('click', this)
    }
})
<first-component></first-component>



回答2:


That shouldn't be log(), but this.log(), because that log function scope is only that element, not in window scope, so your code should be

customElements.define('first-component', class FirstComponent extends HTMLElement {
    constructor() {
        super();
     }

     log() {
        console.log('Well Done!')
     }

     connectedCallback()
        this.innerHTML = '<button onclick="this.parentElement.log()">Do it</button>'
     }
});

-- EDIT -- Sorry, my mistake, I just saw that you added button inside custom element, well... It should be this.parentElement.log() if you still want to prefer inline




回答3:


Since the DOM and its elements does not have any knowledge of the scope it lives in, just setting the value of the innerHTML won't work since log does not exist on window which is the DOM scope. Hence this, it's best practice to create the element and append it to the Shadow Dom of the custom element and at the same time add the eventListener to the button.

customElements.define('first-component', class FirstComponent extends HTMLElement {
    constructor() {
        super();
     }

     log() {
        console.log('Well Done!')
     }

     connectedCallback() { // This parentheses was also missing
         var shadow = this.attachShadow({mode: 'open'});
         const button = document.createElement("button");
         button.textContent = 'Do it!';
         button.addEventListener('click', () => this.log());
         shadow.appendChild(button);
     }
});
<first-component id="component"></first-component>



回答4:


You should - for many reasons - stop using inline event listeners. Instead, use addEventListener - in this case in the connectedCallback.

customElements.define('first-element', class FirstElement extends HTMLElement {
    constructor() {
        super();
     }

     log() {
        console.log('Well Done!')
     }

     connectedCallback() {
        const btn = document.createElement('button');
        btn.textContent = 'Do it!';
        btn.type = 'button'; // otherwise it's type=submit
        btn.addEventListener('click', this.log);
        this.appendChild(btn);
     }
});
<first-element></first-element>


来源:https://stackoverflow.com/questions/53963583/access-class-function-in-web-component-from-inline-element

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!