运行 js 代码在 dom 中渲染后 Cycle.js

Running js code after all dom rendered in Cycle.js

我想使用 Foundation 的显示插件在 Cycle.js 应用程序中显示一个漂亮的模式。

在玩了几个小时的 Webpack 及其配置之后,我想出了如何将 foundation 的 js 正确地导入到我的 (es6) 应用程序中。

但是,由于我处理的是虚拟的dom,实际的html在初始化foundation的js时是不存在的。

这是我的组件代码:

import Rx from 'rx';
import {div} from '@cycle/dom';

import $ from 'jquery';
import {foundation} from 'foundation-sites/js/foundation.core';
import 'foundation-sites/js/foundation.util.keyboard';
import 'foundation-sites/js/foundation.util.box';
import 'foundation-sites/js/foundation.util.triggers';
import 'foundation-sites/js/foundation.util.mediaQuery';
import 'foundation-sites/js/foundation.util.motion';
import 'foundation-sites/js/foundation.reveal';

require('./styles/configuration-modal.scss');

function ConfigurationModal(sources) {

    const values$ = sources.props$;

    const vtree$ = Rx.Observable.just(1).map(() => {
        return div(
            '#config-modal.reveal',
            {attributes: {
                'data-reveal': ''
            }},
            ['hello']
        );
    });

    return {
        DOM: vtree$,
        values$
    };
}

$(function() {
    $.fn.foundation = foundation;
    $(document).foundation();
});

export default ConfigurationModal;

我的main.js:

import Rx from 'rx';
import Cycle from '@cycle/core';
import {makeDOMDriver, div} from '@cycle/dom';
import ConfigurationModal from './components/ConfigurationModal/index';

require('./styles/index.scss');

function main(sources) {
    const props$ = Rx.Observable.of({
        pomodoroDuration: 25 * 60,
        shortBreakDuration: 5 * 60,
        longBreakDuration: 15 * 60
    });
    const configurationModal = ConfigurationModal({
        DOM: sources.DOM,
        props$
    });

    return {
        DOM: configurationModal.DOM,
    };
}

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

现在,如果我在应用程序初始化后 运行 $(document).foundation() 在控制台中,一切都会按预期进行。但是在应用程序代码中,由于 dom 是虚拟的,实际的 html 尚未注入,所以什么也没有出现。

在应用程序完全初始化并且 dom 实际填充后,我如何 运行 js 代码?

在 Cycle 中,DOM 驱动程序有一个有用的功能,允许您订阅元素的更新。

在这种情况下,您可以在应用程序启动后 运行 编码,如下所示:

DOM
 .select(':root')
 .element()
 .take(1)
 .subscribe((element) => $(document).foundation())

您可以将其添加到您的主程序中,这应该可以解决您的问题。

但是,在 Cycle 中,将所有订阅封装在驱动程序中是惯用的做法,因为它们通常是副作用。在这种情况下,您可以制作一个驱动程序来启动 Foundation,如下所示:

function startFoundation () {
  $(document).foundation();
}

function foundationDriver(sink$) {
  return sink$.take(1).subscribe(startFoundation);
}

在你的main.js中:

function main(sources) {
    // ...

    const startup$ = sources.DOM.select(':root').element().take(1);

    return {
        DOM: configurationModal.DOM,

        FoundationStartup: startup$
    };
}

Cycle.run(main, {
    DOM: makeDOMDriver('#app'),
    FoundationStartup: foundationDriver
});