【问题标题】:How to detect a url change through AJAX without reload in jQuery?如何通过 AJAX 检测 url 更改而不在 jQuery 中重新加载?
【发布时间】:2016-06-09 21:07:08
【问题描述】:

我有一个用户脚本(用于 Chrome),我用它来为我格式化 duolingo 的练习页面。它只是应用了一行 css

jQ(document).ready(function(){
    jQ('#start-button').css({"float": "left", "margin-right": "10em"});
});

当我第一次访问该页面时,这工作得很好。但是他们使用 Ajax 来避免页面重新加载。并且 url 确实发生了变化,所以如果我检测到这一点,我可以刷新 css 更改并且不会丢失此站点导航模式的格式。

有人碰巧知道检测它的好方法吗?

编辑:实现几个最初指出的流行解决方案的完整用户脚本(这是行不通的):

// ==UserScript==
// @name         duolingo
// @namespace    http://your.homepage/
// @version      0.1
// @description  reformat /skills to not start timed practice by default
// @author       You
// @include      /^https?\:\/\/www\.duolingo\.com\/(skill|practice)?\/?.*/
// @require      https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js
// @grant        none
// ==/UserScript==

window.jQ=jQuery.noConflict(true);

jQ(document).ready(function(){
    style_duolingo();
});
jQ(window).bind('hashchange', function() {
    style_duolingo();
});
jQ(document).ajaxComplete(function() {
    style_duolingo();
});


function style_duolingo() {
    jQ('#start-button').css({"float": "left", "margin-right": "10em"});
    console.log("Tampermonkey script: wrote css change");
}

编辑#2:

赏金奖励

请提供一个不加载外部库的工作解决方案(我想知道我缺少什么,而不是将其保存在黑匣子中),并使用事件解决问题(没有基于间隔的解决方案)。如果事件(奇怪)无法使用,请提供更正解决方案以及事件未触发的原因。

【问题讨论】:

  • 您在 AJAX 调用中传递的类型参数是什么?
  • 也许这在目标场景中根本不起作用,但是是否可以插入带有 !important 注释 $('head').append("<style type='text/css'> #start-button{ float: left !important; margin-right: 10em; !important}</style>"); 的 css 行?
  • 是的,我经常这样做。通常,这是一个错误,你可以在你的 CSS 中更具体,如果做不到这一点,你可以在使用 jQuery 找到有问题的选择器后删除它。但是,它可以由站点以编程方式注入,并且不必只发生一次 - 所以有时它在用户脚本中确实很重要。

标签: jquery ajax


【解决方案1】:

您可以通过每秒检查 url 并查看是否与之前的 url 匹配来检查任何 url 更改。它可能看起来像这样:

var oldURL = window.location.url;
var newURL = oldURL;
window.setInterval(function(){
    newURL = window.location.url;
    if(oldURL !== newURL){
        //the URL has changed
        oldURL = newURL; //to prevent the above from continuously firing
    }
}, 1000);// checks every 1000 ms (1s)

【讨论】:

    【解决方案2】:

    由于您只是在调整样式,因此最好使用允许您篡改 css 的 Stylish Chrome 扩展程序。然后你会添加

    @-moz-document domain("www.duolingo.com") {
        #start-button {
            float: left;
            margin-right: 10em;
        }
    }
    

    注意@-moz-document 遵循用户样式约定,可导入 Chrome。实际上已经有几个published userstyles for duolingo :)

    【讨论】:

    • 我曾经使用时尚——我非常喜欢它,但我已经切换到默认通过用户脚本在我的页面中加载 jquery,因为它更灵活。我离开时尚的唯一原因是,在当时,你不能轻易地指定规则不应该与时尚页面中显示的 gui 元素相匹配。我理解(并且认为我可以在您的示例中看到)他们最终确实解决了这个问题。
    【解决方案3】:

    要更改 url Duolingo 使用 history.pushstate。我推荐你galambalazs answer to similar question

    这是他的代码:

    (function(history){
        var pushState = history.pushState;
        history.pushState = function(state) {
        if (typeof history.onpushstate == "function") {
            history.onpushstate({state: state});
        }
    
        //Custom code here
        style_duolingo();
    
        return pushState.apply(history, arguments);
    }
    })(window.history);
    

    【讨论】:

    • 这是对的。从练习练习的主要列表转到练习时,它会起作用。从练习结束继续,然后进入下一个练习时,它不起作用。
    • 也许我们在这里遗漏了一些东西。您可以触发以下代码并查看浏览器控制台$('body').on('change', function(){console.warn('App changed')});
    • $('body').on('change', function(){console.warn('App changed')}); [<body class=​"global-en compact-enabled" lang=​"en" style=​"overflow:​ auto;​">​…​</body>​] VM1999:51 Tampermonkey script: wrote css change 最后一行来自我的脚本。尽管它实际上并没有改变 CSS!
    • 实际上,即使它确实更改了 CSS,结果看起来也是一样的:$('body').on('change', function(){console.warn('App changed')});[<body class=​"global-en compact-enabled" lang=​"en">​…​</body>​]e365420…-duolingo.js:3 Duolingo is hiring software engineers: https://www.duolingo.com/jobs/gcm-service-worker.js:1 GET https://www.duolingo.com/gcm-service-worker.js net::ERR_FILE_EXISTSVM6336:55 Tampermonkey script: wrote css change
    • 该代码仅用于向您显示每次页面更改时是否显示更改日志警告。我看到在某些情况下 URL 会发生变化,但并非总是如此。您是否尝试像这样在主体更改侦听器中运行您的函数:$('body').on('change', function(){ style_duolingo() }); 如果这涵盖了您其他 50% 的“正常工作”,请将其与历史推送状态结合起来
    【解决方案4】:

    像这样使用它:

    jQ(document).ready(function(){
    
        jQ(window).bind('hashchange', function() {
            jQ('#start-button').css({"float": "left", "margin-right": "10em"});
        });
    
    });
    

    【讨论】:

    • 这似乎应该是答案,但实际上它不起作用。
    【解决方案5】:

    如果window 上的hashchange 事件失败,似乎还有一个plugin 允许这样做。

    【讨论】:

      猜你喜欢
      • 2013-04-19
      • 1970-01-01
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-28
      • 1970-01-01
      • 2019-01-15
      相关资源
      最近更新 更多