Svelte - объект, возможно, "нулевой"

Я пытаюсь заставить эту Навигацию с плавной прокруткой работать в Svelte. Но, тем не менее, этот объект ошибки TypeScript, возможно, имеет значение «null».ts(2531). Я понял, что эта ошибка связана с тем, что TypeScript считает, что этот элемент может иметь значение null. Поэтому я должен объявить, что это за элемент, с помощью оператора if или использовать оператор восклицательного знака ! (например, это не нуль). Я пробовал множество возможностей для обоих решений, но все еще безуспешно.

REPL полного кода в svelte, где видно, что IntersectionObserver не работает.

<script>
    import { onMount } from 'svelte';
    let id;
    
    onMount(() => {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach((entry) => {
                id = entry.target.getAttribute('id');
                    
                    if (entry.intersectionRatio > 0) {
                        document.querySelector(`nav li a[href = "#${id}"]`)    //error
                            .parentElement    //error
                            .classList
                            .add('active');
                    } else {
                        document.querySelector(`nav li a[href = "#${id}"]`)    //error
                            .parentElement    //error
                            .classList
                            .remove('active');
                    };
            });

            document.querySelectorAll('section[id]').forEach((section) => {
                observer.observe(section);
            });

        });
    });
</script>

Оригинальный код от Bram. Спасибо, что поделился.

Не имеет отношения к вашей проблеме object is possibly 'null', но я думаю, что вы все еще находитесь внутри обратного вызова конструктора IntersectionObserver, когда выполняете document.querySelectorAll('section[id]'), поэтому наблюдатель никогда не сможет ничего наблюдать, и его обратный вызов никогда не будет вызван.

M. Desjardins 22.11.2022 15:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
795
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Рекомендовал бы либо не позволять TypeScript проверять код JS, либо использовать TypeScript.

Первый должен быть настроен с помощью tsconfig.json опции checkJs.

Для последнего вы должны использовать svelte-preprocess (см. документацию) и объявить язык скрипта:

<script lang = "ts"> ...

В противном случае вы не сможете использовать специфичный для TS синтаксис, такой как !, или утверждения типа.


Чтобы устранить возможные ошибки null/undefined, вы всегда можете использовать операторы if, но вам нужно извлечь переменную, содержащую соответствующее значение:

const element = document.querySelector('...');
if (element) {
  // element will be defined here
}

Спасибо за Ваш ответ. Я определил <script lang = "ts"> в своем коде, но забыл написать его в рассматриваемом коде. Когда я устанавливал SvelteKit, я принял вариант с TypeScript, поэтому я подумал, что TS поддерживается. Я пытался отключить checkJS и все равно не работает, потом попробовал поставить strictNullChecks:false но все равно не работает. Хотя я сделал это в jsconfig.json, я не уверен, что это то же самое, но у Svelte есть этот файл. Я попытаюсь извлечь переменную, содержащую значение ... также я не знал о svelte-preprocess, поэтому мне нужно проверить документацию. Спасибо, Х.Б.

Tomca z Brodku 22.11.2022 13:41

Я действительно не думаю, что рекомендация пользователю отключить TS принесет им пользу, особенно в этом случае, поскольку это может привести к реальным ошибкам в их приложении.

Marcos Sandrini 24.11.2022 09:40

@MarcosSandrini: я говорил только о функции проверки JS, которая не так хороша, поскольку вы не можете использовать синтаксис TS для исправления ошибок, требующих выразительности TS.

H.B. 24.11.2022 09:53

@Х.Б. хорошо, справедливое замечание. Но это может быть неправильно истолковано, например, если это первое, что вы говорите в своем ответе, некоторые люди, менее терпеливые, чтобы прочитать его, могут воспринять это как главный совет.

Marcos Sandrini 24.11.2022 10:06

Когда вы пишете:

document.querySelector(`nav li a[href = "#${id}"]`)

Результат этого выражения может быть нулевым, например, он ничего не может найти. TS очень мудро говорит, что вы должны помнить об этом, иначе ваше приложение может дать сбой, и, возможно, преобразовать это в какое-то выражение, в котором учитывается нулевой регистр. Одно предложение:

const element = document.querySelector(`nav li a[href = "#${id}"]`)
if (element && element.parentElement) {
  element.parentElement.classList.add('active');
}

Таким образом, вы принимаете во внимание случай null. Кроме того, я думаю, что строка document.querySelectorAll('section[id]')... должна быть за пределами блока new IntersectionObserver ..., как отметил @Desjardins.

Обновлено: добавлено одно условие. Спасибо @Desjardins.

Спасибо, Маркос, но до сих пор не могу понять окончательную структуру. Я определил строку const element ... , а затем изменил оператор if на этот if (entry.intersectionRatio > 0 && element) {element.parentElement.classList.add('active'); } else if (element) {element.parentElement.classList.remove('active');};, но безуспешно. Я что-то пропустил?

Tomca z Brodku 24.11.2022 22:37
Node.parentElement также может быть нулевым, поэтому вам также необходимо проверить его на нуль, чтобы избежать ошибки TypeScript. Но имейте в виду, что это просто ошибка TypeScript — проблема с IntersectionObserver все еще существует.
M. Desjardins 28.11.2022 14:38

Добавил туда одно условие, чтобы учесть очень полезный комментарий выше.

Marcos Sandrini 14.12.2022 10:35
Ответ принят как подходящий

ДА! Я сделал это.

Функциональная версия TOC (Table of Content) для Svelte с настраиваемым классом, который показывает и отслеживает активный элемент в списке TOC в соответствии с содержимым (заголовком, текстом) в окне просмотра.

<script lang = "ts">
import { onMount } from 'svelte';

let id
let element
    
    onMount(() => {
            const observer = new IntersectionObserver((entries) => {
                entries.forEach((entry) => {
                    id = entry.target.getAttribute('id');
                    if (entry.intersectionRatio > 0) {
                        element = document.querySelector(`nav li a[href = "#${id}"]`);
                        if (element && element.parentElement )  {
                            element.parentElement.classList.add('active');
                        }
                    } else {
                        element = document.querySelector(`nav li a[href = "#${id}"]`)
                        if (element && element.parentElement )  {
                            element.parentElement.classList.remove('active');
                        }
                    };
                });
            });
        // Track all sections that have an `id` applied
        document.querySelectorAll('section[id]').forEach((section) => {
        observer.observe(section);
        });
    });
    
</script>

Это скорректированная версия исходного кода для Svelte. Создатель Брэм загляните в его блог.

Другие вопросы по теме