如何多次包含相同的 JSF 复合组件以拥有自己的 javascript 范围?

How to make same JSF Composite Component included multiple times to have its own javascript scope?

我有一个像这样的 JSF 复合组件:

 <cc:implementation>
   <div id="#{cc.clientId}">
        <h:outputScript library="js" name="helper.js"/>

        <script type="text/javascript">
        if(typeof variables === "undefined"){
             var variables = {};
        }

        (function(){
            variables.formid = '#{cc.clientId}'; 
        })();
        </script>
    </div>

variables.formid 的值我在 helper.js 文件中使用。当我只包含这个复合组件一次时,它会正常工作。当我包含多个复合组件时,每个组件都会收到最后一个包含的复合组件的值,我该如何解决这个问题?

基本上有两种方法。

  1. helper.js中添加一种"register"函数,这样你就可以在那里明确地注册它,而不是让它搜索复合材料。

    <h:outputScript name="js/helper.js" target="head" />
    <div id="#{cc.clientId}">
        ...
    </div>
    <h:outputScript>helper.register("#{cc.clientId}", { foo: "somevalue" });</h:outputScript>
    

    可以通过 JS 对象作为参数提供选项。 a.o也是这样。 PrimeFaces 使用 PrimeFaces.cw() 函数,其中 "widget name" 也作为选项传递。

  2. 给合成一个独特的风格class像这样:

    <h:outputScript name="js/helper.js" target="head" />
    <div id="#{cc.clientId}" class="your-foo-composite">
        ...
    </div>
    

    这样 helper.js 就可以在文档准备期间通过 class 名称收集它们。

    // Vanilla JS:
    var yourFooComposites = document.getElementsByClassName("your-foo-composite");
    
    // Or if you happen to use jQuery:
    var $yourFooComposites = $(".your-foo-composite");
    

    选项可以提供为 HTML5 data attributes (browser support is good these days)。

    <div id="#{cc.clientId}" class="your-foo-composite" data-foo="somevalue">
    

    可以通过以下方式获得:

    // Vanilla JS:
    for (var i = 0; i < yourFooComposites.length; i++) {
        var yourFooComposite = yourFooComposites[i];
        var clientId = yourFooComposite.id;
        var dataFoo = yourFooComposite.dataset.foo;
        // ...
    }
    
    // Or if you happen to use jQuery:
    $yourFooComposites.each(function(index, yourFooComposite) {
        var $yourFooComposite = $(yourFooComposite);
        var clientId = $yourFooComposite.attr("id");
        var dataFoo = $yourFooComposite.data("foo");
        // ...
    });
    

    它还使您的 HTML 输出没有内联脚本。


与具体问题无关,在您的初始代码中使用 "js" 作为库名称并不好。仔细阅读 What is the JSF resource library for and how should it be used? 另请注意,我在 <h:outputScript> 中添加了 target="head" 属性。如果您正确使用 JSF <h:head> 组件,它会让 JSF 自动将脚本重新定位到生成的 HTML <head> 元素。