[Cycle.js] Fine-grained control over the DOM Source
Currently in our main() function, we get click$ event.
function main(sources) { const click$ = sources.DOM; const sinks = { DOM: click$ .startWith(null) .flatMapLatest(() => Rx.Observable.timer(0, 1000) //describe what element should exist .map(i => { return { tagName: 'h1', children: [ { tagName: 'span', children: [ `time esplsed: ${i}` ] } ] } }) ), Log: Rx.Observable.timer(0, 2000).map(i => 2*i), }; return sinks; }
What if we want to change it to mouse event? we need to somehow modiy the DOMSource it return from:
function DOMDriver(obj$) { function createElement(obj) { const element = document.createElement(obj.tagName); obj.children .filter(c => typeof c === 'object') // if it is object, then we need to create another element .map(createElement) .forEach(c => element.appendChild(c)); obj.children .filter(c => typeof c === 'string') .forEach(c => element.innerHTML += c); 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; }
So for main() function, we need to call a function able to manage the tagName and eventType:
const mouseover$ = sources.DOM.selectEvents('span', 'mouseover');
And for the DomDirver, we need add a function which enable user to pass down element and eventType:
const DOMSource = { selectEvents: function(tagName, eventName){ return Rx.Observable.fromEvent(document, eventName); } };
-------------------------
Code:
// Logic (functional) function main(sources) { const mouseover$ = sources.DOM.selectEvents('span', 'mouseover'); const sinks = { DOM: mouseover$ .startWith(null) .flatMapLatest(() => Rx.Observable.timer(0, 1000) //describe what element should exist .map(i => { return { tagName: 'h1', children: [ { tagName: 'span', children: [ `time esplsed: ${i}` ] } ] } }) ), Log: Rx.Observable.timer(0, 2000).map(i => 2*i), }; return sinks; } // source: input (read) effects // sink: output (write) effects // Effects (imperative) function DOMDriver(obj$) { function createElement(obj) { const element = document.createElement(obj.tagName); obj.children .filter(c => typeof c === 'object') // if it is object, then we need to create another element .map(createElement) .forEach(c => element.appendChild(c)); obj.children .filter(c => typeof c === 'string') .forEach(c => element.innerHTML += c); return element; } obj$.subscribe(obj => { const container = document.querySelector('#app'); container.innerHTML = ''; const element = createElement(obj); container.appendChild(element); }); const DOMSource = { selectEvents: function(tagName, eventName){ return Rx.Observable.fromEvent(document, eventName); } }; return DOMSource; } function consoleLogDriver(msg$) { msg$.subscribe(msg => console.log(msg)); } const drivers = { DOM: DOMDriver, Log: consoleLogDriver, } Cycle.run(main, drivers);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具