【问题标题】:2-way data binding in native web components本机 Web 组件中的 2 路数据绑定
【发布时间】:2014-11-10 14:05:20
【问题描述】:

我一直在阅读有关 Web 组件的内容,并且对新生规范非常感兴趣。有谁知道 DOM 中是否支持 2 路数据绑定,而不必使用 Polymer?一个例子将不胜感激。

【问题讨论】:

  • 你可以试试Slim.js。我不是一个大粉丝。我仍在寻找解决问题的好方法,同时避免使用任何库(我厌倦了一个接一个地学习 DSL)。到目前为止,我的方法是 init() 使用模板字符串和 update(),老式的,类似于 D3 图表。

标签: html web-component 2-way-object-databinding


【解决方案1】:

Object.observe 是一种在 javascript 中进行数据绑定的潜在新方法。此功能计划用于 Ecmascript 7(javascript),但目前一些浏览器支持它,请查看 here。另请查看关于 object.observe 的 html5rocks 文章

【讨论】:

  • Object.observe 已被弃用
  • 遗憾的是 Object.observe 已被弃用...不得不创建一个单独的对象(代理),虽然出于自身原因非常有用,但不是一回事,也不能提供所有相同的好处.尽管如此,似乎有充分的理由弃用它:infoq.com/news/2015/11/object-observe-withdrawn
【解决方案2】:

不,数据绑定不是 Web 组件规范的一部分。

您当然可以使用本机 JavaScript event listeners 和可能的 Proxy 对象自己实现数据绑定,但最好不要重新发明轮子:如果您想要数据绑定,请选择众多 JavaScript 中的一种支持这一点的框架。 Polymer、React、Angular 和 Vue 是此类库的一些最新示例。

【讨论】:

    【解决方案3】:

    过去几天我一直在玩这个。您可以创建一个 StateObserver 类,并从中扩展您的 Web 组件。一个最小的实现如下所示:

    // create a base class to handle state
    class StateObserver extends HTMLElement {
    	constructor () {
      	super()
        StateObserver.instances.push(this)
      }
    	stateUpdate (update) {
      	StateObserver.lastState = StateObserver.state
        StateObserver.state = update
        StateObserver.instances.forEach((i) => {
        	if (!i.onStateUpdate) return
        	i.onStateUpdate(update, StateObserver.lastState)
        })
      }
    }
    
    StateObserver.instances = []
    StateObserver.state = {}
    StateObserver.lastState = {}
    
    // create a web component which will react to state changes
    class CustomReactive extends StateObserver {
    	onStateUpdate (state, lastState) {
      	if (state.someProp === lastState.someProp) return
        this.innerHTML = `input is: ${state.someProp}`
      }
    }
    customElements.define('custom-reactive', CustomReactive)
    
    class CustomObserved extends StateObserver {
    	connectedCallback () {
      	this.querySelector('input').addEventListener('input', (e) => {
        	this.stateUpdate({ someProp: e.target.value })
        })
      }
    }
    customElements.define('custom-observed', CustomObserved)
    <custom-observed>
      <input>
    </custom-observed>
    <br />
    <custom-reactive></custom-reactive>

    fiddle here

    我喜欢这种方法,因为它直接发生在您想要与之通信的那些元素之间,无需通过 dom 遍历来查找 data- 属性或其他任何内容。

    【讨论】:

      【解决方案4】:

      一种方式:$0.model = {data}; $0 上的 setter 分配 $0.data,响应更新,另一种方式:$1.dispatchEvent(new CustomEvent('example', {detail: $1.data, cancelable: true, composed: true, bubbles: true}));$0.addEventListenever('example', handler) 提供 2 路数据绑定。数据对象是相同的,在 2 个元素上共享,事件和设置器允许响应更新。为了拦截对对象的更新,代理可以使用model = new Proxy(data, {set: function(data, key, value){ data[key] = value; ...respond... return true; }})other techniques。这解决了简单的场景。你也可以考虑查看和阅读 Redux 的源代码,它提供了看起来比较流行的约定。正如 Ajedi32 提到的那样,为更复杂的场景重新发明轮子并不是那么实际,除非它是一种学术兴趣。

      【讨论】:

        猜你喜欢
        • 2019-03-26
        • 2017-06-05
        • 1970-01-01
        • 2020-01-25
        • 1970-01-01
        • 2018-01-11
        • 1970-01-01
        • 2017-11-05
        • 1970-01-01
        相关资源
        最近更新 更多