JQuery Performance: Selector vs find vs children vs $ — JavaScript — Форумы SitePoint
DrQuincy
#1
Я не знаю, как лучше всего выбирать элементы JQuery в большом количестве.
Допустим, я хочу выбрать изображения в абзацах, которые имеют элемент галереи класса (предположим, что изображение является дочерним элементом абзаца). Я вижу, что есть несколько вариантов.
- $(‘p.gallery-tem изображение’)
- $(‘p.gallery-tem > img’)
- $(‘p.gallery-tem’).дети(‘img’)
- $(‘p.gallery-tem’).find(‘img’)
- $pgallery.find(‘img’) (элемент уже кэширован в переменной $(p.gallery-item))
- $.find(‘p.gallery-tem’).children(‘img’)
Возможны и другие варианты; обычно дочерние элементы и find взаимозаменяемы, учитывая, что мы знаем, что img является дочерним элементом p.
Как ни странно, я прочитал в stackoverflow, что наиболее эффективный может зависеть от обстоятельств. Я также читал, что children() работает медленнее, чем find() из-за использования нативных функций DOM, хотя потомки, естественно, будут возвращать меньше элементов.
Может ли кто-нибудь предложить какие-либо эмпирические правила эффективности выбора потенциально большого количества элементов? Я опускаю выбор по ID, так как очевидно, что это быстрее.
Наконец, что означает $? Представляет ли это весь документ через JQuery?
Спасибо.
Джеймс_Хиббард
#2
Привет,
Доктор Куинси:
Наконец, что означает $? Представляет ли это весь документ через JQuery?
В jQuery доллар является псевдонимом функции jQuery.
Эта функция сильно перегружена и означает полдюжины разных вещей в зависимости от того, какие аргументы ей передаются.
В вашем примере вы передаете ему строку, содержащую селектор, поэтому функция означает «Создать объект jQuery, содержащий любые изображения в абзацах, которые имеют элемент галереи класса».
Подробнее здесь: http://stackoverflow.com/questions/8667736/what-does-the-sign-mean-in-jquery-or-javascript
Доктор Куинси:
Может ли кто-нибудь предложить какие-либо эмпирические правила эффективности выбора потенциально большого количества элементов?
Насколько большой?
Я не могу предложить никаких практических правил (кроме кэширования элементов там, где это возможно, так как, очевидно, это быстрее).
Доктор Куинси
#3
Спасибо за ссылки! jsperf выглядит хорошо.
Думаю, большой не имеет смысла. Вы просто используете свой здравый смысл, а затем оцениваете его? Как вы думаете, если вы не имеете дело с тысячами элементов, не стоит тратить время на их бенчмаркинг?
Джеймс_Хиббард
#4
Привет,Доктор Куинси:
Я думаю, что большой не имеет смысла.
Не обязательно. Например, это может быть случай, когда у вас есть список с 1000 элементов, и в этом случае вы захотите прикрепить обработчик событий к списку, а затем проверить все, что всплывает, в отличие от присоединения 1000 обработчиков событий к элементам списка. .
Доктор Куинси:
Вы просто руководствуетесь здравым смыслом, а затем оцениваете его? Как вы думаете, если вы не имеете дело с тысячами элементов, не стоит тратить время на их бенчмаркинг?
Я использую jsperf для бенчмаркинга, но обычно только ради любопытства.
Не думаю, что мне когда-либо доводилось выбирать тысячи элементов одновременно.
Если вам нужна помощь, чтобы настроить что-то на jsperf, просто дайте мне знать, так как на самом деле было бы интересно узнать, что лучше чего.
Доктор Куинси
#5
Подойдет.
В настоящее время я сначала работаю на основе здравого смысла (например, селекторы кеша, применяю прослушиватель к таблице вместо каждой отдельной ячейки), а затем проверяю, нормально ли он работает на более старом смартфоне. Честно говоря, я никогда не сталкивался с чем-то, что работало бы слишком медленно, но потом, как вы говорите: «Я не думаю, что мне когда-либо приходилось выбирать тысячи элементов одновременно».
Кстати, есть ли простой способ сравнить скрипты JQuery в браузере? Я заметил, что Webkit позволяет вам профилировать JavaScript, но он кажется слишком низким для того, что я хочу.
Спасибо.
Джеймс_Хиббард
#6
Доктор Куинси:
Кстати, есть ли простой способ сравнить сценарии JQuery в браузере?
Ну, вы могли бы использовать библиотеку, что-то вроде бенчмаркинга.
Документы здесь.
Доктор Куинси
Спасибо!
система Закрыто
#8
Памятка Xpath
Тестирование
Испытательный стенд Xpath
Тестовые запросы на тестовом стенде Xpath:
- Испытательный стенд Xpath (whitebeam.org)
Консоль браузера
$x("//дел")
Работает в Firefox и Chrome.
Селекторы
Селекторы потомков
СС | Экспат | ? |
---|---|---|
h2 |
//h2 |
? |
раздел п |
//дел//п |
? |
ул > ли |
//ул/ли |
? |
ул > ли > а |
//ул/ли/а |
|
дел > * |
//дел/* |
|
: корень |
/ |
? |
:корень > тело |
/корпус |
Селекторы атрибутов
СС | Экспат | ? | |
---|---|---|---|
#id |
//*[@id="id"] |
? | |
. |
//*[@class="class"] … типа |
||
ввод[тип="отправить"] |
9=’/’] | //a[начинается с(@href, '/')] |
? |
а[href$='pdf'] |
//a[заканчивается(@href, '.pdf')] |
||
а[href*='://'] |
//a[содержит(@href, '://')] |
||
а[отн~='помощь'] |
//a[содержит(@rel, 'помощь')] …вроде |
Селекторы заказов
СС | Экспат | ? |
---|---|---|
ul > li:first-of-type |
//ул/ли[1] |
? |
ul > li:nth-of-type(2) |
//ул/ли[2] |
|
ul > li:последний тип |
//ul/li[last()] |
|
li#id:первый в своем роде |
//li[1][@id="id"] |
? |
а: первый ребенок
|
//*[1][name()="a"] |
|
а:последний ребенок |
//*[last()][name()="a"] |
Братья и сестры
СС | Экспат | ? |
---|---|---|
h2 ~ ул |
//h2/следующий-брат::ul |
? |
h2 + ул |
//h2/следующий-брат::ul[1] |
|
h2 ~ #id |
//h2/следующий-брат::[@id="id"] |
jQuery
СС | Экспат | ? |
---|---|---|
$('ul > li'). |
//ул/ли/.. |
? |
$('li').closest('раздел') |
//li/предок-или-я::раздел |
|
$('a').attr('href') |
//a/@href |
? |
$('span').text() |
//диапазон/текст() |
Прочее
СС | Экспат | ? |
---|---|---|
h2: не ([id]) |
//h2[не(@id)] |
? |
Текстовое совпадение | //кнопка[текст()="Отправить"] |
? |
Текстовое совпадение (подстрока) | //кнопка [содержит (текст (), "Перейти")] |
|
Арифметика | //продукт[@цена > 2,50] |
|
Имеет детей | //ул[*] |
|
Имеет детей (конкретно) | //ул[ли] |
|
или логика | //a[@имя или @href] |
? |
Союз (объединяет результаты) | //а | //дел |
? |
Проверка класса
//div[содержит(concat(' ',normalize-space(@class),' '),' foobar ')]
В Xpath нет оператора «проверить, является ли часть списка, разделенного пробелами», так что это обходной путь (источник).
Выражения
Ступени и оси
// |
ул |
/ |
а[@id='ссылка'] |
Ось | Шаг | Ось | Шаг |
Префиксы
Начните свое выражение с любого из них.
Оси
Разделите шаги с /
. Используйте два ( //
), если вы не хотите выбирать прямых дочерних элементов.
шагов
//дел //div[@name='box'] //[@id='ссылка']
Шаг может иметь имя элемента ( div
) и предикаты ( [...]
). Оба являются необязательными.
Это могут быть и другие вещи:
//a/text() #=> "Домой" //a/@href #=> "index.html" //a/* #=> Все дочерние элементы a
Предикаты
Предикаты
//дел[true()] // div[@class="голова"] //div[@class="head"][@id="top"]
Ограничивает набор узлов, только если выполняется какое-либо условие. Их можно заковать.
Операторы
# Сравнение //a[@id = "xyz"] //a[@id != "xyz"] //a[@price > 25]
# Логика (и/или) //div[@id="head" и position()=2] //div[(x и y) или нет(z)]
Используйте операторы сравнения и логические операторы для создания условий.
Использование узлов
# Используйте их внутри функций //ул[количество(ли) > 2] //ul[count(li[@class='hide']) > 0]
# Это возвращает `
- `, у которого есть дочерний элемент `
- `
//ул[ли]
Вы можете использовать узлы внутри предикатов.
Индексация
//a[1] # первый //a[last()] # последний //ol/li[2] # секунда
- //ol/li[position()=2] # то же, что и выше //ol/li[position()>1] # :not(:first-of-type)
Используйте
[]
с числом, илиlast()
илиposition()
.Порядок объединения
а[1][@href='/'] а[@href='/'][1]
Порядок важен, эти два разные.
Вложенные предикаты
//раздел[.//h2[@id='привет']]
Это возвращает
id='hi'
.Функции
Функции узла
name() # //[начинается с (name(), 'h')] text() # //кнопка[text()="Отправить"] # //кнопка/текст() язык (ул.) пространство имен-uri()
count() # //таблица[count(tr)=1] position() # //ol/li[position()=2]
Логические функции
не(выражение) # кнопка[не(начинается с(текст(),"Отправить"))]
Строковые функции
contains() # font[contains(@class,"head")] начинает-с() # шрифт[начинает-с(@класс,"голова")] заканчивается-с() # шрифт[заканчивается-с(@класс,"голова")]
конкат (х, у) подстрока (ул, начало, длина) substring-before("01/02", "/") #=> 01 подстрока-после("01/02", "/") #=> 02 переводить() нормализовать пространство () длина строки()
Преобразование типа
строка() число() логическое()
Оси
Использование осей
//ul/li # ul > li //ul/child::li # ul > li (то же самое) //ul/following-sibling::li # ul ~ li //ul/потомок-или-я::li # ul li //ul/предок-или-я::li # $('ul').
closest('li')
Шаги выражения разделяются
/
, обычно используемыми для выбора дочерних узлов. Это не всегда так: можно указать другую «ось» с помощью::
.//
ул
/ребенок::
ли
Ось Шаг Ось Шаг Детская ось
# оба одинаковые //ул/ли/а //ребенок::ul/ребенок::li/ребенок::а
child::
— ось по умолчанию. Это заставляет//a/b/c
работать.# оба одинаковые # это работает, потому что `child::li` является истинным, поэтому предикат выполняется успешно //ул[ли] //ул[ребенок::ли]
# оба одинаковые //ул[количество(ли) > 2] //ul[count(child::li) > 2]
Ось потомка или себя
# оба одинаковые //дел//h5 //div/потомок-или-я::h5
//
— это сокращение от осипотомок или я::
.# оба одинаковые //ul//[последний()] //ul/потомок-или-я::[last()]
Прочие оси
Можно использовать и другие оси.
Союзы
//а | //охватывать
Использовать
|
, чтобы соединить два выражения.Еще примеры
Примеры
//* # все элементы count(//*) # подсчет всех элементов (//h2)[1]/text() # текст первого заголовка h2 //li[span] # найти
- с внутри него
# ...заменяется на //li[child::span]
//ul/li/.. # используйте .. для выбора родителя
Найти родителя
//раздел[h2[@id='имя-раздела']]
Находит
h2#section-name
//раздел[//h2[@id='имя-раздела']]
Находит
h2#section-name
. (То же, что и выше, но вместо потомка используется потомок или я)Ближайший
.