Як перевірити, чи може користувач повернутися в історію браузера чи ні


Відповіді:


119

Коротка відповідь: Ви не можете.

Технічно існує точний спосіб, який би перевіряв майно:

history.previous

Однак це не спрацює. Проблема з цим полягає в тому, що в більшості браузерів це вважається порушенням безпеки і зазвичай просто повертається невизначеним .

history.length

Це властивість, яку запропонували інші ...
Однак довжина не працює повністю, оскільки вона не вказує, де в історії ви перебуваєте. Крім того, воно не завжди починається з однієї кількості. Наприклад, браузер, який не має цільової сторінки, починається з 0, тоді як інший браузер, який використовує цільову сторінку, запуститься з 1.

alt текст

Більшу частину часу додається посилання, яке дзвонить:

history.back();

або

 history.go(-1);

і просто очікується, що якщо ви не можете повернутися, то натискання на посилання нічого не призведе.


Це хороша інформація, але вона не вирішує проблему. Було б розробити якийсь код, який насправді працює в будь-якому браузері. Можливо код, який спочатку перевіряє браузер, який ви використовуєте.
Сантьяго Бендавід

5
Я говорю, що остаточної відповіді немає. Ви говорите про плюси і мінуси кожного підходу, але не про те, як отримати скрипт, який перевіряє, який браузер ви використовуєте, і умовно виконує той чи інший фрагмент коду.
Сантьяго Бендавід

Чи можу я знати, що ви маєте на увазі під "Проблема в тому, що в більшості браузерів це вважається порушенням безпеки" Інший користувач в іншій темі також зазначив, що можливість отримати історію браузера клієнта порушує безпеку, але не пояснює чому так. Хтось може навести якийсь приклад, що таке загрози безпеці?
Кевін Чандра

Веб-сайт не повинен мати можливість знати історію користувача, яка може включати непряму особисту інформацію. Сайт може використовувати функцію відстеження / cookie, щоб знати, що користувач робить на самому сайті, але їм, наприклад, не слід дозволяти розбиратися, в якому банку я користуюся, в яку школу ходять мої діти тощо. Тому браузери не дозволять отримати доступ до цієї власності
McAden

84

Є ще один спосіб перевірити - перевірити реферала. На першій сторінці зазвичай буде порожній референт ...

if (document.referrer == "") {
    window.close()
} else {
    history.back()
}

2
Довідник може бути прихованим з міркувань конфіденційності.
Корнель

11
Довідник завжди порожній, коли сторінка завантажується не посиланням, а введенням URL-адреси в адресний рядок або завантаженням закладок. Такі сторінки, безумовно, можуть мати історію, коли вкладка / вікно браузера раніше завантажувала іншу сторінку!
ygoe

1
Але застосовне рішення для навігації по багатосторінковому веб-сайту
День

36
Не працює, якщо відкрити вікно з target = "_ blank", щоб примусити нове вікно. Кнопка "Назад" у веб-переглядачі не працюватиме, але буде документ.
Довідник

3
Це не спрацює, якщо ви переходите зі захищеної сторінки (HTTPS) на незахищену сторінку (HTTP), оскільки це зніме реферала.
Кевін Бордерс

54

Мій код дозволяє веб-переглядачу повернутися на одну сторінку, і якщо це не вдасться, він завантажує резервну URL-адресу. Він також виявляє зміни хештегів.

Якщо кнопка "назад" не була доступна, резервна URL-адреса завантажується через 500 мс, тому у браузера є достатньо часу для завантаження попередньої сторінки. Завантаження резервного URL-адреси відразу після window.history.go(-1);цього призведе до використання браузера резервного URL-адреси, оскільки сценарій js ще не зупинився.

function historyBackWFallback(fallbackUrl) {
    fallbackUrl = fallbackUrl || '/';
    var prevPage = window.location.href;

    window.history.go(-1);

    setTimeout(function(){ 
        if (window.location.href == prevPage) {
            window.location.href = fallbackUrl; 
        }
    }, 500);
}

6
Я думаю, що це насправді несе в собі питання питання, чому людина піклується і що насправді можна зробити з цим надійно та послідовно.
Кріс Марісіч

