Это очень распространенная проблема, возникающая из-за непонимания работы :nth-child()
и :nth-of-type()
. К сожалению, в настоящее время нет решения на основе селектора, поскольку селектор не обеспечивает способ сопоставления n-го дочернего элемента, который соответствует произвольному селектору на основе шаблона, такого как нечетные, четные или любые an+b
, где a != 1
и b != 0
.
:nth-child()
псевдокласса подсчитывает элементы среди всех всех их братьев и сестер под одним и тем же родителем. Он не учитывает только братьев и сестер, которые соответствуют остальной части селектора. Аналогично, псевдо-класс :nth-of-type()
считает, что siblings используют один и тот же тип элемента, который относится к имени тега в HTML, а не к остальной части селектора.
Это также означает, что если все дочерние элементы одного и того же родителя имеют один и тот же тип элемента, например, в случае тела таблицы, единственными дочерними элементами которого являются tr
или элемент списка, единственными дочерними элементами которого являются li
, тогда :nth-child()
и :nth-of-type()
будут вести себя одинаково, т. е. для каждого значения an+b
, :nth-child(an+b)
и :nth-of-type(an+b)
будут соответствовать одному и тому же набору элементов.
На самом деле все простые селектора в данном соединении селектор, включая псевдоклассы, такие как :nth-child()
и :not()
, работают независимо друг от друга , вместо того, чтобы смотреть на подмножество элементов, которые сопоставляются остальными селектора.
Это также подразумевает, что нет понятия порядка среди простых селекторов в каждом отдельном селекторе 1, что означает, например, следующие два селектора эквивалентны:
[f 1]
При переводе на английский язык оба означают:
Выберите любой элемент
tr
, который соответствует всем следующим независимым условиям:blockquote>
- нечетный номер родительского родителя;
- имеет класс «строка»; и
- является потомком элемента
table
, который имеет класс «myClass».(вы заметите, что мое использование неупорядоченный список здесь, просто для того, чтобы управлять точкой.)
Поскольку в настоящее время нет чистого решения CSS, вам придется использовать скрипт для фильтрации элементов и соответственно применять стили или дополнительные имена классов. Например, следующее обходное решение, использующее jQuery (предполагается, что в таблице есть только одна группа строк, заполненная элементами
tr
):$('table.myClass').each(function() { // Note that, confusingly, jQuery's filter pseudos are 0-indexed // while CSS :nth-child() is 1-indexed $('tr.row:even').addClass('odd'); });
С соответствующим CSS:
table.myClass tr.row.odd { ... }
Если вы используете автоматические инструменты тестирования, такие как Selenium или обрабатываете HTML с помощью таких инструментов, как lxml, многие из этих инструментов позволяют XPath в качестве альтернативы:
//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ', @class, ' '), ' row ')][position() mod 2)=1]
Другие решения, использующие разные технологии, оставил в качестве упражнения читателю; это всего лишь краткий, надуманный пример для иллюстрации.
Для чего это стоит, есть предложение для расширения к
:nth-child()
нотации , которое должно быть добавлено к Селекторы уровня 4 для конкретной цели выбора каждого n-го дочернего элемента, соответствующего данному селектору.2Селектор, в котором для фильтрации совпадений предоставляется в качестве аргумента
:nth-child()
, снова из-за того, как селектора работают независимо от друг друга в последовательности, продиктованной существующим синтаксисом селектора. Итак, в вашем случае это будет выглядеть так:table.myClass tr:nth-child(odd of .row)
(Проницательный читатель сразу заметит, что это должно быть
:nth-child(odd of tr.row)
вместо этого, поскольку простые селекторtr
и:nth-child()
работают независимо друг от друга. Это одна из проблем с функциональными псевдоклассами, которые принимают селекторы, банку червей, которую я предпочитаю не открывать посреди этого ответа. Вместо этого я собираюсь перейти к предположению что большинство сайтов не будут иметь каких-либо других элементов, кроме элементовtr
, как братьев и сестер друг друга в теле таблицы, что сделает любой вариант функционально эквивалентным.)Конечно, будучи новым предложением в новая спецификация, это, вероятно, не увидит реализацию до нескольких лет в будущем. В то же время вам придется придерживаться сценария, как указано выше.
1 Если вы укажете тип или универсальный селектор, он должен быть первым. Однако это не меняет того, как работают селекторы. это не что иное, как синтаксический приступ.
2 Первоначально это было предложено как
:nth-match()
, однако, поскольку оно по-прежнему считает элемент относительным только для его братьев и сестер, а не для каждого другого элемента, который соответствует данному селектору, он с тех пор, как с 2014 года был перепрофилирован как расширение существующего:nth-child()
.
JavaScript нетипизирован, что означает, что мы можем передавать и использовать данные, объекты и функции без ограничений. Мы можем написать код, который вызывает методы, которые не существуют для объекта, или ссылочные переменные, которых у нас нет. Подобные ошибки могут быть трудно обнаружить, когда вы пишете код, и это может привести к нестабильному и глючному коду. Внесение больших изменений в ваш код может стать трудным и рискованным, поскольку вы не сразу видите, конфликтуют ли некоторые изменения с остальным кодом где-то еще.
TypeScript в основном о добавлении типов в JavaScript. Это означает, что TypeScript требует от вас точного описания формата ваших объектов и ваших данных. Когда вы делаете это, это означает, что компилятор может исследовать ваш код и обнаружить ошибки. Он может видеть, что вы пытаетесь вызвать функцию с неправильными типами аргументов или ссылаетесь на переменную, которая недоступна в текущей области.
Когда вы пишете TypeScript самостоятельно, это формальное описание кода является частью самого кода.
Однако, когда вы используете внешние библиотеки, такие как jQuery или moment.js, информация о типах в этом коде отсутствует. Таким образом, чтобы использовать его с TypeScript, вы также должны получить файлы, которые описывают типы этого кода. Это файлы объявлений типа , чаще всего с расширением имени файла .d.ts
. К счастью, люди написали такие файлы объявлений типов для большинства распространенных библиотек JavaScript.
Набор текста был просто инструментом для установки этих файлов. В настоящее время лучше всего использовать npm .
Когда вы установите эти файлы, что в основном означает их загрузку и размещение в вашем проекте, компилятор TypeScript поймет * этот внешний код и вы сможете использовать эти библиотеки. В противном случае вы бы везде получали ошибки.
* В зависимости от того, как вы настроили свой проект и настроили его, вам, возможно, придется настроить машинописный текст, чтобы искать эти файлы специально, или он может просто работать без какой-либо настройки с вашей стороны.
Я работал только с TypeScript в проекте ASP.NET (классический), поэтому я не могу сказать вам, каков типичный способ сделать это. Но есть несколько неортодоксальных вариантов:
declare var $: any;
Я попытаюсь объяснить это на простом примере. Если вы используете сторонние библиотеки, такие как jQuery, в проектах Angular или машинописных текстах
Вы можете напрямую ссылаться на файл jquery (файл angular.json) в проектах Angular и писать код, указав $ или jQuery, как показано ниже
, как показано ниже
declare var $: any;
ngOnInit() {
$(document).ready(function() {
alert('I am Called From jQuery');
});
}
Код будет работать. Но проблема заключается в том, что машинопись - это проверка типов и обнаружение ошибок в коде только во время компиляции.
Так как машинопись не знает ничего о библиотеке jquery, она не может выполнять статическую проверку типов. приведенный ниже код компилируется без ошибок
ngOnInit() {
$(document).ready(function() {
$('#my-button').click(1);
});
}
Я передаю неверный параметр функции click jquery, и приведенный выше код будет компилироваться, и во время выполнения всякий раз, когда мы нажимаем на элемент кнопки, он выдаст ошибку.
Вот где набирает текст. Но если у вас есть определения типов для jquery plug, такие ошибки могут быть обнаружены только во время компиляции.
Установите наборы jquery из пакетов узлов и сослаться на них в коде
npm install --save jquery
npm install --save @types/jquery
И импортировать объект jquery в код, как показано ниже
import * as $ from 'jquery';
И теперь приведенный выше код не будет компилироваться и выдает ошибку, говоря
Argument of type ‘1’ is not assignable to parameter of type ‘false | EventHandlerBase<HTMLElement, ClickEvent<HTMLElement, null, HTMLElement, HTMLElement>>’
Вы можете прочитать больше на Как установить и использовать JQuery в угловых проектах
Что такое типизация?
Короче говоря, TypeScript добавляет статическую типизацию в JavaScript. Поскольку один только JavaScript не определяет такие определения типов, они должны быть написаны и включены в процесс компиляции TypeScript с помощью дополнительных механизмов. Другими словами, библиотека JavaScript может определять функцию:
export function createPerson(name, age, initScore) { ... }
Но в статически типизированной среде TypeScript для разработчика было бы гораздо полезнее иметь что-то подобное:
interface Person {
name: string,
age: number,
score: number
}
export function createPerson(name: string, age: number, initScore?: number): Person;
Цель объявлений типов , часто называемых типами , определений типов или просто типов , состоит в том, чтобы заполнить эти детали над реализациями, таким образом выявляя злоупотребления API даже между библиотеками. Они обычно находятся в файлах с расширением .d.ts
и могут быть собраны из файлов .ts
с использованием компилятора. Однако когда программы не были написаны на TypeScript, эти объявления обычно пишутся вручную.
С учетом вышесказанного ваша путаница несколько оправдана: со временем было сделано более одного подхода к установке и управлению объявлениями TypeScript. Однако сейчас есть официальные (и поэтому рекомендуемые) способы установки и использования файлов объявлений, и они задокументированы здесь :
В TypeScript 2.0 это стало значительно проще использовать файлы деклараций при их получении, использовании и поиске. На этой странице подробно рассказывается, как сделать все три
[...]
Для получения объявлений типов в TypeScript 2.0 и выше не требуется никаких инструментов, кроме npm.
Например, получить объявления для Angular так же просто, как установить эту зависимость в вашем проекте:
npm install --save @types/angular
Пакеты в пространстве имен @types
будут автоматически рассмотрены компилятором для получения объявления типа. Кроме того, если эти объявления уже встроены в пакет npm, вам не нужно делать ничего другого, кроме установки этого пакета (примером такого пакета является redux ). Для получения дополнительной информации см. Документы на tsconfig.json . Существует также целый раздел, посвященный созданию собственных файлов объявлений , который рекомендуется прочитать всем разработчикам, желающим добавить объявления типов в свои библиотеки.