首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Web :属性是否与attributeChangedCallback等效?

Web :属性是否与attributeChangedCallback等效?
EN

Stack Overflow用户
提问于 2019-05-01 07:14:27
回答 1查看 1.2K关注 0票数 1

不应该将丰富的数据(对象、数组、函数)放在HTML元素属性中。相反,建议只将丰富的数据放在属性中(根据Google自定义元素最佳实践文章)。我需要在更新这些属性时运行操作。我们有observedAttributesattributeChangedCallback,但是在属性方面没有类似的地方。

假设我有一个user道具,上面有nameDoBaddress之类的东西。我想我也许可以通过把一个双层建筑设计成洛杉矶来戏弄observedAttributes

代码语言:javascript
复制
set user(val) {
  return;
}

没起作用。return this.user = val给出了一个无限循环。

此时,我唯一的想法是拥有一个名为_user的属性,该属性在每次更改时简单地设置为[Object object],这将触发我真正想要的更改。不过,我不喜欢这样。

更新:这就是我目前正在做的事情

user-info.js

代码语言:javascript
复制
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

代码语言:javascript
复制
document.querySelector('.actions--user').addEventListener('input', e => {
  state.user = {...state.user, [e.target.dataset.action]: e.target.value};
})
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-01 13:53:39

可以使用代理检测对象的更新属性。

代码语言:javascript
复制
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>`
  }
} )
代码语言:javascript
复制
<user-info id=ui></user-info><br>
<label>Name: <input oninput="ui.user.name=this.value"></label>

或者,您可以使用与自定义元素交互的设置器定义用户object / class

代码语言:javascript
复制
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 )
代码语言:javascript
复制
<user-info id=ui></user-info><br>
<label>Name: <input oninput="ui.user.name=this.value"></label>

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55932792

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档