Почему массив, содержащий строки, собранные из элемента, не обновляется при внесении изменений в элемент?

Мне трудно понять, почему добавление TEXT_NODE (document.createTextNode('some string')) в существующий родительский элемент не обновляет количество элементов при использовании цикла for.

Не поймите меня неправильно, это упрощает изменение родительского элемента, я просто не понимаю, почему длина массива не обновляется.

Я думал, что при работе с такого рода элементами они «живые», т.е. обновление с внесенными изменениями.

Редактировать №1:

Почему const words = topNode.textContent.split(" "); не обновляется при добавлении новых строк в элемент topNode-s. т.е.: в начале длина равна 2 (0 - один, 1 - два, 2 - три), при добавлении "какой-то строки" я ожидаю, что длина words будет равна 4 (0 - один, 1 - два, 2 - некоторые, 3 – струна, 4 – три).

Редактировать № 2:

Я хотел бы знать, почему длина массива не обновляется, поскольку я знаю, что в некоторых случаях (я не знаю, в каких случаях...) длина массива обновляется при внесении изменений. Почему в некоторых случаях, а не в этом случае?

Пример:

const textarea = document.querySelector("#textarea");
const topNodes = textarea.childNodes;
for (const topNode of topNodes){
    if (topNode.nodeType === 3){
        let charCount = 0; //character count includes the number of letters and spaces - used for appending a word - function appendString
        const words = topNode.textContent.split(" ");
        for (let i = 0; i < words.length - 1; i++) {
            const word = words[i];
            if (typeof word !== 'undefined' && !word.length){
                charCount++; //in case of double space (currently irrelevant)
                continue;
            }
            charCount += word.length + 1; //adding + 1 as words are split by space
            if (word === 'two'){
                appendString(charCount, topNode, 'some string');
            }
            console.info("+-------------------------+");
            console.info("| current word count: ", words.length - 1, " |")
            console.info("|  actual word count: ", topNode.textContent.split(" ").length - 1, " |")
        }
    }
}

function appendString(charCount, thisParentNode, string){
    const nodeText = thisParentNode.textContent;
    const before = nodeText.slice(0, charCount);
    const after = nodeText.slice(charCount);

    thisParentNode.textContent = before;
    
    if (string.charAt(string.length - 1) !== " "){
      string = string + " ";
    }

    const textNodeAfter = document.createTextNode(after);
    const textNodeAppend = document.createTextNode(string);

    thisParentNode.parentNode.insertBefore(textNodeAppend, thisParentNode.nextSibling);
    thisParentNode.parentNode.insertBefore(textNodeAfter, textNodeAppend.nextSibling);
    
    //and normalize all the way up to textarea
    const textarea = document.querySelector("#textarea");
    normalizeAll(thisParentNode, textarea);

    function normalizeAll(thisNode, topNode){
        if (thisNode !== topNode){
            thisNode.normalize();
            normalizeAll(thisNode.parentNode, topNode);
        } else {
           thisNode.normalize();
        }
    } 
}
#body{
  height: 100%
}
#textarea {
  min-height: 30%;
  border: 1px solid black;
}
<html>
  <body>
    <div id = "textarea" contenteditable>one two three</div>
  </body>
</html>

Чтобы дополнительно объяснить, почему это на самом деле «проблема», возьмем пример ниже. Если я хочу добавить к элементу несколько строк, мне нужно количество символов (чтобы они были добавлены в правильное место).

Если мы возьмем переменную topNode — которая является элементом TEXT_NODE; и мы хотим добавить к элементу несколько строк (textNodes), я ожидаю, что добавление строки после первого раза (2cnd, 3rd, 4th и т. д.) будет добавлено в неправильном месте.

Пример:

один два три два четыре два пять

  • добавьте «что-то» после того, как найдена строка «два».
  • используйте charCount, чтобы определить, где разделить текущий TEXT_NODE, чтобы «что-то» можно было вставить в нужное место.

номер петли. 2

charCount должно быть -> 7 (один два)

charCount на самом деле -> 7

вставь "что-нибудь"


номер петли. 4

charCount должно быть -> 27 (один два что-то три два)

charCount на самом деле -> 17 (один два три два)

при вставке чего-либо с использованием charCount 17 он вставляет это в правильное место (т. е. один два что-то три два что-то)

если бы мы использовали charCount 27, он бы вставил его не в то место.

Почему использование charCount 17 правильно? Я ожидаю, что при использовании 17 при вставке строки она будет вставлена ​​не в то место (т. е.: один, два, что-то, три, два)

Я ожидал, что использование 27 поместит его в правильное место, но это не так.

