问题
I am trying to pass data attribute in custom element as an object but while receiving inside attachedCallback method getting value "[object object]" in a string form.
So can anyone help me to figure out what is the work around to get the attributes as an object inside custom-element(web component).
code sample
<script>
class myElements extends HTMLElement {
createdCallback() {
this.innerHTML = `<h1>Hello</h1>`;
}
attachedCallback() {
console.log(this.getAttribute('data'));
}
}
document.registerElement('my-element', myElements);
</script>
custom element tag
<script>
var object = { key1: 111, key2: 222, key3: function(){return "hi"}, key4:[1,2,3]};
function changeHandler() {
page('/default', function() {
// some logic to decide which route to redirect to
if (admin) {
page.redirect('/admin');
} else {
page.redirect('/guest');
}
});
}
</script>
<my-element data="object" onchange="changeHandler"></my-element>
Note: suppose that <my-element>
is a dropdown which gives user option to choose some value.
Solution: Still no native solution in custom-element specs(v0 and v1).
Since Custom Elements doesn't support data binding so we need a sugaring layer for that (e.g., Polymer or SkateJS) as mention by @tony in the comment.
回答1:
Try by converting object to JSON string,
var object = { key1: 111, key2: 222};
JSON.stringify(object);
Then when you want to get the value, parse it back to object
JSON.parse(this.getAttribute('data'));
回答2:
Custom Elements does not modify the standard HTML element attribute behaviour which is always of type string
.
Because of that, you shoud instead either:
Send a
change
Event from your custom element that will trigger theonchange
handler.Register you object/function callback via a custom element method.
Modify a state attribute that will be observed (with
Mutation Observer
) by its container.
If you want to use attribute anyways you can always use eval()
.
Example with solution 1 with call to changeHandler()
:
//define custom element
class DropDown extends HTMLElement
{
connectedCallback ()
{
var span = this.querySelector( 'span' )
//define ul list
var ul = this.querySelector( 'ul' )
ul.onclick = ev => {
if ( this.value != ev.target.textContent )
{
this.value = ev.target.textContent
this.setAttribute( 'value', this.value )
span.textContent = this.value
this.dispatchEvent( new CustomEvent( 'change' ) )
}
}
//show or hide
this.onclick = ev => ul.classList.toggle( 'show' )
}
}
customElements.define( 'drop-down', DropDown )
drop-down {
position: relative ;
cursor: pointer ;
display: inline-block ;
}
drop-down > span {
border: 1px solid #aae ;
padding: 2px 5px ;
}
drop-down > ul {
position: absolute ;
top: 4px ; left: 5px ;
list-style: none ;
outline: 1px solid #aae ;
padding: 0 ;
display: inline-block ;
opacity: 0 ;
transition: all 0.3s ease-out ;
background: white ;
visibility: hidden ;
z-index: 10 ;
}
drop-down > ul.show {
opacity: 1 ;
visibility: visible ;
}
drop-down > ul > li {
padding: 2px 5px ;
}
drop-down > ul > li:hover {
background: lightgoldenrodyellow ;
}
<drop-down onchange="changeHandler()">
<span>select value</span>
<ul>
<li>Chrome</li>
<li>Firefox</li>
<li>Opera</li>
<li>Safari</li>
</ul>
</drop-down>
<script>
function changeHandler ()
{
console.log( 'changeHandler()', event.target.value )
}
</script>
来源:https://stackoverflow.com/questions/41216860/why-custom-elements-not-support-attributes-as-an-object