HTML
<div class = "tableRow">
<div id = "0-0">
<p>Point {{levelOne}}</p>
</div>
<div id = "0-1" (click) = "select($event)">
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod </li>
</div>
<div id = "0-2" (click) = "select($event)">
<li >Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod. </li>
</div>
<div id = "0-3" (click) = "select($event)">
<li>
Lorem ipsum dolor sit amet,
</li>
</div>
<div id = "0-4" (click) = "select($event)">
<li>Lorem ipsum dolor sit amet, consectetur adipiscing</li>
<li>lorem ipsum dolor</li>
</div>
<div id = "0-5" (click) = "select($event)">
<li>Lorem ipsum dolor sit amet, consectetur adipiscing</li>
</div>
</div>
CSS
.tableRow {
width: 90%;
display: grid;
grid-template-columns: 10% 18% 18% 18% 18% 18%;
}
.tableRow > div {
background: $white;
padding: 1em;
border: 1px solid $purple-70;
text-align: center;
cursor: pointer;
}
.tableRow > div:first-child {
font-weight: bold;
background: $purple-10;
cursor: default;
}
.selected {
background-color: red !important;
}
TS
import { Component, OnInit } from "@angular/core";
@Component({
selector: "example",
templateUrl: "./example.component.html"
})
export class Example implements OnInit {
public levelOne: Number = 1;
public levelTwo: Number = 3;
public levelThree: Number = 9;
public LevelFour: Number = 27;
public selected = false;
constructor() {}
ngOnInit() {}
select($event) {
let id = $event.target.id;
if ($event.target.localName !== "div") {
let id = $event.target.parentElement.id;
}
console.info(id);
}
}
со следующим кодом, щелчок за пределами элемента li приводит к тому, что id устанавливается на фактический идентификатор, но когда я нажимаю на элемент li внутри идентификатора div, устанавливается значение undefined ... однако, если я регистрирую $ event.target.parentElement.id на консоли, он напечатает правильный ID при нажатии на элемент li.
Я почти уверен, что если я смогу получить правильный идентификатор, захваченный при щелчке, я могу использовать его для назначения стиля (например, изменить цвет фона div)
Я не уверен, что делаю не так, или вообще есть способ лучше?
Обычно это плохая практика (по слишком многим причинам, чтобы перечислять здесь) напрямую обращаться к dom при использовании angular. С помощью инструментов, предоставляемых Angular, вы можете делать практически все, что угодно, например:
<div [class.selected] = "div1Selected" (click) = "div1Selected = !div1Selected">
Has class `selected` when component's property `div1Selected` is true.
</div>
Да. Это не "угловой способ" зависеть от идентификаторов элементов ... Делая это, вы упускаете большую часть реальной силы Angular, и было бы лучше узнать, как добиться чего-то, не прибегая к этому.
Я обычно понимаю причины, по которым не читаются собственные свойства DOM, но в какой альтернативной среде было бы проблематично читать идентификаторы? Не могли бы вы просто проверить, является ли цель HTMLElement и есть ли у нее идентификатор, и если да, то использовать его? Если нет, прибегнуть к другому методу таргетинга? Мне искренне любопытно, т.к. я иногда использую этот метод в своем собственном коде в качестве альтернативы созданию потенциально тысяч отдельных прослушивателей событий или отдельных компонентов внутри циклов ngFor. Я программно привязываю идентификатор к чему-то уникальному с помощью id = "{{any}}", а затем выбираю w, что
В цикле * ngFor вы можете просто передать текущий элемент функции, например. * ngFor = "let item of items" (click) = "clicked (item)"
и предположим, что вы хотите изменить стиль элемента, по которому щелкнули мышью, просто переключите какой-либо флаг в элементе, например. item.selected =! item.selected, а затем вы можете привязать его к классу стиля
Но тогда это создает отдельный прослушиватель событий для каждого элемента, сгенерированного циклом for, верно? Вот чего я пытался избежать. Это становится проблематичным, если я, скажем, использую цикл for для создания тысяч строк в электронной таблице. Я всегда предполагал, что одноразовая привязка идентификатора более производительна, чем отдельные, постоянно включенные слушатели.
Да, но это не особо важно. У вас могут быть десятки тысяч элементов с привязкой (щелчком), прежде чем это станет напряжением. И рендеринг dom, вероятно, сам по себе является большим стрессом. В таком случае в любом случае потребуется разбивка на страницы или виртуальная прокрутка.
Но да, на мой взгляд, в некоторых случаях вполне нормально использовать общий прослушиватель кликов для всей таблицы, например, если вам не нужна разбивка на страницы :)
проверьте эту потрясающую виртуальную библиотеку прокрутки, кстати. Действительно эффективен, когда вы визуализируете только те элементы, которые соответствуют области просмотра и повторно используете элементы :) github.com/aminpaks/angular-virtual-list
Интересно ... Я думаю, мне нужно провести несколько тестов между привязкой тысяч идентификаторов и созданием тысяч слушателей. Я всегда предполагал, что один из них намного эффективнее другого, но, честно говоря, никогда не тестировал его. Это действительно единственный вариант использования, в котором я полагаюсь на идентификаторы. если это не имеет большого значения, я проведу рефакторинг своего кода! Спасибо за совет
Я бы просто использовал привязку стиля, чтобы привязать любой стиль, который вы хотите, к родительскому div, а затем использовать щелчки дочернего div, чтобы изменить значение строки, привязанной к этому стилю.
<div class = "tableRow" [style.background] = "myStyle">
<div id = "0-0">
<p>Point {{levelOne}}</p>
</div>
<div id = "0-1" (click) = "myStyle = 'red'">
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod </li>
</div>
<div id = "0-2" (click) = "myStyle = 'blue'">
<li >Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod. </li>
</div>
<div id = "0-3" (click) = "myStyle = 'green'">
<li>
Lorem ipsum dolor sit amet,
</li>
</div>
<div id = "0-4" (click) = "myStyle = 'orange'">
<li>Lorem ipsum dolor sit amet, consectetur adipiscing</li>
<li>lorem ipsum dolor</li>
</div>
<div id = "0-5" (click) = "myStyle = 'magenta'">
<li>Lorem ipsum dolor sit amet, consectetur adipiscing</li>
</div>
</div>
Составная часть
import { Component, OnInit } from "@angular/core";
@Component({
selector: "example",
templateUrl: "./example.component.html"
})
export class Example implements OnInit {
public levelOne: Number = 1;
public levelTwo: Number = 3;
public levelThree: Number = 9;
public LevelFour: Number = 27;
myStyle = 'inherit';
public selected = false;
constructor() {}
ngOnInit() {}
В качестве альтернативы, если вы хотите уменьшить количество прослушивателей событий, которые вы добавляете на свою страницу, вы можете просто установить один прослушиватель событий в родительском div и использовать идентификатор $ event.target для проверки целевого дочернего div и установить строка на основе этой цели.
<div class = "tableRow" [style.background] = "myStyle" (click) = "setStyle($event)">
Затем просто добавьте в свой компонент функцию, аналогичную той, что у вас уже есть.
select($event) {
let id = ($event.target as HTMLElement).id;
// here you could add a a switch case that sets the myStyle string based on the id of the clicked element
Является ли просто чтение идентификатора цели MouseEvent «прямым доступом к DOM»? Angular и TypeScript изначально поддерживают объекты MouseEvent. Вы даже можете присвоить им соответствующий тип. выберите ($ event: MouseEvent), а затем Intellisense TypeScript покажет вам, какие именно свойства / методы доступны для этого события.