【问题标题】:Use a variable inside a CDATA block, in Javascript?在 Javascript 中使用 CDATA 块内的变量?
【发布时间】:2011-06-05 23:00:27
【问题描述】:

CDATA-blocks 非常适合将大块 HTML 或 CSS 编码为字符串。但是,我不知道如何在一个变量中使用变量值。

例如,考虑以下 JavaScript 代码:

var FullName    = "Friedrich Hayek";
var ProfileCode = (<><![CDATA[
                    <div id="BigHonkingChunkO_HTML">
                        ...Lot's o' code...

                        Name: $FullName$
                        Birth: $Birthdate$

                        ...Lot's o' code...

                        ... $FullName$ ...

                        ...Lot's o' code...
                    </div>
                ]]></>).toString ();


如何让$FullName$ 呈现为“Friedrich Hayek”而不是“$FullName$”?

请注意,有多个变量,每个变量可以在 CDATA 块中使用几次。


备用代码示例:

var UserColorPref   = "red";
var UI_CSS          = (<><![CDATA[
                        body {
                            color:              $UserColorPref$;
                        }
                    ]]></>).toString ();

希望将颜色属性设置为red

【问题讨论】:

    标签: javascript variables cdata


    【解决方案1】:

    够优雅吗?

    function replaceVars(content, vars)
    {
        return content.replace(/\$(\w+)\$/g, function($0, $1)
        {
            return ($1 in vars ? vars[$1] : $0);
        });
    }
    
    ProfileCode = replaceVars(ProfileCode, {"FullName" : "Friedrich Hayek"});
    

    如果关联键并不重要,您可以随时选择使用:
    sprintfvsprintf

    编辑

    让第二个参数可选呢?

    function replaceVars(content, scope) {
        if (!scope || typeof scope != "object") {
            scope = this;
        }
    
        return content.replace(/\$(\w+)\$/g, function($0, $1) {
            return ($1 in scope ? scope[$1] : $0);
        });
    }
    
    // example1
    var FullName = "Friedrich Hayek";
    ProfileCode = replaceVars(ProfileCode);
    
    // example2
    var vars = {"FullName" : "Friedrich Hayek"};
    ProfileCode = replaceVars(ProfileCode, vars);
    

    【讨论】:

    • replaceVars() 是优雅的。调用它比函数的类似 sprintf() 的版本有点笨拙。 +1。
    • 这更容易使用,也是一个不错的选择。但是使第二个参数可选可能会使代码变得模糊。只看到ProfileCode = replaceVars(ProfileCode); 意味着开发人员必须仔细检查ProfileCode,然后扫描整个JS 代码,看看是什么替换了什么! ...函数的第一个版本,以及我们最终使用的函数,都在函数调用级别自我记录了他们的意图。
    【解决方案2】:
    ProfileCode=ProfileCode.replace('$FullName$',FullName);
    

    【讨论】:

    • 这有点笨拙,不能优雅地扩展。在实际的实时代码中,目前有 8 个变量在起作用。我希望有一个更内联的解决方案。
    • 使用数组,将变量名映射到值并在循环遍历时替换它们。
    【解决方案3】:

    在搜索 the CDATA specthis "CDATA Confusion" article 之后,似乎 CDATA 部分将所有内容都视为纯文本,除了字符数据实体和部分结束标记 (]]&gt;)。例如,

    var x = $('<!DOCTYPE X[<!ENTITY foo "BAR">]><z> cc &#65; &foo;</z>');
    console.log ($(x, 'z').text() );
    

    产量:]&gt; cc A &amp;foo;

    因此,无法在 CDATA 部分中进行变量替换。我们能做的最好的事情就是开始和停止这些部分,如下所示:

    var FullName    = "Friedrich Hayek";
    var ProfileCode = (<><![CDATA[
                        <div id="BigHonkingChunkO_HTML">
                            ...Lot's o' code...
    
                            Name: ]]></>).toString () + FullName+ (<><![CDATA[
    
                            ...Lot's o' code...
                        </div>
                    ]]></>).toString ();
    console.log (ProfileCode);
    

    ——这显然是不能接受的。


    实际解决方法:

    它不会帮助任何寻找 CDATA 解决方案的人(我们现在知道,根据规范,这是不可能的)。但由于我们只是使用 CDATA 作为生成复杂字符串的方法,因此我们可以在之后清理字符串,根据 Ratna Dinakar 的回答。

    我们最终使用的函数是:

    function sSetVarValues (sSrcStr, sReplaceList /* , Variable */)
    /*--- function sSetVarValues takes a string and substitutes marked
        locations with the values of the variables represented.
        Conceptually, sSetVarValues() operates a little like sprintf().
    
        Parameters:
            sSrcStr         --  The source string to be replaced.   
            sReplaceList    --  A string containing a comma-separated list of variable
                                names expected in the raw string.  For example, if 
                                sReplaceList was "Var_A", we would expect (but not require)
                                that sSrcStr contained one or more "$Var_A$" substrings.
            *Variable*      --  A variable-length set of parameters, containing the values
                                of the variables specified in sReplaceList.  For example,
                                if sReplaceList was "Var_A, Var_B, Var_C", then there better 
                                be 3 parameters after sReplaceList in the function call. 
        Returns:                The replaced string.
    */
    {
        if (!sSrcStr)       return null;
        if (!sReplaceList)  return null;
    
        var aReplaceList    = sReplaceList.split (/,\s?/);
    
        for (var J = aReplaceList.length-1;  J >= 0;  --J)
        {
            var zRepVar     = new RegExp ('\\$' + aReplaceList[J] + '\\$', "g");
            sSrcStr         = sSrcStr.replace (zRepVar, arguments[J+2]);
        }
        return sSrcStr;
    }
    


    使用示例:

    var AAA     = 'first';
    var BBB     = 'second'; 
    var CCC     = 'third';
    var Before  = "1 is $AAA$, 2 is $BBB$, 3 is $CCC$";
    
    var After   = sSetVarValues (Before, "AAA, BBB, CCC", AAA, BBB, CCC);
    
    console.log (Before);
    console.log (After);
    

    产量:

    1 是 $AAA$,2 是 $BBB$,3 是 $CCC$ 1是第一,2是第二,3是第三

    【讨论】:

      猜你喜欢
      • 2021-01-02
      • 2018-03-25
      • 2021-05-19
      • 2014-01-22
      • 1970-01-01
      • 2017-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多