更灵活的 DOM driver
目前,DOM driver 接收的 sink 是一个发出字符串的 Observable:
function DOMDriver(text$) {
text$.subscribe(text => {
$app = document.querySelector('#app');
$app.textContent = text;
});
const DOMSource = Rx.Observable.fromEvent(document, 'click');
return DOMSource;
}
为了让它更加灵活,它接收的应当是一个能发出 DOM Element 对象的 Observable,假定 main()
发出的 Observable 为:
function main(sources) {
const click$ = sources.DOM;
return {
DOM: click$
.startWith(null)
.flatMapLatest(() =>
Rx.Observable.timer(0, 1000)
.map(i => ({
tagName: 'H1',
children: [{
tagName: 'SPAN',
children: [
`Seconds elapsed ${i}`
]
}]
}))
),
Log: Rx.Observable.timer(0, 2000)
.map(i => 2 * i)
};
}
我们让 DOM driver 能够递归的创建 DOM Element:
function DOMDriver(obj$) {
function createElement(obj) {
const element = document.createElement(obj.tagName);
obj.children
.filter(c => typeof c === 'object')
.map(createElement)
.forEach(e => element.appendChild(e));
obj.children
.filter(c => typeof c === 'string')
.forEach(str => element.innerHTML=str);
return element;
}
obj$.subscribe(obj => {
const container = document.querySelector('#app');
container.innerHTML = '';
const element = createElement(obj);
container.appendChild(element);
});
const DOMSource = Rx.Observable.fromEvent(document, 'click');
return DOMSource;
}