1
Це спрацювало, поки я не взяв URL-адресу, де знаходиться кнопка "Назад", і вставив її в нову вкладку в хромі. Клацання на кнопку "Назад" призвело до надсилання на порожню вкладку. :(
karlingen

2
Це поведінка Chrome за замовчуванням. Ви "відвідали" сторінку, chrome://newtabі таким чином ви зможете повернутися в історію.
redelschaap

Будьте обережні з цим, оскільки при повільному підключенні до мережі ви будете регулярно потрапляти на резервний URL.
вийшов

14

Ось як я це зробив.

Я використовував подію " перед завантаженням ", щоб встановити булевий стан. Тоді я встановив тайм-аут, щоб спостерігати, чи вистрілив "передзавантаження".

var $window = $(window),
    $trigger = $('.select_your_link'),
    fallback = 'your_fallback_url';
    hasHistory = false;

$window.on('beforeunload', function(){
    hasHistory = true;
});

$trigger.on('click', function(){

    window.history.go(-1);

    setTimeout(function(){
        if (!hasHistory){
            window.location.href = fallback;
        }
    }, 200);

    return false;
});

Здається, працює в основних веб-переглядачах (поки перевірений FF, Chrome, IE11).


1
Це, безумовно, найкраща відповідь на питання. Ви можете легко замінити window.location.href = fallbackз , window.close()і це теж працює.
Вітані

13

Є фрагмент, який я використовую в своїх проектах:

function back(url) {
    if (history.length > 2) {
        // if history is not empty, go back:
        window.History.back();
    } else if (url) {
        // go to specified fallback url:
        window.History.replaceState(null, null, url);
    } else {
        // go home:
        window.History.replaceState(null, null, '/');
    }
}

FYI: я використовую History.js для управління історією браузера.


Навіщо порівнювати history.length з числом 2?

Тому що початкова сторінка Chrome вважається першим елементом в історії браузера.


Мало можливостей поведінки history.lengthта поведінки користувача:

  • Користувач відкриває нову порожню вкладку у браузері, а потім запускає сторінку. history.length = 2і ми хочемо back()в цьому випадку відключити , оскільки користувач перейде до порожньої вкладки.
  • Користувач відкриває сторінку в новій вкладці , натискаючи посилання десь раніше. history.length = 1і знову хочемо відключити back()метод.
  • І нарешті, користувач потрапляє на поточну сторінку після перезавантаження кількох сторінок . history.length > 2і тепер back()його можна ввімкнути.

Примітка. Я пропускаю випадок, коли користувач переходить на поточну сторінку після натискання посилання з зовнішнього веб-сайту без target="_blank".

Примітка 2: document.referrer порожня під час відкриття веб-сайту, ввівши його адресу, а також коли веб-сайт використовує ajax для завантаження підсторінок, тому я припинив перевірку цього значення в першому випадку.


Такий підхід спрацював для мене чудово. Я фактично зберігаю статичні резервні посилання на свої сторінки, які я використовую в резервній системі.
Грег Бласс

Але, якщо ви повернетесь назад, history.length не зміниться .. Отже, це не працює належним чином
Ciprian Mocanu

Ти маєш рацію, на жаль. Я використовую цей фрагмент лише зі структурою "один крок назад" ...
gregmatys

12

це, здається, робить трюк:

function goBackOrClose() {  

    window.history.back();
    window.close(); 

    //or if you are not interested in closing the window, do something else here
    //e.g. 
    theBrowserCantGoBack();

}

Виклик history.back (), а потім window.close (). Якщо браузер зможе повернутися в історію, він не зможе перейти до наступного оператора. Якщо він не зможе повернутися назад, він закриє вікно.

Однак зауважте, що якщо на сторінку було введено введення URL-адреси, Firefox не дозволить скрипту закрити вікно.


3
Я виявив, що це не працює, якщо я не використовую setTimeout із затримкою на кілька сотень мілісекунд або близько того, перш ніж спробувати запустити наступне твердження, інакше воно все одно запуститься після запуску history.back ()
Кен Фелінг

Я особисто цього не відчував, який це браузер?
xtrahelp.com

Я добре працював з функцією setTimeout у відповіді нижче. наприклад: setTimeout (функція () {window.close ()}, 400);
gilchris

2
window.close()багатьма сучасними браузерами вважається ризиком для безпеки. Деякі просто не дозволяють вам це зробити.
Руді Кершо

ви можете робити що завгодно після window.history.back (); window.close (); лише приклад
hariszaman

10

Будьте обережні, window.history.lengthоскільки вони також містять записи дляwindow.history.forward()

Таким чином, у вас може бути window.history.lengthбільше 1 запису, але жодних записів історії. Це означає, що нічого не відбувається, якщо ви стріляєтеwindow.history.back()


9

Ви не можете безпосередньо перевірити, чи використовується кнопка "назад". Ви можете подивитися history.length>0, але це буде справедливо, якщо перед поточною сторінкою також є сторінки. Ви можете бути впевнені лише в тому, що кнопка "назад" є непридатною, коли history.length===0.

Якщо це недостатньо добре, все, що ви можете зробити, - це зателефонувати, history.back()і якщо ваша сторінка все-таки буде завантажена, кнопка повернення недоступна! Звичайно , це означає , якщо кнопка назад знаходиться в наявності, ви просто переходите від сторінки. Вам не дозволяється скасовувати навігацію onunload, тому все, що ви можете зробити, щоб зупинити ситуацію, яка насправді відбувається, - це повернути щось із цього onbeforeunload, що призведе до появи великого дратівливого підказки. Це не варто.

Насправді це, як правило, дуже погана ідея робити щось з історією. Навігація по історії призначена для хромованого веб-переглядача, а не веб-сторінок. Додавання посилань «повернутися назад», як правило, викликає більше плутанини користувачів, ніж це варто.


2
щодо довжини - навіть тоді не у всіх браузерах. Деякі веб-переглядачі вважають поточну сторінку предметом історії та починають з 1. Потрібно включити виявлення браузера.
Макден

Насправді я думав, що це завжди 1! Я 0був мозком, я думав, що браузери завжди відповідатимуть 1чи більше. Виявляється, Opera і IE думають інакше - хороший улов.
bobince

1
"Навігація по історії призначена для хромованого веб-переглядача, а не веб-сторінок" - Погоджено
Брайан

5

history.lengthмарно, оскільки це не показує, чи може користувач повернутися в історію. Також різні браузери використовують початкові значення 0 або 1 - це залежить від браузера.

Робочим рішенням є використання $(window).on('beforeunload'події, але я не впевнений, що воно спрацює, якщо сторінка завантажується через ajax і використовує pushState для зміни історії вікон.

Тому я використовував наступне рішення:

var currentUrl = window.location.href;
window.history.back();
setTimeout(function(){
    // if location was not changed in 100 ms, then there is no history back
    if(currentUrl === window.location.href){
        // redirect to site root
        window.location.href = '/';
    }
}, 100);

Для мене працює так: функція goBackOrTo (targetUrl) {var currentUrl = window.location.href; window.history.go (-1); setTimeout (function () {// якщо місце розташування не було змінено за 800 мс, то повернення історії назад не буде, якщо (currentUrl === window.location.href) {// перенаправлення на кореневе вікно сайту.location.href = targetUrl; }}, 800); }
alfonx

2

Я придумав наступний підхід. Він використовує подію onbeforeunload, щоб виявити, чи починає браузер залишати сторінку чи ні. Якщо це не відбувається в певний проміжок часу, він просто переспрямується на резервну копію.

var goBack = function goBack(fallback){
    var useFallback = true;

    window.addEventListener("beforeunload", function(){
      useFallback = false;
    });

    window.history.back();

    setTimeout(function(){
        if (useFallback){ window.location.href = fallback; }
    }, 100); 
}

Цю функцію можна викликати за допомогою goBack("fallback.example.org").


1
Мені це найбільше подобається, я просто змінився windows.onbeforeunloadна слухача подій, window.addEventListener("beforeunload", function (event) { useFallback = false; });щоб він не перезаписав window.onbeforeunload.
MiChAeLoKGB

2

Спираючись на відповідь тут і тут . Думаю, більш переконлива відповідь - це просто перевірити, чи це нова сторінка на новій вкладці.

Якщо історії сторінки більше, ніж однієї, ми можемо повернутися до попередньої сторінки. Якщо ні, вкладка - це нещодавно відкрита вкладка, і нам потрібно створити нову вкладку.

Інакше, на відповіді, пов’язані з нами, ми не перевіряємо наявність, referrerоскільки нова вкладка все ще матиме референс.

if(1 < history.length) {
    history.back();
}
else {
    window.close();
}

1
Дякую. Ти врятував мені день :).
Біджай Ядав

1

Є ще одне, майже ідеальне рішення, взяте з іншої відповіді :

if( (1 < history.length) && document.referrer ) {
    history.back();
}
else {
    // If you can't go back in history, you could perhaps close the window ?
    window.close();
}

Хтось повідомив, що це не працює під час використання, target="_blank"але, здається, працює для мене в Chrome.


0

у браузера є кнопка "назад" і "вперед". Я підходжу до цього питання. але це вплине на переадресацію браузера та призведе до помилок у деяких браузерах.

Це працює так: Якщо веб-переглядач відкриє нову URL-адресу, яка ніколи не відкривалася, history.length зростатиме.

так що ви можете змінювати хеш, як

  location.href = '#__transfer__' + new Date().getTime() 

щоб отримати ніколи не показаний URL, тоді history.length отримає справжню довжину.

  var realHistoryLength = history.length - 1

але, це не завжди працює добре, і я не знаю чому, особливо коли авто-стрибок швидко стрибає.


0

Я намагався знайти рішення, і це найкраще, що я міг отримати (але це чудово, і це найпростіше рішення, яке я знайшов навіть тут).

У моєму випадку я хотів повернутися до історії за допомогою кнопки "назад", але якщо перша сторінка, яку відкрив користувач, була підсторінкою мого додатка, вона повернеться на головну сторінку.

Рішення полягало в тому, що, як тільки програма завантажується, я просто робив заміну в історії історії:

history.replaceState( {root: true}, '', window.location.pathname + window.location.hash)

Таким чином, мені просто потрібно перевірити, history.state.rootперш ніж повернутися назад. Якщо це правда, замість цього я замінюю історію:

if(history.state && history.state.root)
    history.replaceState( {root: true}, '', '/')
else
    history.back() 

Я не думаю, що є інший хороший випадок використання. Можливо, це не гарна ідея. Якщо ви хочете перевірити історію поза додатком.
Maxwell sc

-1
var fallbackUrl = "home.php";
if(history.back() === undefined)
    window.location.href = fallbackUrl;

це виглядає дуже просто ?! це тестується на різних браузерах?
benzkji

в Chrome history.back()є undefinedлише на порожній сторінці вкладки
gregmatys

-2

Рішення

'use strict';
function previousPage() {
  if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
    window.history.back();
  }
}

Пояснення

window.location.pathnameдасть вам поточний URI. Наприклад https://domain/question/1234/i-have-a-problem, дасть /question/1234/i-have-a-problem. Додаткову інформацію див. У документації про window.location .

Далі, заклик до split()дасть нам усі фрагменти цього URI. тому якщо ми візьмемо попередній URI, у нас вийде щось подібне ["", "question", "1234", "i-have-a-problem"]. Додаткову інформацію див. У документації про String.prototype.split () .

Тут заклик до filter()того, щоб відфільтрувати порожній рядок, породжений зворотною косою рисою. В основному він поверне лише URI фрагмента, який має довжину більше 1 (не порожній рядок). Тож у нас було б щось подібне ["question", "1234", "i-have-a-question"]. Це могло бути записане так:

'use strict';
window.location.pathname.split('/').filter(function(fragment) {
  return fragment.length > 0;
});

Для отримання додаткової інформації див документацію про Array.prototype.filter () та завдання Destructuring .

Тепер, якщо користувач намагається повернутися назад під час роботи https://domain/, ми не будемо запускати if-операцію, і так не window.history.back()будемо запускати метод, щоб користувач залишився на нашому веб-сайті. Ця URL-адреса буде еквівалентною []довжині 0та 0 > 0помилковою. Отже, мовчки провалюються. Звичайно, ви можете щось зареєструвати або виконати іншу дію, якщо хочете.

'use strict';
function previousPage() {
  if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
    window.history.back();
  } else {
    alert('You cannot go back any further...');
  }
}

Обмеження

Звичайно, це рішення не працюватиме, якщо браузер не підтримує API історії . Перевірте документацію, щоб дізнатися більше про неї, перш ніж використовувати це рішення.


-5

Я не впевнений, чи це працює, і це абсолютно не перевірено, але спробуйте:

<script type="text/javascript">

    function goBack() {
        history.back();
    }

    if (history.length > 0) { //if there is a history...
        document.getElementsByTagName('button')[].onclick="goBack()"; //assign function "goBack()" to all buttons onClick
    } else {
        die();
    }
</script>

І десь у HTML:

<button value="Button1"> //These buttons have no action
<button value="Button2">

Редагувати:

Ви також можете зробити дослідження, які браузери підтримують функцію "назад" (я думаю, що вони все роблять) і використовувати стандартний об'єкт виявлення браузера JavaScript, знайдений та ретельно описаний на цій сторінці . Тоді ви можете мати дві різні сторінки: одну для "хороших браузерів", сумісних із кнопкою "Назад", і одну для "поганих браузерів", яка дозволяє їм оновити веб-переглядач.


2
history.backє функцією. Ви хочете перевірити, чи history.length > 0повертається він зhistory.back()
піксельним кодером

3
Також []у NodeList немає сенсу, і ви не можете призначити рядок обробнику подій.
bobince

-8

Перевірте, чи window.history.lengthдорівнює 0.


6
Це не гарний спосіб, оскільки history.length не говорить вам, де ви перебуваєте в історії ...
Ron Reiter

@Ron Reiter: Так, я думаю, що найкраща відповідь та інші коментарі до цього питання вже встановили, що понад рік тому ...
Крістіан Санчес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.