【问题标题】:Can you load jQuery contextMenu with JavaScript?你能用 JavaScript 加载 jQuery contextMenu 吗?
【发布时间】:2018-09-09 09:53:42
【问题描述】:

我想用 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);
            }
        }
    }
});

【问题讨论】:

    标签: javascript jquery jquery-plugins


    【解决方案1】:

    简答

    问题是<script>s 加载是异步操作。
    而且因为您是动态插入这些脚本,所以当您执行 $.contextMenu 指令时,还没有加载必要的脚本。

    说明

    当您静态在页面<head>中使用<script>标签定义多个脚本时,浏览器将并行获取它们并尽快执行它们,保持它们的顺序(并阻止对页面的进一步解析)。

    但在您的情况下,您是动态<script>标签一一插入到页面<head>中,这意味着:

    • 这些脚本的执行顺序未知(一获取就执行)
    • 在您的<script>s 加载时继续执行,因此$.contextMenu 在您的<script>s 确实加载之前执行。

    为了说明这一点,我在$.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 处理脚本加载。

    【讨论】:

      猜你喜欢
      • 2021-09-27
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 2019-01-23
      • 2020-11-01
      • 2011-01-24
      • 1970-01-01
      相关资源
      最近更新 更多