Почему"#.id " плохой селектор в CSS / jQuery, но он работает в HTML-якоре?
я использую JSDoc. Он генерирует идентификаторы с периодом как в
<a id=".someMethodName"></a>
если другая часть страницы имеет
<a href="#.someMethodName"></a>
это прекрасно работает. Щелчок по второму якорю приведет к первому.
однако, ни document.querySelector
и jQuery не найдет якорь.
почему сам браузер принимает этот якорь, а jQuery и querySelector-нет?
test("document.querySelector('#.someMethodName')", function() {
document.querySelector('#.someMethodName');
});
test("$('#.someMethodName')", function() {
$('#.someMethodName');
});
function test(msg, fn) {
try {
var result = fn();
log(msg, result);
} catch(e) {
log(msg, e);
}
}
function log() {
var pre = document.createElement("pre");
pre.appendChild(document.createTextNode(Array.prototype.join.call(arguments, " ")));
document.body.appendChild(pre);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#.someMethodName">click here to go to anchor and see errors</a>
<pre>
put
some
text
here
so
the
page
is
long
enough
that
when
we
click
the
anchor
the
browser
has
as
a
place
to
scroll
that
is
off
screen
otherwise
we'd
have
no
way
to
see
if
it
worked
or
not
</pre>
<a id=".someMethodName">we should scroll to here</a>
<p>did we make it?</p>
<hr/>
5 ответов
HTML5 позволяет иметь период в значении атрибута ID, и браузеры обрабатывали это без каких - либо проблем в течение десятилетий (вот почему ограничение в HTML 4 - само по себе определяется не HTML, а SGML, на котором оно основано-было ослаблено в HTML5, теперь свободном от устаревшего багажа SGML). Так что проблема не в значении атрибута.
грамматика идентификатора фрагмента, определенного RFC 3986 - это:
fragment = *( pchar / "/" / "?" )
где набор символов pchar
включает в себя период. Так что .someMethodName
является допустимым идентификатором фрагмента, поэтому <a href="#.someMethodName">
строительство.
но #.someMethodName
не является допустимым селектор, и причина двоякая:
- селектор ID состоит из
#
затем идент, и идентификатор в CSS не может содержать точку. - таким образом, период зарезервирован для селектора классов (который аналогично состоит из следующего периода по иденту).
короче говоря, парсер ожидает идентификатор CSS после #
но не найти его из-за .
, что непосредственно следует за ним, делая селектор недействительным. Это удивительно, потому что обозначение селектора ID фактически основано на обозначении URI для идентификатора фрагмента - как видно из того, что оба они начинаются с #
знак, а также тот факт, что они оба используются для ссылки на элемент однозначно выявлены внутри документа по этому идентификатору. Вполне разумно ожидать, что все, что работает в фрагменте URI, также будет работать в селекторе ID - и в большинстве случаев это is правда. Но потому, что CSS имеет свою собственную грамматику, которая не обязательно коррелирует с грамматикой URI (потому что они два совершенно несвязанных стандарта1), вы получаете крайние случаи, такие как этот.
поскольку период является частью идентификатора фрагмента, вам понадобится чтобы избежать его с обратной косой чертой, чтобы использовать его в селекторе ID:
#\.someMethodName
не забывайте, что вам нужно избежать обратной косой черты в строке JavaScript (например, для использования с document.querySelector()
и jQuery):
document.querySelector('#\.someMethodName')
$('#\.someMethodName')
1несколько лет назад W3C Community Group был сформирован (членом которого я являюсь) вокруг предложения, известного как использование селекторов CSS в качестве идентификаторов фрагментов это, как вы можете представьте себе, женился на двух технологиях интересным образом. Однако это никогда не снималось, и единственными известными реализациями являются некоторые расширения браузера, которые, вероятно, даже не поддерживаются.
на в HTML5 является допустимым атрибутом id:
нет никаких других ограничений на то, какую форму ID может принять; в в частности, идентификаторы могут состоять только из цифр, начать с цифры, начать с символа подчеркивания, состоящих из знаков препинания и т. д.
Так как это не является действительным идентификатор CSS, чтобы использовать его с querySelector()
или $()
вы должны избежать этого, как это:
#\.someMethodName
для соответствия идентификатору или селекторам, которые не следуют синтаксису CSS (с помощью двоеточие или пробел неуместно, например),вы должны бежать характер с задней косой чертой. Как обратная косая черта является Escape-символом в JavaScript, если вы вводите литеральную строку,вы должны бежать это дважды (один раз для строки JavaScript, а другой раз для querySelector):
имейте в виду, что это не является действительным HTML4 атрибут id
вы должны бежать .
С \
перед запросом элементов.
Заменить
document.querySelector('#.someMethodName');
до
document.querySelector('#\.someMethodName');
Также обратите внимание, что технически, для HTML 4 требуемый формат значения ID указан ниже:
маркеры ID и NAME должны начинаться с буквы ([A-Za-z]) и могут сопровождаться любым количеством букв, цифр ([0-9]), дефисов ("-"), подчеркиваний ("_"), двоеточий ( " :") и периодов (".").
так .[A-Za-z]
является недействительным..
относительно соглашений об именах HTML5 ID
в HTML5, вы можете назовите свой ID атрибуты все, что вы хотите практически без ограничений по синтаксису:
нет никаких других ограничений на то, какую форму может принимать идентификатор; в частности, идентификаторы могут состоять только из цифр, начинаться с цифры, начинаться с подчеркивания, состоять только из пунктуации и т. д.
какие функции селектора ждем
однако при использовании селекторов JavsScript, таких как документ.querySelector(), важно отметить, что синтаксис как он оценивает свои аргументы.
возвращает первый элемент в документе (с использованием глубины первого предварительного порядка обхода узлов документа / первым элементом в разметке документа и итерации через последовательные узлы по порядку количества дочерних узлов), который соответствует указанная группа селекторов.
элемент = документ.querySelector(селекторов);
element
является объектом элемента.selectors
- строка, содержащая один или несколько селекторов CSS, разделенных запятыми.
когда вы путаете функции селектора
Итак, здесь мы видим, что он пытается разобрать селекторы CSS. В основном, функция интерпретирует любую строку, начинающуюся с #
как класс и любая строка, начинающаяся с #
как id, так что когда вы пытаетесь передать ему строку, как это:
#.someMethodName
он думает, что вы пытаетесь разобрать id и Класс all как один аргумент и выдает ошибку, называя ее синтаксической ошибкой.
В Заключение
Итак, в заключение, в то время как ваши значения ID технически допустимы, используя .
и #
будет путать эти функции селектора JavaScript, такие как $(selector)
и document.querySelector(selector)
etc.
чтобы устранить эту проблему, вам нужно сообщить функции, что вы пытаетесь использовать .
или #
в качестве символа вместо идентификатора путем экранирования символов без идентификаторов:
#\.someMethodName
почему сам браузер принимает этот якорь, а jQuery и querySelector-нет?
потому что хэш не является селектором CSS, это #
с последующим идентификатором.
браузер счастливо прокручивается к этому элементу, потому что он не использует хэш, без изменений, как селектор CSS. Вероятно, он вообще не использует селектор CSS, а скорее его внутренний метод поиска элементов по ID - тот, который также вызывается document.getElementById
, что также не волнует точка. Доказательство:
document.getElementById(".someMethodName").style.color = "green";
<div id=".someMethodName">I'm green because I was found by <code>document.getElementById(".someMethodName")</code></div>
хотя это правда, что CSS использует #
чтобы отметить начало селектора идентификаторов, это не означает, что каждый #
everywhere-это начало селектора идентификаторов CSS.
если браузер сделал используйте хэш в качестве селектора CSS, он, по-видимому, будет правильно избегать его до его использования.