JavaScript HERE-doc 或其他大型引用机制?
Posted
技术标签:
【中文标题】JavaScript HERE-doc 或其他大型引用机制?【英文标题】:JavaScript HERE-doc or other large-quoting mechanism? 【发布时间】:2011-02-26 13:49:46 【问题描述】:有没有一种方便的方法来引用 javascript 中同时包含单引号和双引号的大块 html?
是否有类似 HERE-doc <<EOF
、多引号字符 """
或自定义分隔符 q
?
对这个问题有什么创造性或创造性的解决方案吗?
【问题讨论】:
Creating multiline strings in JavaScript 的可能重复项 ECMAscript 6,现在是标准,允许对多行字符串使用反引号。这方面的一个例子,假装\n
是一个文字换行符,将是var foo = `multi \n line \n string`
【参考方案1】:
JavaScript 做不到,但 CoffeeScript,它是 JavaScript 之上的一个薄层,可以。
点击链接并向下滚动到“多行字符串和 Heredocs”。
【讨论】:
> 如果链接页面发生更改,仅链接的答案可能会变得无效。 ...这正是发生的事情。这是一个有效的网址:coffeescript.org/#strings【参考方案2】:有些人不喜欢这样,所以要做好轻蔑和嘲笑的准备,但一个技巧是将你的“大块东西”倾倒到<script language="text">
块中:
<script id='blockOfStuff' language="text">
Hi this is random stuff
<h1>Including HTML markup</h1>
And quotes too, or as one man said, "These are quotes, but
'these' are quotes too."
</script>
John Resig 使用这种技术(或者,如果您愿意,也可以使用这种可憎的技术)作为他的模板机制的示例。
您可以根据需要使用“innerText”或“innerHTML”或通过您喜欢的框架的服务来获取内容。
edit — 请注意,通过 jQuery(与我在下面的评论中所说的相反).text()
确实 not 工作,虽然我认为它应该。请改用.html()
。
【讨论】:
++,我很开心。我什至没有那么生气。尽管在这种情况下出于 SEO 的原因,我不希望在 html 中包含文本块(因为动态操作正在使其发挥作用,因此默认情况下不适用于页面)。 与安迪的有趣回答不同,这可以跨浏览器工作吗?哦,正如我今天多次说过的,<script>
元素的language
属性是deprecated。 :-P
@Marcel 我认为确实如此;我没有做过很多测试。我有点假设如果 Resig 先生在博客文章等中使用它,它可能是相当“安全的”。我也想知道“语言”,尤其是。 w.r.t.未来的 HTML5 支持。
@Marcel:我很高兴我的回答逗乐了你,我在写它的时候对自己微笑。我认为@Pointy 在这里有唯一可行的生产解决方案,我不明白为什么它不能在所有浏览器中工作,它肯定是有道理的,即使应用完全虚假的语言或 mime 类型只要既不是空的也不是实际支持的脚本语言。
@Andy E 好吧,我认为 Firefox 与“innerHTML”相当松散,并将交回<script>
的内容。如果你在 IE 中调用 <script>
或 <style>
块,你会得到一个奇怪的“未知异常”错误,但我认为“innerText()”有效。我不太确定,因为我只是调用 $('#scriptId').text()` :-) (哦,它们当然不是函数!对不起!)【参考方案3】:
我记得不久前看到一个聪明的解决方案,它在函数中使用了多行 cmets:
(function ()
/*
"This is an example of a multi-line string. It's really just a mult-line
comment, and it's wrapped in quote marks. You might also notice the
apostrophe's ;-)";
*/
);
注意:最后一个撇号是故意不正确的;-P
诀窍是调用函数的toString()
方法并使用正则表达式解析出多行注释。聪明,但很像 Pointy 的建议,有点可恶。
我实际上并不认为问题是寻找一种用于生产用途的切实可行的方法——这是我自己的过错,我不敢贸然下结论——我不确定你为什么不直接逃避相关的字符串文字分隔符。正如 Tim Down 在下面的 cmets 中指出的那样,ECMAScript 第 3 版将函数的 toString() 定义为依赖于实现。
为了好玩,我决定检查浏览器的兼容性,这种方法在 IE、Opera、Safari 和 Chrome 中是可行的,但在 Firefox 中是可行的,它在返回的字符串中不包含 cmets。 http://jsfiddle.net/2yvXG/
【讨论】:
说真的,这真的很脆弱:函数如何将自己转换为字符串是未指定的,在当前浏览器中有效的方法可能在未来的浏览器中无效。来自 ECMAScript 3 规范:"15.3.4.2 Function.prototype.toString ( )。返回一个依赖于实现的函数表示。这种表示具有 FunctionDeclaration 的语法。特别注意使用和放置表示字符串中的空格、行终止符和分号取决于实现。" 不适用于我 Firefox 3.5javascript:alert ( (function () /*foo "" '" bar "' '' */ ).toString() )
@Evan:我承认,我并没有在每个浏览器中都测试它:-)
@Tim:他要求提供创造性或创造性的解决方案,我认为这至少符合其中一个条件 ;-) 无论如何,我并不打算将答案作为一个严肃的使用建议在任何生产环境中,可能应该在某处提到这一点!
@Andy:当然,它很有创意。在这方面我没有批评 :) 至少你完整地阅读了这个问题,这比我管理的要多。【参考方案4】:
本机不支持。
但既然我们正在讨论如何让它发挥作用,这里有一个(根据我的经验):
<script type="text/javascript">
var name = "Mud";
var str = "\
My name is " + name + "\
not to be confused with Bill\
or Jack or Pete or Dennis\
my name is " + name + " and it's always been\
";
alert("Les'n one: " + str);
</script>
那些反斜杠可以解决问题。只需确保对字符串中的任何双引号进行反斜杠转义,因为整个块都被它们引用。
请注意,这不会保留换行符,您必须在每行尾随斜杠之前手动将它们插入为“\n”。另一方面,每行开头的任何空白缩进都将包含在输出中。
当您必须在脚本(例如 XML)中声明一个长的多行字符串时,这确实最有效,但当您需要保持该字符串的格式与您定义它的方式完全相同时,效果就不那么好了。
干杯
【讨论】:
【参考方案5】:这是你的答案。在您的页面正文中创建一个跨度或 div,使用唯一的 id 并在其中放置您想要的所有文本以及您想要的所有引号都没有关系。使 span 或 div 的样式为“display:none; visibility:hidden;”。然后,当您希望它从 id 获取 DOM 对象并检索 innerHTML 以执行您想要的操作时。
【讨论】:
Op 要求的是 JS 解决方案,而不是 DOM 解决方案。在你已经设置了display:none;
之后设置visibility:hidden;
有什么意义?【参考方案6】:
我实际上设计了一个类似于 user742675 的 kludgy 变体,您将文本放在一个 div 中,然后将其可见性设置为无,然后提取内容。但是仅仅引用大量的 HTML 是不够的,所以我添加了一个功能来获取你在脚本中声明的所有变量,所以如果你有 var a = 'Steve'
,你的 heredoc 文本中的任何 $a 实例都是呈现为“史蒂夫”。
<script type="text/javascript">
// set variables named andy and handy, which we can use as $andy and $handy in our text
var andy = "Fred Flintstone";
var handy = "Steve Austin";
function hereDoc(divid)
var obj = window; // gets an object containing all the variables
var str = document.getElementById(divid).innerHTML; // gets the HTML block
for(var i in obj)
/* the for loop recurses through all the objects in the page - remember strings are objects in Javascript */
if((typeof(obj[i])=="string")||(typeof(obj[i])=="number"))
/* Type of makes sure it only executes replacement for strings and numbers. The function worked without this test in Firefox and Safari, but threw errors on Opera until it was added. */
myregex = new RegExp('\\$'+i,"g");
/* To replace globally, you need to use a regular expression and use the "g" option, but within the string.replace() method, the regular expression is unquoted, so you can't use a variable in it directly. So we create it and assign it to a RegExp object that works in the string.replace() method. */
str = str.replace(myregex, obj[i]);
/* we replace instances of the variable name with a dollar sign before it with the variable's value */
return str;
/* and when the loop is done, we return the processed text to be used however needed */
function gotoit()
/* fill the "steve" div with the processed contents of the "randy" div. */
document.getElementById("steve").innerHTML = hereDoc("randy");
</script>
<a href="javascript:gotoit();">Run the script</a>
<div id="randy" style="display:none;">
The interesting thing about $andy is that he's not nearly as popular with young kids as $handy.<br><br>
What I really find 'interesting' is that this "multiline" thing works as well as $handy's bionic arm. <br><br>
</div>
<div id="steve"></div>
【讨论】:
【参考方案7】:用于 JavaScript 的 HereDoc
FuncToHereDoc(“demiter”,带有注释的 HEREDOC 的未调用函数)
function FuncToHereDoc(here,str)
var reobj = new RegExp("/\\*"+here+"\\n[\\s\\S]*?\\n"+here+"\\*/", "m");
str = reobj.exec(str).toString();
str = str.replace(new RegExp("/\\*"+here+"\\n",'m'),'').toString();
return str.replace(new RegExp("\\n"+here+"\\*/",'m'),'').toString();
用法:
FuncToHereDoc("HERE", MyHereDoc);
function MyHereDoc()
/*HERE
<p>
This is written ing the HEREDOC, notice the multilines :D.
</p>
<p>
HERE
</p>
<p>
And Here
</p>
HERE*/
【讨论】:
这只是假设func.toString();
返回源代码。 That was identified as being unsafe below
@EvanCarroll 假设 SO 上答案的垂直顺序也是不安全的;)【参考方案8】:
根据之前的回答和不同的用例,这里是一个小例子:
https://gist.github.com/lavoiesl/5880516
/*!
* Extract a function's comment, useful to have multiline string
* @link https://gist.github.com/lavoiesl/5880516
*
* Don't forget to use /*! to avoid the comment being removed in minification
*/
function extractFuncCommentString(func)
var matches = func.toString().match(/function\s*\(\)\s*\\s*\/\*\!?\s*([\s\S]+?)\s*\*\/\s*\/);
if (!matches) return false;
return matches[1];
var myString = extractFuncCommentString(function()/*!
<p>
foo bar
</p>
*/);
【讨论】:
这只是假设 func.toString();返回源代码。 That was identified as being unsafe below 它表示它返回函数的实现相关表示,即 FunctionDefinition,但不确定 空格 的位置。我的总结似乎可以解决任何空白问题,即使已最小化。【参考方案9】:我对这个问题很感兴趣,因为我想使用 javascript 将新行添加到编辑屏幕(例如,用于多个电话号码)。 (我可以为此使用 ajax,但希望避免额外的服务器请求。)
我喜欢 Pointy 关于使用标签来包含您要使用的 html 块的回答:
<script id='blockOfStuff'>
Hi this is random stuff
<h1>Including HTML markup</h1>
</script>
但是当我尝试这个时,Firefox 和 Chrome 抱怨语法错误。我的解决方案是将“脚本”标签更改为“div”,通过 css 向用户隐藏其显示,并将其移动到正文中。例如:
<div style="display: none;" id="new_row_innerhtml">
<td><a href="#" onclick="removeCurrentRow(this); return false;">Remove</a></td>
<input type="hidden" name="id[]" value="new" />
<td><input name="name[]" type="text" /></td>
</div>
That removed the syntax errors.
Here's how I used that block:
I had an "Add" link that called the appendRow function:
<a href="#" onclick="appendRow(this); return false;">Add</a>
here's the appendRow function:
function appendRow()
var tbl = document.getElementById('my_table');
var row = tbl.insertRow(-1); // add to end of table
【讨论】:
我将此解决方案用作一个很好的解决方法。这让我可以毫无问题地将许多会导致各种 JS 心痛的文本放入我的应用程序中。【参考方案10】:// js heredoc - http://***.com/a/32915549/466363
// a function with comment with eval-able string, use it just like regular string
function extractFuncCommentString(func,comments)
var matches = func.toString().match(/function\s*\(\)\s*\\s*\/\*\!?\s*([\s\S]+?)\s*\*\/\s*\/);
if (!matches) return undefined;
var str=matches[1];
// i have made few flavors of comment removal add yours if you need something special, copy replacement lines from examples below, mix them
if(comments===1 )
// keep comments, in order to keep comments you need to convert /**/ to / * * / to be able to put them inside /**/ like /* / * * / */
return (
str
.replace(/\/\s\*([\s\S]*?)\*\s\//g,"/*$1*/") // change / * text * / to /* text */
)
else if(comments===2)
// keep comments and replace singleline comment to multiline comment
return (
str
.replace(/\/\s\*([\s\S]*?)\*\s\//g,"/*$1*/") // change / * text * / to /* text */
.replace(/\/\/(.*)/g,"/*$1*/") // change //abc to /*abc*/
)
else if(comments===3)
// remove comments
return (
str
.replace(/\/\s\*([\s\S]*?)\*\s\//g,"") // match / * abc * /
.replace(/\/\/(.*)/g,"") // match //abc
)
else if(comments===4)
// remove comments and trim and replace new lines with escape codes
return (
str
.replace(/\/\s\*([\s\S]*?)\*\s\//g,"") // match / * abc * /
.replace(/\/\/(.*)/g,"") // match //abc
.trim() // after removing comments trim and:
.replace(/\n/g,'\\n').replace(/\r/g,'\\r') // replace new lines with escape codes. allows further eval() of the string, you put in the comment function: a quoted text but with new lines
)
else if(comments===5)
// keep comments comments and replace strings, might not suit when there are spaces or comments before and after quotes
// no comments allowed before quotes of the string
// url html links
return (
str
.replace(/\/\s\*([\s\S]*?)\*\s\//g,"/*$1*/") // change / * text * / to /* text */
.replace(/\/\/(.*)/g,"/*$1*/") // change //abc to /*abc*/
.trim() // trim space around quotes to not escape it and:
.replace(/\n/g,'\\n').replace(/\r/g,'\\r') // replace new lines with escape codes. allows further eval() of the string, you put in the comment function: a quoted text but with new lines
)
else if(comments===6)
// good for html with links
// remove comments and trim and replace new lines with escape codes
return (
str
.replace(/\/\s\*([\s\S]*?)\*\s\//g,"") // match / * abc * /
.trim() // after removing comments trim and:
.replace(/\n/g,'\\n').replace(/\r/g,'\\r') // replace new lines with escape codes. allows further eval() of the string, you put in the comment function: a quoted text but with new lines
)
else
return str
例子
var week=true,b=123;
var q = eval(extractFuncCommentString(function()/*!
// this is a comment
'select
/ * this
is a multiline
comment * /
a
,b // this is a comment
,c
from `table`
where b='+b+' and monthweek="'+(week?'w':'m')+'"
//+' where a=124
order by a asc
'
*/,4));
with cache: - 制作一个简单的模板函数,并保存函数:
var cache=;
function myfunction(week,a)
if(!cache.myfunction_sql1) eval('cache.myfunction_sql1=function(week,a)return ('+extractFuncCommentString(function()/*!
'select
/ * this
is a multiline
comment * /
a
,b // this is a comment
,c
from `table`
where b='+b+' and monthweek="'+(week?'w':'m')+'"
//+' where a=124
order by a asc
'*/,4)+')');
q=cache.myfunction_sql1(week,a);
console.log(q)
myfunction(true,1234)
简单文本(未评估):
//var cache=;
function myfunction2(week,a)
if(!cahce.myfunction_sql2) cahce.myfunction_sql2=extractFuncCommentString(function()/*!
some multiline text
with <html>
and a link://to.url
and a / * comment * /
*/,6);
q=cahce.myfunction_sql2;
console.log(q)
【讨论】:
【参考方案11】:ECMAscript 6,现在是标准,允许使用反引号(重音) 引用多行文字字符串。不幸的是,这不是 IE 11 支持,因此不应在大多数网站上使用。 (图片来源:Adam Katz,上图)
例子:
var str=
`Line 1
Line 2`;
【讨论】:
这其实是原题最正确的答案。从 IE 11.0.45 开始检查,它也可以在该浏览器上运行。以上是关于JavaScript HERE-doc 或其他大型引用机制?的主要内容,如果未能解决你的问题,请参考以下文章
无论 Django 中的模板更改(或发生其他外部问题)如何,在后台提取大型 zip 文件的最佳方法是啥?