【问题标题】:separating javascript and html for readable code分离 javascript 和 html 以获得可读代码
【发布时间】:2014-02-20 07:17:35
【问题描述】:

有时我的 javascript 代码会与 html 和 css 混合使用。在这种情况下,我的代码无法阅读。 javascript中的javascript和html端是怎么分开的?

例如:(使用javascript dojo工具包)

addLayer: function (layer, index) {                
var layerClass = layer.visible === true ? 'layer checked' : 'layer';
var html = '';
html += '<li class="' + layersClass + '">';
html += '<div class="cover"></div>';
html += '<span tabindex="0" class="info" title="MyTitle"></span>';
html += '<span tabindex="0" class="toggle box"></span>';
html += '<div class="clear"></div>';                    
html += '</li>';
var node = dom.byId('layersList');
if (node) {
    domConstruct.place(html, node, "first");
    HorizontalSlider({
        name: "slider",
        value: parseFloat(layer.opacity),
        minimum: 0,
        maximum: 1,
        showButtons: false,
        discreteValues: 20,
        intermediateChanges: true,
        style: "width:100px; display:inline-block; *display:inline; vertical-align:middle;",
        onChange: function (value) {
            layer.setOpacity(value);
        }
    }, "layerSlider" + index);

    if (!this.layerInfoShowClickHandler) {
        this.layerInfoShowClickHandler = on(query(".listMenu"), ".cBinfo:click, .cBinfo:keyup", this._onLayerInfoShowIconClicked);
    }
}                 
}

在这种情况下,我的代码是动态添加 html 到视图侧。将事件处理程序添加到创建的 html 代码。同时添加其他工具(Horizo​​ntalSlider)。 此工作流程相互绑定。此代码不可读。有没有办法用干净的代码解决这个问题?

【问题讨论】:

  • 您在哪里以及如何使用 HorizontalSlider ?我的意思是HorizontalSlider 的构建方式还是您的问题与html 变量有关?

标签: javascript jquery html css dojo


【解决方案1】:

此答案使用 Dojo 将您的 HTML + CSS 从 JavaScript 中分离出来。

HTML 模板

推荐的方法是在一个单独的 HTML 文件中定义您的 HTML 模板。例如:

<li class="{layersClass}">
    <div class="cover"></div>
    <span tabindex="0" class="info" title="MyTitle"></span>
    <span tabindex="0" class="toggle box"></span>
    <div class="clear"></div>
</li>

还要注意 layersClass 被占位符替换。


加载 HTML 模板

现在,要加载模板,您可以使用 dojo/text 插件。使用此插件,您可以加载外部模板,例如使用:

require(["dojo/text!./myTemplate.html"], function(template) {
    // The "template" variable contains your HTML template
});

转换占位符

要替换{layersClass},可以使用dojo/_base/lang模块的replace()函数。您的代码最终将如下所示:

require(["dojo/text!./myTemplate.html", "dojo/_base/lang"], function(myTemplate, lang) {
    var html = lang.replace(myTemplate, {
        layersClass: layersClass
    });
});

这将返回与您的 html 变量完全相同的结果,但将 HTML 与您的 JavaScript 代码分开。


单独的 CSS

要将 CSS 样式与您的 HorizontalSlider 分开,您可以定义一个 id 属性并将您的 CSS 放在单独的 CSS 文件中。你的HorizontalSlider 会变成:

HorizontalSlider({
    name: "slider",
    value: parseFloat(layer.opacity),
    minimum: 0,
    maximum: 1,
    showButtons: false,
    discreteValues: 20,
    intermediateChanges: true,
    id: "mySlider",
    onChange: function (value) {
        layer.setOpacity(value);
    }
}, "layerSlider" + index);

现在您可以使用以下 CSS:

#mySlider {
    width:100px;
    display:inline-block;
    *display:inline;
    vertical-align:middle;
}

【讨论】:

  • 这种方式与在dojo中创建基于模板的小部件是一样的吗?还有什么区别?
  • 类似,但基于模板的小部件使用另一个解析器。在这个例子中,我使用了dojo/_base/lang::replace(),但基于模板的小部件使用了一个单独的解析器,它也解释了data-dojo-attach-pointdata-dojo-attach-event 属性。占位符符号也略有不同,因为在模板中您将使用 ${layerClass},而现在我们做了类似的事情,但没有美元符号 $(但您可以使用 dojo/_base/lang 覆盖模式)。
