Как мне сделать компонент, который знает текущий URL-адрес в Sapper с помощью Svelte?

У меня есть страница, на которой есть панель навигации со ссылкой "Кварталы". Под ссылкой Quarters, когда пользователь находится на маршруте /quarters, будет показан список кварталов, например, 2019Q2 и т. Д. URL-адрес будет /quarters/2019q2.

Я хочу создать компонент, который показывает гиперссылку, которая будет иметь класс selected, если текущий URL-адрес совпадает с href ссылки. Вот самое близкое, что я могу найти:

<script>
  import { afterUpdate } from 'svelte';
  export let segment;
  export let text = 'text here';
  export let link;
  let isCurrentPath = false;
  console.log(segment, link, text);
  afterUpdate(() => {
    if (window.location.pathname.includes(link)) {
      isCurrentPath = true;
      debugger;
    }
    console.log('HL afterUpdate ', window.location);
  });
</script>

<style>
  /* omitted */
</style>

<a class:selected={segment && isCurrentPath} href={link}>{text}</a>

Это отлично работает для первой загрузки, но когда пользователь переходит на другую страницу данных, выбор не обновляется. Как мне заставить некоторый код работать только на стороне клиента? Если я обращусь к объекту window за пределами afterUpdate, я получу ошибку null ref из серверного кода.

ETA: Тоже пробовал:

  let isCurrentPath = false;
  let path = typeof window === 'undefined' ? '' : window.location.pathname;
  $: if (path) isCurrentPath = window.location.pathname.includes(link);

Этот код не срабатывает, когда пользователь щелкает одну из ссылок на данные. Пробовал onMount тоже без положительного результата.


person jcollum    schedule 05.09.2019    source источник


Ответы (2)


Уловка состоит в том, чтобы создать реактивный оператор на основе значения в хранилище страниц.

<!--
This is used to have a link on the page that will show highlighted if the url meets the criteria.
You might want to adjust the logic on line 19.
usage: 
<HighlightedLink bind:segment highlight="faq" rel="prefetch" link="/faq" text="FAQ" />
--> 

<script>
  import { stores } from '@sapper/app';
  const { page } = stores();
  export let highlight;
  export let segment;
  export let text = 'text here';
  export let link;
  export let target;
  let highlightPath = false;
  $: highlightPath =
    $page.path && highlight && ($page.path.includes(highlight) || $page.path.includes(link));
</script>

<style>
  .selected {
    position: relative;
    display: inline-block;
  }
  .selected::after {
    position: absolute;
    content: '';
    width: calc(100% - 1em);
    height: 2px;
    background-color: rgb(255, 62, 0);
    display: block;
    bottom: -1px;
  }
  a {
    padding-left: 10px;
  }
</style>


<a class:selected={highlightPath} href={link}>{text}</a>
person jcollum    schedule 11.09.2019

вместо использования afterUpdate я считаю, что вам следует заняться написанием чего-либо с onMount и использовать реактивные операторы https://svelte.dev/examples#reactive-statements, чтобы сообщить svelte, что вы хотите пересчитывать isCurrentPath при изменении местоположения.

person nks1111    schedule 06.09.2019