Як я можу видалити хеш розташування, не викликаючи прокручування сторінки?


77

Чи можна видалити хеш, window.locationне змушуючи сторінку переходити до прокрутки до початку? Мені потрібно мати можливість змінити хеш, не викликаючи стрибків.

У мене є таке:

$('<a href="#123">').text('link').click(function(e) {
  e.preventDefault();
  window.location.hash = this.hash;
}).appendTo('body');

$('<a href="#">').text('unlink').click(function(e) {
  e.preventDefault();
  window.location.hash = '';
}).appendTo('body');

Дивіться приклад у прямому ефірі тут: http://jsbin.com/asobi

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

Але коли користувач натискає кнопку « від’єднати », тег has видаляється, а прокрутка сторінки перескакує вгору. Мені потрібно видалити хеш без цього побічного ефекту.


Дозвольте мені здогадатися: ваш клієнт вважає хеш потворним і забруднює приємну та чисту URL-адресу, яка читається: http: // www.example.com/ (без пробілів)?
anddoutoi

Гарна здогадка, але ні. У мене є модальні вікна, які можна забронювати на основі хеш-адрес, і коли користувач закриває вікно, хеш повинен перейти.
Девід Хеллсінг,

1
Мені відомо, що цьому питанню вже майже 2 роки, але цей коментар може допомогти майбутньому читачеві. Якщо ви дійсно хочете видалити хеш, ви можете змінити URL-адресу за допомогою history.pushState (). developer.mozilla.org/en/DOM/…
двозначна

@joshli, на жаль, це не спрацює IE9.
Цукімото Міцумаса

Відповіді:


97

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

<a href="#A4J2S9F7">No jumping</a>

або

<a href="#_">No jumping</a>

"#"сам по собі еквівалентний "_top"тому, що таким чином викликає прокручування до початку сторінки


12
Не оптимально, але досить добре. Я використовував '# /' з тим самим результатом.
Девід Хеллсінг

window.location.hash = (new_hash === '') ? '_' : new_hash;
тестер

Не задоволений цим рішенням, як щодо: stackoverflow.com/questions/19728020/…
Стівен

21
Я використовуюwindow.location.hash = "💩";
Aeyoun

37

Я використовую наступне на кількох сайтах, СТРИМАННЯ СТОРІНКИ НІ!

Приємний чистий адресний рядок для браузерів, зручних для HTML5, і просто # для старих браузерів.

$('#logo a').click(function(e){
    window.location.hash = ''; // for older browsers, leaves a # behind
    history.pushState('', document.title, window.location.pathname); // nice and clean
    e.preventDefault(); // no page reload
});

12
history.replaceStateможе бути кращим, оскільки натискання назад повернеться до останньої дійсної URL-адреси.
орладе

Також слід зазначити, що цей код встановлює дві зміни в історії навігації. Результат полягає в тому, що коли користувач натискає кнопку "Назад", його спочатку перенаправляють через [url] #, а потім йому знадобиться другий клік, щоб приземлитися на [url] без #. Якщо ви розробляєте досвід роботи з кнопкою "Назад", розгляньте умовний підхід, щоб не встановлювати стан двічі.
Вінні Келлі

18

Хеш-властивість window.location є дурним кількома способами. Це одна з них; інший - це має різні значення get і set:

window.location.hash = "hello";  // url now reads *.com#hello
alert(window.location.hash);   // shows "#hello", which is NOT what I set.
window.location.hash = window.location.hash; // url now reads *.com##hello

Зверніть увагу, що встановлення властивості хешу на '' також видаляє позначку хешу; ось що переспрямовує сторінку. Щоб встановити значення хеш-частини URL-адреси на '', залишивши знак хешу і, отже, не оновлюючи, напишіть це:

