将javascript和html分开以获取可读代码

时间:2014-02-20 07:17:36

标签: javascript jquery html css dojo

有时我的javascript代码与html和css混合。在这个stuation中,我的代码是不可读的。你如何在javascript中分离javascript和html?

例如:(使用javascript dojo toolkit)

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代码中。同时添加其他工具(HorizantalSlider)。 此工作流程彼此绑定。此代码无法读取。有没有办法用干净的代码解决这个问题?

4 个答案:

答案 0 :(得分:2)

这个答案使用Dojo从JavaScript中分割HTML + CSS。

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变量完全相同的内容,但会从JavaScript代码中分离HTML。


单独的CSS

要从HorizontalSlider分离CSS样式,您可以定义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;
}

答案 1 :(得分:1)

您可以将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或Google "javascript templating engine"

答案 2 :(得分:0)

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

例如:

http://handlebarsjs.com/

http://underscorejs.org/#template

答案 3 :(得分:0)

一种方法是使用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