Извините, я не совсем понял ваш вопрос?

mikegross 22.08.2024 18:51

Кроме того, я бы посоветовал вам дать переменным гораздо лучшие имена. Прямо сейчас у вас есть переменные с именами textarea, nodes и node, каждая из которых имеет разные значения, и ни одна из этих переменных не содержит того, что подразумевает их имя.

Rory McCrossan 22.08.2024 19:07

Почему вы вычитаете из длины? Это не будет правильным подсчетом для каждого.

mykaf 22.08.2024 19:11

добавил правку для ясности. @Рори МакКроссан, у меня вопрос не о прослушивателях событий. Я хотел бы знать, почему длина массива не обновляется, поскольку я знаю, что в некоторых случаях (я не знаю, в каких случаях...) длина массива обновляется при внесении изменений. Почему в некоторых случаях, а не в этом случае? Также спасибо за указатель на имена переменных.

DoomBot 22.08.2024 19:14

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

mykaf 22.08.2024 19:14
topNode.textContent(" ") похоже на ошибку. Что ты имел в виду?
Bergi 22.08.2024 19:21

спасибо, сейчас отредактирую

DoomBot 22.08.2024 19:21

«Я ожидаю, что длина nodes будет равна 4» — в вашем коде нет nodes (по крайней мере, больше). Вы имели в виду topNodes или words?

Bergi 22.08.2024 19:24

Проклятие. Отредактировал код, но не текст. Я имел в виду words. Редактируем текст сейчас

DoomBot 22.08.2024 19:25
Поведение ключевого слова "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) для оценки ваших знаний,...
2
9
69
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Почему добавление TEXT_NODE в существующий родительский элемент не обновляет количество элементов? Я думал, что при работе с такого рода элементами они «живые», т.е. обновление с внесенными изменениями.

Они делают.

const topNodes = textarea.childNodes;

это не массив, а живой NodeList дочерних элементов этого элемента. Когда вы добавите больше узлов в textArea, это отразится в коллекции.

Почему const words = topNode.textContent.split(" "); не обновляется при добавлении к элементу новых строк.

Потому что это массив, созданный из строки (topNode.textContent). Ни строка не является «живой», а просто значением, ни метод split() не знает, как построить «живой массив». Этот код запускается один раз, и если вы не обновите массив самостоятельно, он сохранит состояние, в котором он был инициализирован.

Спасибо. Я отредактировал вопрос (после кода), который отражает (надеюсь, ясно), почему я запутался. Не могли бы вы взглянуть, отредактировать свой ответ, и я приму.

DoomBot 22.08.2024 19:56

«переменная topNode является элементом TEXT_NODE; и мы хотим добавить к элементу несколько строк (textNodes)» — нет. Текстовый узел не является элементом , и вы не можете добавлять к нему другие узлы в качестве дочерних. Вы можете изменить только его nodeValue.

Bergi 22.08.2024 20:03

И опять же, живыми могут быть только объекты. topNodes активен, и его .length действительно изменится, когда вы запустите thisParentNode.parentNode.insertBefore(…). Но charCount — это всего лишь число, и вы сами несете ответственность за обновление переменной.

Bergi 22.08.2024 20:06

Почему const words = topNode.textContent.split(" "); не обновляется при добавлении новых строк в элемент topNode-s.

Потому что механизма для этого нет и никогда не было. (Я не знаю ни одного языка, который бы это делал. Если бы он когда-либо был реализован, он должен был бы быть либо на новом языке, либо в новом явном синтаксисе только для этой функциональности, поскольку такая вещь фундаментально нарушила бы весь существующий код. .)

topNode действительно может быть ссылкой на элемент на странице. Но words наверняка нет. Это просто массив строк, полученный на основе информации об этом элементе. Чтобы получить обновленные данные, вам придется снова запросить этот элемент.

Чтобы упростить ту же операцию, учтите следующее:

let x = 2;
let y = 3;
let z = x + y;
x = 3;

Какую ценность вы ожидаете от z после этих четырех строк кода и почему?

z будет равно 5, хотя x было изменено. Это связано с тем, что значение z не является живой ссылкой на переменные, используемые для его расчета. Это значение, полученное в результате этого расчета. Обновление значения означает повторное выполнение расчета.

Если вы хотите аппроксимировать эту функциональность, на каком-то уровне для этого нужны функции:

let x = 2;
let y = 3;
let z = () => x + y;
x = 3;

Теперь z не имеет числового значения, его значение представляет собой функцию, которую можно вызвать для получения нужного значения. Эта функция имеет «живую» ссылку на переменные x и y.

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