window.location.href = window.location.href.replace(/#.*$/, '#');

Неможливо повністю видалити позначку хешу, коли вона встановлена, не оновлюючи сторінку.

ОНОВЛЕННЯ 2012:

Як зазначили Blazemonger та thinkdj, технологія вдосконалилася. Деякі браузери дозволяють очистити цей хештег, а деякі - ні. Щоб підтримати обидва, спробуйте щось на зразок:

if ( window.history && window.history.pushState ) { 
    window.history.pushState('', '', window.location.pathname) 
} else { 
    window.location.href = window.location.href.replace(/#.*$/, '#'); 
}

2
Неправда. Браузери, які підтримують, window.historyдозволяють вам робити саме це.
Blazemonger

@Blazemonger Правда! Ви можете використовувати history.pushState ('', document.title, window.location.pathname);
Діпак Томас

Але знову ж таки, цей коментар був зроблений у лютому 10 року, і браузери почали підтримувати pushstates десь приблизно в середині 2011 року
Діпак Томас

Наведений вище код не зберігає рядок запиту. Використанняwindow.history.pushState('', '', window.location.pathname + window.location.search);
dipole_moment

3

Це стара публікація, але я хотів поділитися своїм рішенням Всі посилання в моєму проекті, які обробляються JS, мають атрибут href = "#_ js" (або будь-яке ім'я, яке ви хочете використовувати лише для цих цілей), та на ініціалізації сторінки Я згоден:

$('body').on('click.a[href="#_js"]', function() {
    return false;
});

Це зробить трюк


2

Якщо встановити window.location.hash для порожнього або неіснуючого імені прив'язки, сторінка завжди буде змушена переходити вгору. Єдиний спосіб запобігти цьому - захопити позицію прокрутки вікна і знову встановити його в це положення після зміни хешу.

Це також змусить перефарбувати сторінку (не можу цього уникнути), хоча, оскільки вона виконується в одному js-процесі, вона не буде стрибати вгору / вниз (теоретично).

$('<a href="#123">').text('link').click(function(e) {
    e.preventDefault();
    window.location.hash = this.hash;
}).appendTo('body');

$('<a href="#">').text('unlink').click(function(e) {
    e.preventDefault();
    var pos = $(window).scrollTop(); // get scroll position
    window.location.hash = '';
    $(window).scrollTop(pos); // set scroll position back
}).appendTo('body');

Сподіваюся, це допомагає.


1
не зовсім коректно ... встановивши хеш на "" прокрутку до початку, але якщо немає іменованого прив'язки або елемента з відповідним idатрибутом, браузер не буде прокручувати.
scunliffe

1

Я не впевнений, що це дасть бажаний результат, спробуйте:

$('<a href="#">').text('unlink').click(function(e) {
    e.preventDefault();
    var st = parseInt($(window).scrollTop())
    window.location.hash = '';
    $('html,body').css( { scrollTop: st });  
});

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


1
це працює для мене, за винятком того, що я використовую $(window).scrollTop(st)замість.css()
Thomas Joulin

Спробував це, оскільки мені потрібно змінити хеш на існуючий #id. Все працює добре, але коли я намагаюся прокручувати за допомогою миші, після зміни хешу прокрутка стрибає до нуля. Будь-які ідеї щодо того, що може спричинити це?
lucascaro

1

Ви пробували return false;обробник подій? jQuery робить щось особливе, коли ви робите це, схоже на, але AFAIK більш вражаюче, ніж e.preventDefault.


2
return false;у jQuery та у власних обробниках подій у сумісних браузерах еквівалентно e.preventDefault(); e.stopPropagation();. Не думаю, що зупинка розмноження допоможе у вирішенні цього питання.
Джессі Халлетт

0

Сподіваюся, це допомагає

html

<div class="tabs">
  <ul>
    <li><a href="#content1">Tab 1</a></li>
    <li><a href="#content2">Tab 2</a></li>
    <li><a href="#content3">Tab 3</a></li>
  </ul>
</div>
<div class="content content1">
    <p>1. Content goes here</p>
</div>
<div class="content content2">
    <p>2. Content goes here</p>
</div>
<div class="content content3">
    <p>3. Content goes here</p>
</div>

js

function tabs(){
  $(".content").hide();

  if (location.hash !== "") {
    $('.tabs ul li:has(a[href="' + location.hash + '"])').addClass("active");
    var hash = window.location.hash.substr(1);
    var contentClass = "." + hash;
    $(contentClass).fadeIn();
  } else {
    $(".tabs ul li").first().addClass("active");
    $('.tabs').next().css("display", "block");
  }
}
tabs();

$(".tabs ul li").click(function(e) {
  $(".tabs ul li").removeAttr("class");
  $(this).addClass("active");
  $(".content").hide();
  var contentClass = "." + $(this).find("a").attr("href").substr(1);
  $(contentClass).fadeIn();
  window.location.hash = $(this).find("a").attr("href");
  e.preventDefault();
  return false;
});

URL-адреса без будь-якого хешу.
http://output.jsbin.com/tojeja

URL-адреса з хештегом, який не переходить на якір.
http://output.jsbin.com/tojeja#content1

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.