自定义 Web 组件,作用类似于 link(锚标记)
Custom web component that acts like a link (anchor tag)
我创建了一个自定义 Web 组件按钮,它具有 href
属性。如果单击按钮,我会使用 Javascript 导航到它自己的 href
属性。
不幸的是,在迁移了一个看起来像按钮的锚标记的大型代码库之后,我意识到我的自定义 Web 组件有很多缺点:
- 没有右键单击 link 上下文菜单。
- 例如无法右键单击并 select 在选项卡中打开。
- 无法通过 CTRL+单击在新选项卡中打开 link。
- 无法在新标签页中单击鼠标中键打开。
项目 2-3 可以在 Javascript 中修复,但项目 1 并非微不足道。
我做了一些关于使用 is
关键字扩展内置元素的研究,但这只是让我陷入了 Safari 拒绝实施用于扩展 [=36 的 Web 组件规范的错误报告中=] 元素.
是否有任何方法可以将锚标记的行为添加到自定义 Web 组件,例如通过混合?
只需使用 @ungap/custom-elements polyfill,您就可以使用 Safari 甚至 Internet Explorer,它们都具有自定义的内置元素和自主的自定义元素。
那么一个实现可能是这样的:
class CustomAnchor extends HTMLAnchorElement {
constructor() {
super();
this.addEventListener('click', this.click.bind(this));
}
click(event) {
if (event.getModifierState('Control') || event.getModifierState('Meta')) return; // allow control-click or cmd-click (mac) to work as usual
event?.preventDefault();
console.log(this.href);
// do whatever you like here
}
}
customElements.define('custom-anchor', CustomAnchor, { extends: 'a' });
<script src="//unpkg.com/@ungap/custom-elements"></script>
<a is="custom-anchor" href="https://google.com">Custom google anchor</a>
扩展内置的缺点是没有允许样式封装的shadowDOM。如果您需要,请改为使用自主自定义元素并在内部使用本机锚标记(甚至您的扩展内置 HTMLAnchorElement):
const styles = `
a { color: red; }
a:hover { background-color: yellow; }
`;
class CustomAnchor extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
const style = document.createElement('style');
style.textContent = styles;
this.anchor = document.createElement('a');
this.shadowRoot.append(style, this.anchor);
}
static get observedAttributes() { return ['link', 'text']; }
attributeChangedCallback(attr, oldVal, newVal) {
if (oldVal === newVal) return; // nothing changed
switch (attr) {
case 'link':
if (newVal) this.anchor.href = newVal;
else this.anchor.removeAttribute('href');
break;
case 'text':
this.anchor.textContent = newVal ?? '';
break;
default:
}
}
}
customElements.define('custom-anchor', CustomAnchor);
<script src="//unpkg.com/@ungap/custom-elements"></script>
<custom-anchor link="https://google.com" text="Google Search"></custom-anchor>
如果您更喜欢(例如出于屏幕阅读器和 SEO 原因)将 link 文本作为元素的内容,请输入默认值 <slot>
:
const styles = `
a { color: red; }
a:hover { background-color: yellow; }
`;
class CustomAnchor extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
const style = document.createElement('style');
style.textContent = styles;
this.anchor = document.createElement('a');
const slot = document.createElement('slot');
this.anchor.appendChild(slot);
this.shadowRoot.append(style, this.anchor);
}
static get observedAttributes() { return ['link']; }
attributeChangedCallback(attr, oldVal, newVal) {
if (oldVal === newVal) return; // nothing changed
switch (attr) {
case 'link':
if (newVal) this.anchor.href = newVal;
else this.anchor.removeAttribute('href');
break;
default:
}
}
}
customElements.define('custom-anchor', CustomAnchor);
<script src="//unpkg.com/@ungap/custom-elements"></script>
<custom-anchor link="https://google.com">Google Search</custom-anchor>
只需包装一个 link 并将其设置为按钮。
点击代码片段中的link无效,因此我也为它创建了一个codepen。 https://codepen.io/waxolunist/pen/ZEXwQYa
<script type="module">
import {
LitElement,
html,
css
} from "https://unpkg.com/lit-element/lit-element.js?module";
class MyLinkButton extends LitElement {
static get properties() {
return {
href: { type: String, reflect: true },
};
}
static get styles() {
return css`
.button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
.button:hover {background-color: #220440}
.button:active {
background-color: #230545;
box-shadow: 0 5px #e1d5ed;
transform: translateY(4px);
}
`;
}
render() {
return html`
<a class="button" href="${this.href}" target="_blank">
<slot></slot>
</a>
`;
}
}
customElements.define("my-linkbutton", MyLinkButton);
</script>
<my-linkbutton href="http://example.com">SOME TEXT</my-linkbutton>
抱歉,如果 unpkg 又慢了。
我创建了一个自定义 Web 组件按钮,它具有 href
属性。如果单击按钮,我会使用 Javascript 导航到它自己的 href
属性。
不幸的是,在迁移了一个看起来像按钮的锚标记的大型代码库之后,我意识到我的自定义 Web 组件有很多缺点:
- 没有右键单击 link 上下文菜单。
- 例如无法右键单击并 select 在选项卡中打开。
- 无法通过 CTRL+单击在新选项卡中打开 link。
- 无法在新标签页中单击鼠标中键打开。
项目 2-3 可以在 Javascript 中修复,但项目 1 并非微不足道。
我做了一些关于使用 is
关键字扩展内置元素的研究,但这只是让我陷入了 Safari 拒绝实施用于扩展 [=36 的 Web 组件规范的错误报告中=] 元素.
是否有任何方法可以将锚标记的行为添加到自定义 Web 组件,例如通过混合?
只需使用 @ungap/custom-elements polyfill,您就可以使用 Safari 甚至 Internet Explorer,它们都具有自定义的内置元素和自主的自定义元素。
那么一个实现可能是这样的:
class CustomAnchor extends HTMLAnchorElement {
constructor() {
super();
this.addEventListener('click', this.click.bind(this));
}
click(event) {
if (event.getModifierState('Control') || event.getModifierState('Meta')) return; // allow control-click or cmd-click (mac) to work as usual
event?.preventDefault();
console.log(this.href);
// do whatever you like here
}
}
customElements.define('custom-anchor', CustomAnchor, { extends: 'a' });
<script src="//unpkg.com/@ungap/custom-elements"></script>
<a is="custom-anchor" href="https://google.com">Custom google anchor</a>
扩展内置的缺点是没有允许样式封装的shadowDOM。如果您需要,请改为使用自主自定义元素并在内部使用本机锚标记(甚至您的扩展内置 HTMLAnchorElement):
const styles = `
a { color: red; }
a:hover { background-color: yellow; }
`;
class CustomAnchor extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
const style = document.createElement('style');
style.textContent = styles;
this.anchor = document.createElement('a');
this.shadowRoot.append(style, this.anchor);
}
static get observedAttributes() { return ['link', 'text']; }
attributeChangedCallback(attr, oldVal, newVal) {
if (oldVal === newVal) return; // nothing changed
switch (attr) {
case 'link':
if (newVal) this.anchor.href = newVal;
else this.anchor.removeAttribute('href');
break;
case 'text':
this.anchor.textContent = newVal ?? '';
break;
default:
}
}
}
customElements.define('custom-anchor', CustomAnchor);
<script src="//unpkg.com/@ungap/custom-elements"></script>
<custom-anchor link="https://google.com" text="Google Search"></custom-anchor>
如果您更喜欢(例如出于屏幕阅读器和 SEO 原因)将 link 文本作为元素的内容,请输入默认值 <slot>
:
const styles = `
a { color: red; }
a:hover { background-color: yellow; }
`;
class CustomAnchor extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
const style = document.createElement('style');
style.textContent = styles;
this.anchor = document.createElement('a');
const slot = document.createElement('slot');
this.anchor.appendChild(slot);
this.shadowRoot.append(style, this.anchor);
}
static get observedAttributes() { return ['link']; }
attributeChangedCallback(attr, oldVal, newVal) {
if (oldVal === newVal) return; // nothing changed
switch (attr) {
case 'link':
if (newVal) this.anchor.href = newVal;
else this.anchor.removeAttribute('href');
break;
default:
}
}
}
customElements.define('custom-anchor', CustomAnchor);
<script src="//unpkg.com/@ungap/custom-elements"></script>
<custom-anchor link="https://google.com">Google Search</custom-anchor>
只需包装一个 link 并将其设置为按钮。
点击代码片段中的link无效,因此我也为它创建了一个codepen。 https://codepen.io/waxolunist/pen/ZEXwQYa
<script type="module">
import {
LitElement,
html,
css
} from "https://unpkg.com/lit-element/lit-element.js?module";
class MyLinkButton extends LitElement {
static get properties() {
return {
href: { type: String, reflect: true },
};
}
static get styles() {
return css`
.button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
.button:hover {background-color: #220440}
.button:active {
background-color: #230545;
box-shadow: 0 5px #e1d5ed;
transform: translateY(4px);
}
`;
}
render() {
return html`
<a class="button" href="${this.href}" target="_blank">
<slot></slot>
</a>
`;
}
}
customElements.define("my-linkbutton", MyLinkButton);
</script>
<my-linkbutton href="http://example.com">SOME TEXT</my-linkbutton>
抱歉,如果 unpkg 又慢了。