CycleDOM
我们看下我们写好的 DOM driver:
function DOMDriver(obj$) {
function createElement(obj) {
// ...
}
obj$.subscribe(obj => {
const container = document.querySelector('#app');
container.innerHTML = '';
const element = createElement(obj);
container.appendChild(element);
});
const DOMSource = {
selectEvents: function (tagName, eventType) {
return Rx.Observable.fromEvent(document, eventType)
.filter(evt => evt.target.tagName === tagName.toUpperCase())
}
};
return DOMSource;
}
呃,暂时,它只能算是一个小玩具:
- 它硬编码了容器对象:
const container = document.querySelector('#app');
这使得我们 HTML 中的容器变化时,需要修改代码内部。
- 它性能不好:
container.innerHTML = '';
const element = createElement(obj);
container.appendChild(element);
每次 sink 变化,我们都会清空、然后重新渲染 container
的内容。
- 它提供的
selectEvents
方法不够强大:
selectEvents: function (tagName, eventType) {
return Rx.Observable.fromEvent(document, eventType)
.filter(evt => evt.target.tagName === tagName.toUpperCase())
}
我们只能使用 HTML 标签来选择 DOM,而不能像 querySelector(selector)
那样通过元素 id 或者 class 来选择 DOM。
在实际环境中,我们可以使用 Cycle.js 官方提供的 DOM driver 来替换目前写好的、但是很弱逼的 DOM driver:
<script src="https://rawgit.com/cyclejs/cycle-core/v6.0.0/dist/cycle.js"></script>
const {h, h1, span, makeDOMDriver} = CycleDOM;
function main(sources) {
const hover$ = sources.DOM.select('span').events('mouseover');
return {
DOM: hover$
.startWith(null)
.flatMapLatest(() =>
Rx.Observable.timer(0, 1000)
.map(i => h1({style: {background: 'red'}}, [span([`Seconds Elapsed ${i}`])]))
),
Log: Rx.Observable.timer(0, 2000)
.map(i => 2 * i)
};
}
function consoleLogDriver(msg$) {
msg$.subscribe(msg => {
console.log(msg);
});
}
const drivers = {
DOM: makeDOMDriver('#app'),
Log: consoleLogDriver
};
Cycle.run(main, drivers);