组件的多个实例

现在,我们利用写好的 LabeledSlider 组件来重构我们的 BMI 小程序:

查看示例

出现 bug 了,我们拖动任意一个滑块,都会引起另一个滑块的变化,这显然就表明了两个滑块实例出现了 冲突。原因不难找到,在滑块组件的 Intent 中,我们把 css class 为 .slider 的滑块全部进行了事件绑定:

function intent(DOMSource) {
  const change$ = DOMSource.select('.slider').events('input').map(evt => evt.target.value);
  return change$;
}

对此,我们首先能够想到的解决思路是,在组件实例化时,为不同的实例进行不同的标识,比如指定不同的 css class。并且,在组件实例化时,传入绑定了该 class 对应事件的 DOM source:

function main(sources) {
  const weightProps$ = Rx.Observable.of({
    label: 'Weight',
    unit: 'kg',
    min: 40,
    max: 150,
    init: 70
  });

  const weightSinks = LabeledSlider({
    DOM: sources.DOM.select('.weight'),
    props: weightProps$
  });

  const weightVTree$ = weightSinks.DOM.map(vtree => {
    vtree.properties.className += ' weight';
    return vtree;
  });

  const heightProps$ = Rx.Observable.of({
    label: 'Height',
    unit: 'cm',
    min: 140,
    max: 220,
    init: 170
  });

  const heightSinks = LabeledSlider({
    DOM: sources.DOM.select('.height'),
    props: heightProps$
  });

  const heightVTree$ = heightSinks.DOM.map(vtree => {
    vtree.properties.className += ' height';
    return vtree;
  });

  const vtree$ = Rx.Observable.combineLatest(
    weightSinks.DOM, heightSinks.DOM,
    (weightVTree, heightVTree) => {
      return div([
        weightVTree,
        heightVTree
      ]);
    }
  );

  return {
    DOM: vtree$
  };
}

别忘了在 Intent 和组件的绑定位置解耦:

function intent(DOMSource) {
  const change$ = DOMSource.events('input').map(evt => evt.target.value);
  return change$;
}

现在,bug 就修复了:

查看示例

results matching ""

    No results matching ""