Web组件:属性是否等同于attributeChangedCallback?

问题描述 投票:1回答:1

您不应该在HTML元素属性中放置丰富的数据(对象,数组,函数)。相反,它建议只在属性中放入丰富的数据(根据Google custom elements best practices article)。我需要在更新这些属性时运行操作。我们有observedAttributesattributeChangedCallback,但是没有类似的属性。

假设我有一个user道具,上面有nameDoBaddress。我以为我可以通过把一个双层塞特犬放到la来欺骗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};
})
javascript callback web-component object-properties
1个回答
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>

或者,您可以使用可与自定义元素交互的setter定义用户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>
© www.soinside.com 2019 - 2024. All rights reserved.