您不应在HTML元素属性中放置丰富的数据(对象,数组,函数)。相反,建议仅将丰富的数据放入属性中(根据Google custom elements best practices article)。这些属性更新后,我需要运行操作。我们有observedAttributes
和attributeChangedCallback
,但属性没有相似之处。
假设我有一个user
道具,上面有name
,DoB
和address
之类的道具。我以为我可以通过放置双层塞子 ala
observedAttributes
set user(val) {
return;
}
没用。 return this.user = val
产生无限循环。
这时我唯一的想法是拥有一个名为_user
的属性,该属性在每次更改时都被简单地设置为[Object object]
,从而触发了我真正想要的更改。不过不是很喜欢。
更新:这是我目前正在做的
在user-info.js
中:
class UserInfo extends HTMLElement {
connectedCallback() {
subscribers.push({ element: this, props: ['user'] });
this._user = state.user;
this.render();
}
static get observedAttributes() {
return ['user'];
}
attributeChangedCallback(name, oldValue, newValue) {
this.render();
}
get user() {
return this._user;
}
set user(val) {
if (JSON.stringify(val) !== JSON.stringify(this._user)) {
this._user = val;
return this.setAttribute('user', val);
}
}
render() {
this.innerHTML = `<span>${this._user.name}</span> was born on <span>${this._user.dob}</span>`;
}
}
在main.js
中:
document.querySelector('.actions--user').addEventListener('input', e => {
state.user = {...state.user, [e.target.dataset.action]: e.target.value};
})
答案 0 :(得分:2)
您可以使用Proxy来检测对象的更新属性。
customElements.define( 'user-info', class extends HTMLElement {
connectedCallback() {
this._user = {
name: 'Bruno',
dob: '1/1/2000'
}
this.render();
this._proxy = new Proxy( this._user, {
set: ( obj, prop, val ) => {
if ( prop === 'name' )
if ( this._user.name !== val ) {
console.log( 'username updated to ' + val )
this._user.name = val
this.render()
}
}
} )
}
get user() {
return this._proxy
}
set user(val) {
if (JSON.stringify(val) !== JSON.stringify(this._user)) {
this._user = val
this.render()
}
}
render() {
this.innerHTML = `<span>${this._user.name}</span> was born on <span>${this._user.dob}</span>`
}
} )
<user-info id=ui></user-info><br>
<label>Name: <input oninput="ui.user.name=this.value"></label>
或者,您可以定义用户object / class
,其设置员将与自定义元素进行交互。
class User {
constructor( elem ) {
this._elem = elem
this._name = 'Bruno'
this._dob = '1/1/2000'
}
set name( val ) {
if ( val !== this._name ) {
this._name = val
this._elem.render()
}
return false
}
get name() {
return this._name
}
get dob() {
return this._dob
}
update( obj ) {
this._name = obj.name
this._dob = obj.dob
}
}
class UserInfo extends HTMLElement {
connectedCallback() {
this._user = new User( this )
this.render()
}
get user() {
return this._user
}
set user(val) {
this._user.update( val )
this.render()
}
render() {
this.innerHTML = `<span>${this._user.name}</span> was born on <span>${this._user.dob}</span>`
}
}
customElements.define( 'user-info', UserInfo )
<user-info id=ui></user-info><br>
<label>Name: <input oninput="ui.user.name=this.value"></label>