在 Cycle.js 中呈现所有 dom 后运行 js 代码

Posted

技术标签:

【中文标题】在 Cycle.js 中呈现所有 dom 后运行 js 代码【英文标题】:Running js code after all dom rendered in Cycle.js 【发布时间】:2016-07-31 12:58:01 【问题描述】:

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

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

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

这是我的组件代码:

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(),一切都会按预期工作。但是在app代码中,由于dom是虚拟的,实际的html还没有被注入,所以什么都没有出现。

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

【问题讨论】:

你可能需要 virtual-dom 小部件github.com/cyclejs/core/issues/10 看起来很有趣,谢谢。 【参考方案1】:

在 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
);

【讨论】:

@Widdershin ':root' 是一个特殊的关键字吗?我尝试了代码并且 select(':root') 返回一个 null @patrick 是的,':root' 是特殊的,它将选择应用程序的容器元素。这不起作用的原因可能是因为.observable 现在是.element()。我会更新我的答案以反映这一点:)

以上是关于在 Cycle.js 中呈现所有 dom 后运行 js 代码的主要内容,如果未能解决你的问题,请参考以下文章

[Cycle.js] Making our toy DOM Driver more flexible

[Cycle.js] Read effects from the DOM: click events

在 Nuxt.js 中完全呈现路由后运行函数

使用 $and 查询后,结果不会在 DOM 上呈现

[Cycle.js] Introducing run() and driver functions

无法在Mac Safari中呈现HTML