VueJS:如何从字符串动态执行Javascript?
我正在使用VueJS编写一个网站,它允许(选定的)用户添加在页面加载时自动执行的脚本。以下是用户可能上载的示例文本:VueJS:如何从字符串动态执行Javascript?,javascript,vue.js,Javascript,Vue.js,我正在使用VueJS编写一个网站,它允许(选定的)用户添加在页面加载时自动执行的脚本。以下是用户可能上载的示例文本: <script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.0.5/howler.js"></script> <script> var sound = new howler.Howl({ src: ['./sample.mp3'] )}.play();
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.0.5/howler.js"></script>
<script>
var sound = new howler.Howl({
src: ['./sample.mp3']
)}.play();
</script>
问题不是Vue问题,而是JavaScript问题 我假设您已经理解了允许用户运行JavaScript的安全含义;这很少是个好主意。像JSFiddle这样的网站成功地做到了这一点,但是要使其安全,需要大量的工作和理解,所以如果你不能100%确定你在做什么,那么正如@WaldemarIce所说,你不应该这样做 好的,在警告结束后,您需要做一些事情来实现这一点: 1) 加载外部脚本:
loadScripts() {
return new Promise(resolve => {
let scriptEl = document.createElement("script");
scriptEl.src = "https://cdnjs.cloudflare.com/ajax/libs/howler/2.0.5/howler.js";
scriptEl.type = "text/javascript";
// Attach script to head
document.getElementsByTagName("head")[0].appendChild(scriptEl);
// Wait for tag to load before promise is resolved
scriptEl.addEventListener('load',() => {
resolve();
});
});
}
在这里,我只是将外部脚本附加到文档的头部,并附加一个加载事件,该事件在加载时解析
2) 现在我们已经加载了外部脚本,我们可以执行脚本的其余部分。您需要去掉脚本标记,以便执行以下操作:
executeScript() {
// remove script tags from string (this has been declared globally)
let script = string.replace(/<\/?script>/g,"")
eval(script)
}
我将让您从用户输入中提取要加载的外部脚本,但这里有一个JSFiddle:问题不是Vue问题,而是JavaScript问题 我假设您已经理解了允许用户运行JavaScript的安全含义;这很少是个好主意。像JSFiddle这样的网站成功地做到了这一点,但是要使其安全,需要大量的工作和理解,所以如果你不能100%确定你在做什么,那么正如@WaldemarIce所说,你不应该这样做 好的,在警告结束后,您需要做一些事情来实现这一点: 1) 加载外部脚本:
loadScripts() {
return new Promise(resolve => {
let scriptEl = document.createElement("script");
scriptEl.src = "https://cdnjs.cloudflare.com/ajax/libs/howler/2.0.5/howler.js";
scriptEl.type = "text/javascript";
// Attach script to head
document.getElementsByTagName("head")[0].appendChild(scriptEl);
// Wait for tag to load before promise is resolved
scriptEl.addEventListener('load',() => {
resolve();
});
});
}
在这里,我只是将外部脚本附加到文档的头部,并附加一个加载事件,该事件在加载时解析
2) 现在我们已经加载了外部脚本,我们可以执行脚本的其余部分。您需要去掉脚本标记,以便执行以下操作:
executeScript() {
// remove script tags from string (this has been declared globally)
let script = string.replace(/<\/?script>/g,"")
eval(script)
}
我将让您从用户输入中提取要加载的外部脚本,但这里有一个JSFiddle:我最近遇到了这个问题,不得不扩展@craig_h的答案。下面的示例允许以字符串形式发送完整的嵌入代码(HTML元素以及脚本和内联JS)。这是在使用
从“Vue”导入Vue;
导出默认值{
...
方法:{
克隆属性(元素,源节点){
让attr;
让attributes=Array.prototype.slice.call(sourceNode.attributes);
while(attr=attributes.pop()){
setAttribute(attr.nodeName、attr.nodeValue);
}
}
},
安装的(){
if(this.embedString&&this.embedString.length>0)
{
//将API中给出的代码解析到一个新的DOM中,以便我们可以轻松地对其进行操作
var parser=新的DOMParser();
var htmlDoc=parser.parseFromString(this.embedString,'text/html');
//获取新DOM主体的内容并循环。
//我们希望将所有HTML元素添加到页面并运行/加载所有JS
var kids=[…htmlDoc.body.children];
让len=kids.length;
对于(变量i=0;i
我最近遇到了这个问题,不得不扩展@craig_h的答案。下面的示例允许以字符串形式发送完整的嵌入代码(HTML元素以及脚本和内联JS)。这是在使用
从“Vue”导入Vue;
导出默认值{
...
方法:{
克隆属性(元素,源节点){
让attr;
让attributes=Array.prototype.slice.call(sourceNode.attributes);
while(attr=attributes.pop()){
setAttribute(attr.nodeName、attr.nodeValue);
}
}
},
安装的(){
if(this.embedString&&this.embedString.length>0)
{
//将API中给出的代码解析到一个新的DOM中,以便我们可以轻松地对其进行操作
var parser=新的DOMParser();
var htmlDoc=parser.parseFromString(this.embedString,'text/html');
//获取新DOM主体的内容并循环。
//我们希望将所有HTML元素添加到页面并运行/加载所有JS
var kids=[…htmlDoc.body.children];
让len=kids.length;
对于(变量i=0;i<div ref="htmlDump"></div>
<script>
import Vue from "vue";
export default {
...
methods: {
cloneAttributes(element, sourceNode) {
let attr;
let attributes = Array.prototype.slice.call(sourceNode.attributes);
while(attr = attributes.pop()) {
element.setAttribute(attr.nodeName, attr.nodeValue);
}
}
},
mounted(){
if(this.embedString && this.embedString.length > 0)
{
//Parse the code given from the API into a new DOM so we can easily manipulate it
var parser = new DOMParser();
var htmlDoc = parser.parseFromString(this.embedString, 'text/html');
//Get the contents of the new DOM body and loop through.
//We want to add all HTML elements to the page and run / load all JS
var kids = [...htmlDoc.body.children];
let len = kids.length;
for (var i = 0; i < len; i++) {
var item = kids[i];
if(item.tagName == "SCRIPT")
{
//If we have a 'src' attribute then we're loading in a script
if(item.hasAttribute('src'))
{
//Create a new element within the current doc to trigger the script load
let scriptEl = document.createElement("script");
//Copy all attributes from the source element to the new one
this.cloneAttributes(scriptEl, item);
//Attach script to the DOM to trigger it to load
this.$refs.htmlDump.appendChild(scriptEl);
} else {
//if we don't have a 'src' attribute then we have some code to run
eval(item.innerText);
}
} else{
this.$refs.htmlDump.appendChild(item);
}
}
}
}
...
}
</script>