2016-03-28 63 views
0

只是试图来愚蠢的东西,并与Cycle.js玩耍。并遇到问题。基本上我只是有一个按钮。当你点击它时,假设将该位置导航到随机哈希并显示它。几乎就像一个没有预定义路由的愚蠢路由器。 IE浏览器。路线是动态的。再次,这不是什么实际的,我只是搞乱了一些东西,并试图学习Cycle.js。但是当我点击“添加”按钮后,下面的代码崩溃了。但是位置已更新。如果我实际上只是导航到“#/ asdf”,它显示正确的内容与“哈希:#/ asdf”。不知道为什么流与错误而崩溃:简单的历史记录推碰

渲染dom.js:242类型错误:无法读取属性未定义“订阅”(...)

import Rx from 'rx'; 
import Cycle from '@cycle/core'; 
import { div, p, button, makeDOMDriver } from '@cycle/dom'; 
import { createHashHistory } from 'history'; 
import ranomdstring from 'randomstring'; 

const history = createHashHistory({ queryKey: false }); 

function CreateButton({ DOM }) { 
    const create$ = DOM.select('.create-button').events('click') 
    .map(() => { 
     return ranomdstring.generate(10); 
    }).startWith(null); 

    const vtree$ = create$.map(rs => rs ? 
    history.push(`/${rs}`) : 
    button('.create-button .btn .btn-default', 'Add') 
); 

    return { DOM: vtree$ }; 
} 

function main(sources) { 
    const hash = location.hash; 
    const DOM = sources.DOM; 

    const vtree$ = hash ? 
    Rx.Observable.of(
     div([ 
     p(`Hash: ${hash}`) 
     ]) 
    ) : 
    CreateButton({ DOM }).DOM; 

    return { 
    DOM: vtree$ 
    }; 
} 

Cycle.run(main, { 
    DOM: makeDOMDriver('#main-container') 
}); 

感谢您的帮助

回答

2

在你的函数CreateButton你映射你的点击,history.push(),而不是它映射到vtree这将导致错误

function CreateButton({ DOM }) { 
    ... 
    const vtree$ = create$.map(rs => rs 
    ? history.push(`/${rs}`) // <-- not a vtree 
    : button('.create-button .btn .btn-default', 'Add') 
); 
    ... 
} 

相反,你可以用做运营商执行hashchange:在函数式编程

function CreateButton({ DOM }) { 
    const create$ = 
    ... 
    .do(history.push(`/${rs}`)); // <-- here 

    const vtree$ = Observable.of(
    button('.create-button .btn .btn-default', 'Add') 
); 
    ... 
} 

但是你不应该在你的应用程序逻辑执行副作用,每一个功能必须保持pure。相反,所有的副作用都应该由司机处理。要了解更多,请查看drivers section on Cycle's documentation

在消息结尾处看到正在工作的驱动程序跳转。


而且您main功能你不使用流渲染你vtree。由于vtree$ = hash ? ... : ...仅在应用程序引导时评估过一次(当主函数被评估并“将每个流连接在一起”时),所以它不会反应到locationHash更改。

的改善将是宣布你main的vtree $如下,同时保持相同的逻辑:

const vtree$ = hash$.map((hash) => hash ? ... : ...) 

这里是一个小locationHash驱动器的完整解决方案:

import Rx from 'rx'; 
import Cycle from '@cycle/core'; 
import { div, p, button, makeDOMDriver } from '@cycle/dom'; 
import { createHashHistory } from 'history'; 
import randomstring from 'randomstring'; 


function makeLocationHashDriver (params) { 
    const history = createHashHistory(params); 

    return (routeChange$) => { 
    routeChange$ 
     .filter(hash => { 
     const currentHash = location.hash.replace(/^#?\//g, '') 
     return hash && hash !== currentHash 
     }) 
     .subscribe(hash => history.push(`/${hash}`)); 

    return Rx.Observable.fromEvent(window, 'hashchange') 
     .startWith({}) 
     .map(_ => location.hash); 
    } 
} 

function CreateButton({ DOM }) { 
    const create$ = DOM.select('.create-button').events('click') 
    .map(() => randomstring.generate(10)) 
    .startWith(null); 

    const vtree$ = Rx.Observable.of(
    button('.create-button .btn .btn-default', 'Add') 
); 

    return { DOM: vtree$, routeChange$: create$ }; 
} 

function main({ DOM, hash }) { 
    const button = CreateButton({ DOM }) 
    const vtree$ = hash.map(hash => hash 
    ? Rx.Observable.of(
     div([ 
      p(`Hash: ${hash}`) 
     ]) 
    ) 
    : button.DOM 
) 

    return { 
    DOM: vtree$, 
    hash: button.routeChange$ 
    }; 
} 

Cycle.run(main, { 
    DOM: makeDOMDriver('#main-container'), 
    hash: makeLocationHashDriver({ queryKey: false }) 
}); 

PS:您的randomstring函数名称存在拼写错误,我在示例中对其进行了修复。

+0

啊是有道理的。应该已经想通了。谢谢帮助表示赞赏 – Bojan

5

我会进一步建议使用@周期/历史做你的路径切换 (只显示相关部分)

import {makeHistoryDriver} from '@cycle/history' 
import {createHashHistory} from 'history' 

function main(sources) { 
    ... 
    return {history: Rx.Observable.just('/some/route') } // a stream of urls 
} 

const history = createHashHistory({ queryKey: false }) 
Cycle.run(main, { 
    DOM: makeDOMDriver('#main-container'), 
    history: makeHistoryDriver(history), 
}) 
+0

你好,感谢您的反馈。对不起,我觉得真的很愚蠢,但我无法使用@ cycle/history;我尝试了不同的东西并阅读文档。如何将历史驱动程序与按钮的更改事件连接起来?我想结合这两个流? – Bojan

+0

嗯,我想我终于明白了,谢谢你的帮助。 – Bojan