我正在尝试将以下代码改编为 Angular,涉及 Text 元素:
function setAxisValue(name, value)
{
var axis = document.getElementById(name)
if(!axis)
return
var text = document.getElementById(name+"Text")
if(!text)
return
axis.style.width = ((100*value).toFixed(1) + "%");
text.innerHTML = ((100*value).toFixed(0) + "%");
if (text.offsetWidth > axis.offsetWidth)
text.style.visibility = "hidden";
else
text.style.visibility = "visible";
}
这适用于大量元素,具体取决于不同的名称和相应的值。
我通过使用
{{...}}
插值解决了 innerHTML 部分,并使用 [style.width]="..."
解决了宽度部分(当然使用表达式而不是省略号)。<span id="...Text" [style.visibility]="getVisibility()">
在语法方面是可行的,但问题是该函数需要访问其被调用的 DOM 元素,以提取其 offsetWidth 及其父元素的 offsetWidth (是的,axis 元素系统地是文本元素的父元素)。
我怎样才能做到这一点?
事件侦听器语法
(keyup)="..."
有一个特殊变量
$event
来访问引发调用的事件(或将其传递给函数),但是没有匹配的
$element
用于方括号属性绑定(这会给出方便的
[style.visibility]="getVisibility($element)"
)。我读到了有关在 Component 类的某种 onInit 方法中添加一些代码的内容,以向受选择器表达式约束的所有元素添加回调。好的方面是 DOM 元素可用于回调,因为它是我调用 addEventListener 的对象。不好的方面是我不知道它应该监听什么事件:可见性的驱动应该是每次两个元素的 offsetWidth 发生变化时(例如,包括窗口大小调整时)。
最后,我看到了名为 ViewChild / ViewChildren 的东西,据说可以让组件访问 DOM 对象。问题是,我对它了解甚少,选择器似乎与我想要寻找的东西不匹配:
.someclass div span
CSS选择器表达式。相反,它似乎只遵循 Angular 特定的机制来选择 DOM 元素。另外,假设我在组件中获取了该计算应该发生的所有元素的集合,并将绑定函数
[style.visibility]="getVisibility()"
附加到每个元素。仍然存在一个问题,当我在函数内部时,我应该猜测哪个元素(在集合中的所有元素中)我应该读取(以及父级的 offsetWidth)的 offsetWidth 来计算和返回可见性。
@Directive({
selector: '[DynamicAxis]',
standalone: true,
})
export class DynamicAxisDirective {
@Input() name!: string;
@Input() value: number = 0;
constructor(private element: ElementRef, private renderer: Renderer2) {}
ngOnChanges() {
var axis = document.getElementById(this.name);
if (!axis) return;
axis.style.width = (100 * this.value).toFixed(1) + '%';
const text = this.element?.nativeElement;
text.innerHTML = (100 * this.value).toFixed(0) + '%';
this.renderer.setStyle(
text,
'visibility',
text.offsetWidth > axis.offsetWidth ? 'hidden' : 'visible'
);
}
}
我们使用 [name]="test"
属性绑定将输入变量作为输入属性传递,并使用它们来执行逻辑。我们使用
ElementRef
,它是放置指令的元素引用。我将把它放在 span 元素上。
<span id="...Text" DynamicAxisDirective [name]="'test'" [value]="70">
我们可以使用Renderer2
来设置样式、类等。为什么用这个而不是传统的JS,因为数据会自动处理。我更希望您传入
axis
作为模板引用变量,而不是使用 `getElementById,因为这更像是角度方法。
<div id="test" #axis>axis</div>
...
<span id="...Text" DynamicAxisDirective [name]="'test'" [value]="70" [axis]="axis">
然后您可以使用这个传入的值并通过 ID 部分删除获取元素。这样一切都以有角度的方式完成。