【解决方案2】:

您可以将html 变量存储在不同的位置,比如说在一个名为template.js 的文件中。但是,这样做您不能立即连接 HTML 字符串,因为您需要注入此 layersClass 变量。这是一个可能的解决方法:

// template.js

var template = function () {
    return [
        '<li class="', this.layersClass, '">',
            '<div class="cover"></div>',
            '<span tabindex="0" class="info" title="MyTitle"></span>',
            '<span tabindex="0" class="toggle box"></span>',
            '<div class="clear"></div>',
        '</li>'
    ].join('');
};
// view.js

html = template.call({ 
    layersClass: layerClass 
});

有效且易于使用。但是,如果您想以字符串而不是函数的形式使用模板,则需要模板解析器。以下将给出与上述相同的结果(注意 IE7 split() 不支持正则表达式捕获):

function compile(tpl) {
    tpl = Array.prototype.join.call(tpl, '').split(/{{(.*?)}}/);
    return Function('return [' + tpl.map(function (v, i) {
        if (i % 2) return 'this["' + v + '"]';
        return v && '"' + v.replace(/"/g, '\\"') + '"';
    }).join(',') + '].join("");');
}

使用示例:

var template = '<b>{{text}}</b>';
var compiled = compile(template);
// compiled -> function () {
//     return ["<b>",this["text"],"</b>"].join("");
// }
var html1 = compiled.call({ text: 'Some text.' });
var html2 = compiled.call({ text: 'Bold this.' });
// html1 -> "<b>Some text.</b>"
// html2 -> "<b>Bold this.</b>"

现在,让我们看看如何使用此工具以干净的方式组织文件。

// product.data.js

product.data = [{ 
    name: 'Apple iPad mini', 
    preview: 'ipadmini.jpeg', 
    link: 'ipadmini.php',
    price: 280
}, { 
    name: 'Google Nexus 7',
    preview: 'nexus7.jpeg', 
    link: 'nexus7.php',
    price: 160
}, { 
    name: 'Amazon Kindle Fire',
    base64: 'kindlefire.jpeg', 
    link: 'kindlefire.php',
    price: 230
}];
// product.tpl.js

product.tpl = [
    '<div class="product">',
        '<img src="{{preview}}" alt="{{name}}" />',
        '<span>{{name}} - ${{price}}</span>',
        '<a href="details/{{link}}">details</a>',
    '</div>'
];
// product.view.js

var html = [];
var compiled = compile(product.tpl);
for (var i = 0, l = product.data.length; i < l; i++) {
    html.push(compiled.call(product.data[i]));
}
document.getElementById('products').innerHTML = html.join('');

演示:http://jsfiddle.net/wared/EzG3p/.

更多细节在这里:https://stackoverflow.com/a/20886377/1636522


这个compile 函数可能不足以满足您的需求,我的意思是,您可能很快需要更强大的东西,例如包括条件结构。在这种情况下,您可以查看MustacheHandlebarsJohn Resig 或谷歌"javascript templating engine"

【讨论】:

    【解决方案3】:

    考虑使用模板来构建动态视图元素

    例如:

    http://handlebarsjs.com/

    http://underscorejs.org/#template

    【讨论】:

      【解决方案4】:

      一种方法是使用 HTML (如果您不喜欢拆分逻辑,那就没那么酷了):

       <div style="display:none" id="jQ_addLayer">    
          <div class="cover"></div>
          <span tabindex="0" class="info" title="MyTitle"></span>
          <span tabindex="0" class="toggle box"></span>
          <div class="clear"></div>
        </div>
      

      在 jQuery 中使用传递的变量创建 LI 并插入您的 #jQ_addLayer 内容:

      var html = '<li class="'+layersClass+'">'+ $("#jQ_addLayer").html() +'</li>';
      

      另一种方法是转义你的字符串换行符:

      var html = '\
         <li class="' + layersClass + '">\
           <div class="cover"></div>\
           <span tabindex="0" class="info" title="MyTitle"></span>\
           <span tabindex="0" class="toggle box"></span>\
           <div class="clear"></div>\
         </li>'; //don't forget to escape possible textual single-quotes in your string
      

      【讨论】:

        猜你喜欢
        • 2012-07-31
        • 2013-04-18
        • 1970-01-01
        • 2011-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-16
        相关资源
        最近更新 更多