如何在jQuery中通过AJAX检测URL的变化而无需重新加载页面?

8

我有一个用户脚本(适用于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:

赏金奖励

请提供一个不加载外部库的工作解决方案(我想知道我错过了什么,而不是把它放在黑匣子中),并使用事件解决该问题(不能使用基于间隔的解决方案)。如果事件不能使用,请提供正确的解决方案和不触发事件的原因。


这有帮助吗? https://dev59.com/4Gw15IYBdhLWcg3wzO1_ - Prophecies
你在 AJAX 调用中传递的类型参数是什么? - Abhishek Dhanraj Shahdeo
也许在目标场景中这根本不起作用,但是是否有可能插入一个带有!important注释的CSS行 $('head').append("<style type='text/css'> #start-button{ float: left !important; margin-right: 10em; !important}</style>"); - Me.Name
是的,我有时会做这样的事情。通常,这是一个错误,你可以在CSS中更具体地描述,如果失败了,你可以使用jQuery定位到它并删除有问题的选择器。然而,它可能会被网站以编程方式注入,而且不一定只发生一次 - 因此有时在用户脚本中确实很重要。 - roberto tomás
5个回答

3

要改变Duolingo使用的URL,可以使用history.pushstate方法。我建议你查看类似问题的galambalazs答案

以下是他的代码:

(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);

这只是一半正确的。当从练习题的主列表转到练习时,它可以工作。但是当从一个练习结束后继续,然后进入下一个练习时,它就无法工作了。 - roberto tomás
也许我们在这里漏掉了什么。您能否执行以下代码并查看浏览器控制台 $('body').on('change',function(){console.warn('App changed')}); - sulest
「$('body').on('change',function(){console.warn('应用程序已更改')});」 「[<body class=​"global-en compact-enabled" lang=​"en" style=​"overflow:​ auto;​">​…​</body>​]」 最后一行是来自我的脚本。尽管它实际上并没有更改CSS! - roberto tomás
实际上,即使它改变了CSS,结果看起来也是一样的:$('body').on('change', function(){console.warn('App changed')}); [<body class=​"global-en compact-enabled" lang=​"en">​…​</body>​] e365420…-duolingo.js:3 Duolingo正在招聘软件工程师:https://www.duolingo.com/jobs /gcm-service-worker.js:1 GET https://www.duolingo.com/gcm-service-worker.js net::ERR_FILE_EXISTS VM6336:55 Tampermonkey脚本:写入CSS更改 - roberto tomás
代码只是为了向您展示是否在每个页面更改时显示更改日志警告。我发现在某些情况下URL会更改,但并不总是。您是否尝试在body change监听器内运行函数,如下所示:$('body').on('change', function(){ style_duolingo() }); 如果这涵盖了您另外50%的“正常工作”,请将其与历史记录pushstate结合使用。 - sulest
显示剩余2条评论

1
像这样使用它:
jQ(document).ready(function(){

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

});

2
这似乎是答案,但实际上它并不起作用。 - roberto tomás

1

如果你只是调整样式,最好使用 Stylish Chrome 扩展程序,它允许你篡改 CSS。然后你可以添加

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

注意,@-moz-document 遵循用户样式约定,并可导入 Chrome。实际上,已经有一些针对Duolingo发布的用户样式了 :)


我曾经使用过 Stylish 插件,我非常喜欢它,但后来我改用用户脚本默认加载 jQuery,因为它更加灵活。我离开 Stylish 的唯一原因是,在当时,你不能轻松地指定规则不匹配 Stylish 显示在页面中的 GUI 元素。不过我理解(并且我认为我可以从你的例子中看到),他们最终修复了这个问题。 - roberto tomás

0

似乎还有一个插件,如果window上的hashchange事件失败,则允许相同的操作。


0
您可以通过每秒检查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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接