你能用 JavaScript 加载 jQuery contextMenu 吗?
Can you load jQuery contextMenu with JavaScript?
我想用 JavaScript 加载一个 jQuery 插件 jQuery contextMenu。
我尝试在 Chrome 开发人员工具控制台上执行 JavaScript 脚本并收到错误 VM4631:1 Uncaught TypeError: $.contextMenu is not a function
。
// setting up jQuery contextMenu Plugin
function dynamicallyLoadScript(url) {
var script = document.createElement("script");
script.src = url;
document.head.appendChild(script);
}
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js')
var link = document.createElement( "link" );
link.href = "https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.contextMenu.min.css" ;
link.type = "text/css";
link.rel = "stylesheet";
link.media = "screen,print";
document.getElementsByTagName( "head" )[0].appendChild( link );
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.contextMenu.min.js')
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.ui.position.js')
// testing
$.contextMenu({
selector: '#post-868 > div > header > h2 > a',
items: {
copy: {
name: "Copy",
callback: function(key, opt){
alert("Clicked on " + key);
}
}
}
});
简答
问题是<script>
的加载是一个异步操作。
并且因为您正在动态插入这些脚本,所以当您的 $.contextMenu
指令被执行时,还没有加载必要的脚本。
说明
当您静态在页面<script>
标签中定义多个脚本时<head>
,浏览器将并行获取它们并尽快执行它们可能,维持它们的顺序(并阻止进一步解析页面)。
但在你的情况下,你是动态地将<script>
标签一个接一个地插入页面<head>
,这意味着:
- 这些脚本的执行顺序未知(一获取就执行)
- 在您的
<script>
加载时继续执行,因此 $.contextMenu
在您的 <script>
确实加载之前执行。
为了说明这一点,我在 $.contextMenu
指令之前添加了一个 console.log
,并在 dynamicallyLoadScript
函数中添加了一个 console.time/timeEnd
:
function dynamicallyLoadScript(url) {
var script = document.createElement("script");
script.src = url;
// Print log on script loaded
script.onload = () => { console.timeEnd(url); };
console.time(url);
document.head.appendChild(script);
}
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js')
var link = document.createElement( "link" );
link.href = "https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.contextMenu.min.css" ;
link.type = "text/css";
link.rel = "stylesheet";
link.media = "screen,print";
document.getElementsByTagName( "head" )[0].appendChild( link );
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.contextMenu.min.js')
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.ui.position.js')
console.log('Calling $.contextMenu');
$.contextMenu({
selector: '#post-868 > div > header > h2 > a',
items: {
copy: {
name: "Copy",
callback: function(key, opt){
alert("Clicked on " + key);
}
}
}
});
我不知道你为什么要这样加载脚本。
如果您添加 script.async = false;
,您的脚本将以正确的顺序加载,但这不会阻止 $.contextMenu
首先执行。
我建议您看看 this great HTML5 Rocks article 处理脚本加载。
我想用 JavaScript 加载一个 jQuery 插件 jQuery contextMenu。
我尝试在 Chrome 开发人员工具控制台上执行 JavaScript 脚本并收到错误 VM4631:1 Uncaught TypeError: $.contextMenu is not a function
。
// setting up jQuery contextMenu Plugin
function dynamicallyLoadScript(url) {
var script = document.createElement("script");
script.src = url;
document.head.appendChild(script);
}
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js')
var link = document.createElement( "link" );
link.href = "https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.contextMenu.min.css" ;
link.type = "text/css";
link.rel = "stylesheet";
link.media = "screen,print";
document.getElementsByTagName( "head" )[0].appendChild( link );
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.contextMenu.min.js')
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.ui.position.js')
// testing
$.contextMenu({
selector: '#post-868 > div > header > h2 > a',
items: {
copy: {
name: "Copy",
callback: function(key, opt){
alert("Clicked on " + key);
}
}
}
});
简答
问题是<script>
的加载是一个异步操作。
并且因为您正在动态插入这些脚本,所以当您的 $.contextMenu
指令被执行时,还没有加载必要的脚本。
说明
当您静态在页面<script>
标签中定义多个脚本时<head>
,浏览器将并行获取它们并尽快执行它们可能,维持它们的顺序(并阻止进一步解析页面)。
但在你的情况下,你是动态地将<script>
标签一个接一个地插入页面<head>
,这意味着:
- 这些脚本的执行顺序未知(一获取就执行)
- 在您的
<script>
加载时继续执行,因此$.contextMenu
在您的<script>
确实加载之前执行。
为了说明这一点,我在 $.contextMenu
指令之前添加了一个 console.log
,并在 dynamicallyLoadScript
函数中添加了一个 console.time/timeEnd
:
function dynamicallyLoadScript(url) {
var script = document.createElement("script");
script.src = url;
// Print log on script loaded
script.onload = () => { console.timeEnd(url); };
console.time(url);
document.head.appendChild(script);
}
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js')
var link = document.createElement( "link" );
link.href = "https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.contextMenu.min.css" ;
link.type = "text/css";
link.rel = "stylesheet";
link.media = "screen,print";
document.getElementsByTagName( "head" )[0].appendChild( link );
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.contextMenu.min.js')
dynamicallyLoadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.0/jquery.ui.position.js')
console.log('Calling $.contextMenu');
$.contextMenu({
selector: '#post-868 > div > header > h2 > a',
items: {
copy: {
name: "Copy",
callback: function(key, opt){
alert("Clicked on " + key);
}
}
}
});
我不知道你为什么要这样加载脚本。
如果您添加 script.async = false;
,您的脚本将以正确的顺序加载,但这不会阻止 $.contextMenu
首先执行。
我建议您看看 this great HTML5 Rocks article 处理脚本加载。