如何在自定义组件中嵌入链接作为插槽?



我正在尝试创建一个包含一些动画的简单组件。我为链接的文本设置了名称属性。我为链接的目标设置了一个插槽,但模板不允许将链接设置为插槽。我不确定接下来要尝试什么。

当我将鼠标悬停在链接上时,它只是说<slot name=而不是实际的 URL。

const template = document.createElement('template');
template.innerHTML = `
<style>
.txt-link a {
color: #005fec;
font-weight: 700;
font-size: 18px;
text-decoration: none;
position: relative;
}
.txt-link a:hover {
text-decoration: none;
cursor: pointer;
}
.txt-link a::before {
content: "";
position: absolute;
bottom: -5px;
left: 0;
width: 0;
height: 1px;
background-color: #005fec;
visibility: hidden;
transition: all 0.3s ease-in-out 0s;
}
.txt-link a:hover::before {
visibility: visible;
width: 100%;
}
.txt-link.arrow-link img {
height: 15px;
position: relative;
top: 2px;
}
</style>
<div class="txt-link arrow-link">
<a href="<slot name="destination" />"></a>
<img alt="arrow right icon" class="learn-more-arrow" src="https://www.pikpng.com/pngl/m/73-734729_arrow-blue-right-transparent-blue-arrow-right-clipart.png" loading="lazy">
</div>
`;
class CustomAnimLink extends HTMLElement {
constructor() {
super();
this.showInfo = true;
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(template.content.cloneNode(true));
this.shadowRoot.querySelector('a').innerText = this.getAttribute('name');
}
}
window.customElements.define('custom-anim-link', CustomAnimLink);
<custom-anim-link name="Learn more">
<div slot="destination">https://www.yahoo.com</div>
</custom-anim-link>

你不能用插槽做到这一点。插槽用于将HTMLElement放置在插槽的位置,不能用于其他任何用途。

而是将 URL 作为属性传递。这似乎适用于数据类型。Web组件有一些很好的生命周期来帮助你解决这个问题。

我添加了static get observedAttributes()来指示应遵守某些属性。这样做将使您能够在更改其中一个属性中的值时执行某些操作,例如更新 Shadow DOM 中定位点上的 URL。

每当观察到的属性值发生变化时,都会调用attributeChangedCallback,您可以在其中确定值更改时应发生的情况。

observedAttributesattributeChangedCallback都是 Web 组件生命周期挂钩的一部分。

const template = document.createElement('template');
template.innerHTML = `
<style>
.txt-link a {
color: #005fec;
font-weight: 700;
font-size: 18px;
text-decoration: none;
position: relative;
}
.txt-link a:hover {
text-decoration: none;
cursor: pointer;
}
.txt-link a::before {
content: "";
position: absolute;
bottom: -5px;
left: 0;
width: 0;
height: 1px;
background-color: #005fec;
visibility: hidden;
transition: all 0.3s ease-in-out 0s;
}
.txt-link a:hover::before {
visibility: visible;
width: 100%;
}
.txt-link.arrow-link img {
height: 15px;
position: relative;
top: 2px;
}
</style>
<div class="txt-link arrow-link">
<a href=""><slot></slot></a>
<img alt="arrow right icon" class="learn-more-arrow" src="https://www.pikpng.com/pngl/m/73-734729_arrow-blue-right-transparent-blue-arrow-right-clipart.png" loading="lazy">
</div>
`;
class CustomAnimLink extends HTMLElement {
static get observedAttributes() {
return ['name', 'destination'];
}
constructor() {
super();
this.showInfo = true;
this.attachShadow({
mode: 'open'
});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
get anchor() {
return this.shadowRoot.querySelector('a');
}
get name() {
return this.getAttribute('name');
}
set name(value) {
if ('string' === typeof value) {
this.setAttribute('name', value);
}
}
get destination() {
return this.getAttribute('destination');
}
set destination(value) {
if ('string' === typeof value) {
this.setAttribute('destination', value);
}
}
attributeChangedCallback(attrName, oldValue, newValue) {
switch (attrName) {
case 'destination':
this.anchor.href = newValue;
break;
case 'name':
this.anchor.textContent = newValue;
break;
}
}
}
window.customElements.define('custom-anim-link', CustomAnimLink);
<custom-anim-link name="Learn more" destination="https://www.yahoo.com"></custom-anim-link>

或者,您可以在插槽的位置传递<a>标记。然后获取分配给destination槽的所有元素,并根据name属性的值设置textContent属性。我们在上一个示例中添加的destination属性也是如此。

const template = document.createElement('template');
template.innerHTML = `
<style>
.txt-link a {
color: #005fec;
font-weight: 700;
font-size: 18px;
text-decoration: none;
position: relative;
}
.txt-link a:hover {
text-decoration: none;
cursor: pointer;
}
.txt-link a::before {
content: "";
position: absolute;
bottom: -5px;
left: 0;
width: 0;
height: 1px;
background-color: #005fec;
visibility: hidden;
transition: all 0.3s ease-in-out 0s;
}
.txt-link a:hover::before {
visibility: visible;
width: 100%;
}
.txt-link.arrow-link img {
height: 15px;
position: relative;
top: 2px;
}
</style>
<div class="txt-link arrow-link">
<slot name="destination"></slot>
<img alt="arrow right icon" class="learn-more-arrow" src="https://www.pikpng.com/pngl/m/73-734729_arrow-blue-right-transparent-blue-arrow-right-clipart.png" loading="lazy">
</div>
`;
class CustomAnimLink extends HTMLElement {
static get observedAttributes() {
return ['name', 'destination'];
}
constructor() {
super();
this.showInfo = true;
this.attachShadow({
mode: 'open'
});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
get destinations() {
const slot = this.shadowRoot.querySelector('slot');
const assignedElements = slot.assignedElements();
return assignedElements;
}
get name() {
return this.getAttribute('name');
}
set name(value) {
if ('string' === typeof value) {
this.setAttribute('name', value);
}
}

get destination() {
return this.getAttribute('destination');
}
set destination(value) {
if ('string' === typeof value) {
this.setAttribute('destination', value);
}
}

attributeChangedCallback(attrName, oldValue, newValue) {
switch(attrName) {
case 'name':
this.destinations.forEach(destination => {
destination.textContent = newValue;
});

break;
case 'destination':
this.destinations.forEach(destination => {
destination.href = newValue;
});

break;
}
}
}
window.customElements.define('custom-anim-link', CustomAnimLink);
<custom-anim-link name="Learn more" destination="https://www.yahoo.com">
<a slot="destination"></a>
</custom-anim-link>

或者作为最后的简单手段,只需将<a>作为子元素完整地传递给您的自定义元素即可。

<custom-anim-link>
<a href="https://www.yahoo.com">Learn more</a>
</custom-anim-link>

如果您只想在创建 Web 组件时在 a 标签中设置 href,使用数据标签会容易得多:

class CustomAnimLink extends HTMLElement {
constructor() {
super();
this.showInfo = true;
this.attachShadow({ mode: 'open' });
let template = document.getElementById("github-link-template");
this.shadowRoot.appendChild(template.content.cloneNode(true));
this.shadowRoot.querySelector('a').href= this.dataset.href;
}
}
window.customElements.define('custom-anim-link', CustomAnimLink);

然后

<custom-anim-link data-href="https://www.yahoo.com"></custom-anim-link>

对于 a 标签的实际内容("了解更多"),您应该能够毫无问题地使用插槽。

最新更新