После получения содержимого страницы из запроса AJAX я могу выбрать элемент тега, но не могу выбрать элемент тела - PullRequest
0 голосов
/ 07 января 2020

Я получил html страницу через AJAX запрос

$.ajax({
    async: true,
    method: 'GET',
    url: linkPage,
    // cache: true,
    success: function (data) {
        console.log(data);
    }
});

Формат данных, который я получаю так:

<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<div id="wrap">
    <main class="temp>
        <section class="sec01">
            ...
        </section>
    </main>
</div>
</body>
</html>

Теперь я хочу получить идентификатор тела и класс (который «устойчивый» ) через этот код:

$(data).find('body').attr('class');

Но я понятия не имею, почему я не могу этого получить, он возвращает undefiend . Но когда я получаю html контент или класс <main> по этому коду:

$(data).find('main').attr('class');
$(data).find('main').html();

Он возвращает именно то, что я хочу. Кто-нибудь может мне объяснить, почему?

Я уже пробовал некоторые решения, создавая виртуальный DOM, подобный этому, и я могу выбирать <body> и <main> из AJAX данных, как я хочу: Невозможно получить элемент тела из ajax ответа

Но я все еще удивляюсь, почему я не могу выбрать <body> class и html в качестве первого случая?

Ответы [ 3 ]

1 голос
/ 07 января 2020

Похоже, что при задании такой строки jQuery сохранит только содержимое тела в свою коллекцию:

const data = `<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<div id="wrap">
    <main class="temp>
        <section class="sec01">
            ...
        </section>
    </main>
</div>
</body>
</html>`;
console.log($(data)[0]);
console.log($(data)[1]);
console.log($(data)[2]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

(Проверьте консоль браузера. Она выбирает текстовые узлы вокруг #wrap и #wrap, но не the <head> или <body>)

Вместо этого вы можете использовать DOMParser, который попытается превратить всю строку в документ, не пытаясь исключить:

const data = `<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<div id="wrap">
    <main class="temp>
        <section class="sec01">
            ...
        </section>
    </main>
</div>
</body>
</html>`;
const doc = new DOMParser().parseFromString(data, 'text/html');
console.log(doc.body.className);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Другое преимущество использования DOMParser заключается в том, что, в отличие от jQuery, он не будет выполнять потенциально небезопасный код в строке HTML:

const data = `<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<img src onerror="alert('evil')">
</body>
</html>`;
$(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
jQuery version, unsafe

const data = `<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<img src onerror="alert('evil')">
</body>
</html>`;
const doc = new DOMParser().parseFromString(data, 'text/html');
console.log(doc.body.className);
DOMParser version, safe
1 голос
/ 07 января 2020

Причина, по которой это не работает так, как вы пытались, объяснена в jQuery документации :

Если HTML сложнее, чем один тег без атрибутов, как в приведенном выше примере, фактическое создание элементов обрабатывается механизмом браузера .innerHTML. В большинстве случаев jQuery создает новый элемент <div> и устанавливает для свойства innerHTML элемента значение, которое было передано во фрагмент HTML.

Поскольку вы не можете иметь <body> внутри <div> браузер игнорирует тег <body>.

В документации говорится:

При передаче в комплексе HTML некоторые браузеры могут не создавать DOM, который точно повторяет предоставленный источник HTML. Как уже упоминалось, jQuery использует свойство браузера .innerHTML для анализа переданного HTML и вставки его в текущий документ. Во время этого процесса некоторые браузеры отфильтровывают определенные элементы, такие как <html>, <title> или <head>. В результате вставленные элементы могут не соответствовать исходной переданной строке.

0 голосов
/ 07 января 2020

Следующее jQuery Не будет работать:

$(data).find('sustainable');

, так как div - это элементы верхнего уровня, а данные - это не элемент, а строка, для работы вам необходимо использовать .filter

$(data).filter('sustainable.wrap');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...