【问题标题】:Create a height and width attribute for a custom HTML element为自定义 HTML 元素创建高度和宽度属性
【发布时间】:2019-07-02 05:02:52
【问题描述】:

我正在创建自定义 html 标签/元素,然后将通过 JavaScript/jQuery 动态添加这些标签/元素。我的最终目标是创建一个像<xt-vertical-layout height="30px" width="50px"></xt-vertical-layout> 这样的自定义元素,其中高度和宽度将设置渲染大小。我已经想出了如何创建自定义元素并拥有可以保存数据的自定义属性,但我似乎找不到修改渲染的方法。需要明确的是,我没有遇到 CSS 高度和宽度不起作用的问题。我的问题是,我可能有数百个大小不一的元素,这些元素在文档加载后被注入到 DOM 之前是未知的。

我最初研究了带有属性选择器的 CSS,但它似乎无法将属性的值向下传递到 CSS 规则中。同样,我研究了 CSS 的 attr() 函数,但似乎这只适用于 content。我发现了一些关于 CSS4 中所有属性都允许使用此功能的文档,尽管然后我读到一些内容说 CSS4 将不会被发布,而是 CSS 将开始按模块更新,所以似乎这还没有成为当前标准.

我们将不胜感激任何可以阐明这个主题的信息。我觉得有一些方法可以做到这一点,但不太确定如何。不过要明确一点,我不希望使用 JavaScript/jQuery 解析标记并使用 $().css() 或类似的东西修改该元素,因为这会修改实际标记。我的愿望是保持标记不变,属性修改渲染,类似于<img/> 标签的工作方式。

编辑: 我不介意在自定义元素的构造函数中使用 JS/jQuery 执行此操作,如果它可以在不修改内联 style 属性的情况下完成,并且保持标记不变。

【问题讨论】:

  • 除非你考虑内联样式,否则我认为你不能用 CSS 做到这一点。我猜你有义务做一些 JS
  • style="height:30px"?
  • 是的,在这种情况下这很简单,但你有内联样式,如果你想稍后应用另一个 CSS,你必须处理特殊性问题
  • 还有,你说的那个JS,是指修改内联样式属性,还是在自定义元素的构造函数中?如果这是第二个,我会喜欢(实际上更喜欢)那个。
  • 用 JS 可以做很多事情。第一个想法是更改样式属性,但我们可以做其他事情,例如使用随机类/ID 为该元素生成唯一的 CSS

标签: javascript html css


【解决方案1】:

您通常会在您的 CustomElement 的类 connectedCallback 中处理此问题,在那里您将能够以 this 的身份访问节点,如果它继承自 HTMLElement,则它的 DOM 方法(如 getAttribute())。

class VerticalLayout extends HTMLElement {
  constructor() {
    super();
  }
  connectedCallback() {
    this.style.width = this.getAttribute('width');
    this.style.height = this.getAttribute('height');
  }
}
customElements.define('xt-vertical-layout', VerticalLayout);

// dynamically inserted
const elem = document.createElement('xt-vertical-layout');
elem.setAttribute('width', '25px');
elem.setAttribute('height', '25px');
document.body.append(elem);
xt-vertical-layout {
  border: 1px solid;
  display: inline-block;
}
<xt-vertical-layout height="30px" width="50px"></xt-vertical-layout>

<xt-vertical-layout height="50px" width="150px"></xt-vertical-layout>

<xt-vertical-layout height="10px" width="50px"></xt-vertical-layout>

如果你真的不想修改序列化的 DOM,那么你可以在元素的 shadowDOM 中附加一个样式表,并在那里设置一个规则。但请注意,这样做,您将失去对旧版浏览器的支持,因为无法填充此功能。

class VerticalLayout extends HTMLElement {
  constructor() {
    super();
  }
  connectedCallback() {
    const shadow = this.attachShadow({mode: 'open'});
    const style = document.createElement('style');
    style.textContent = `:host {
  width: ${ this.getAttribute('width') };
  height: ${ this.getAttribute('height') };
}`;
    shadow.append(style);
  }
}
customElements.define('xt-vertical-layout', VerticalLayout);

// dynamically inserted
const elem = document.createElement('xt-vertical-layout');
elem.setAttribute('width', '25px');
elem.setAttribute('height', '25px');
container.append(elem);

console.log(container.innerHTML);
xt-vertical-layout {
  border: 1px solid;
  display: inline-block;
}

.as-console-wrapper {max-height: 120px !important;}
<div id="container">
<xt-vertical-layout height="30px" width="50px"></xt-vertical-layout>

<xt-vertical-layout height="50px" width="150px"></xt-vertical-layout>

<xt-vertical-layout height="10px" width="50px"></xt-vertical-layout>
  
</div>

【讨论】:

  • 我想要的是能够在不修改标记本身的情况下做到这一点。以您的方式进行操作时,标记会添加内联属性style。拉取属性值的 CSS 规则可以做到这一点,但这似乎只适用于 content 属性。
  • @Xandor 如果您可以使用 shadowDOM,您可以在元素的 shadowDOM 中附加一个样式表,但是您将失去对许多旧浏览器的支持(这不能被填充) .为什么不能更改 style 属性?
  • 目前,失去对旧浏览器的支持对我来说并不是什么大问题,我正在做的事情本身就是实验性的。不更改标记对我来说不是一个交易破坏者,但它会非常受欢迎。本质上,我正在尝试编写一种标记语言,以适应我已经构建的系统,该系统用完网络浏览器。这个想法是人们将能够为它发展。考虑到这一点,如果标记保持不变,共享/观察其他代码对于第一次学习它的人来说会更直观。
  • 话虽如此,我认为这个 shadowDOM 将是我现在最接近幕后的东西。非常感谢!
  • 在你的立场上,我宁愿将标记和 DOM 保持为两个独立的东西。用户提供标记,您的页面生成 DOM。只要您保持标记干净(如在字符串变量中),就无需担心修改 DOM。所需要的只是一些比浏览器的开发工具更吸引人的 UI(取决于您的目标用户群,它或多或少容易)。
【解决方案2】:

自定义标签将显示内联,不能有宽度和高度。您需要显示块或内联块。

addContent('Here is some content', 200, 50);

function addContent(content, width, height) {
  const elm = document.createElement('xt-vertical-layout');
  elm.setAttribute('style', `width: ${width}px; height: ${height}px;`);
  elm.innerText = content;
  document.body.append(elm);
}
xt-vertical-layout {
  display: inline-block;
  color: white;
  padding: 5px;
  background-color: red;
}

【讨论】:

  • 如果我没有在我的问题中解释得足够好,我深表歉意,但这根本不是我的问题。我的问题是我将拥有多个这些自定义标签,并且我想通过使用内联宽度和高度属性来设置宽度和高度。问题是在加载元素之前我不会知道所需的高度和宽度。它们不会都具有相同的大小,并且会有很大差异。我无法使用静态 CSS 规则来实现这一点。
  • 编辑为动态
  • 再一次,这根本不能回答我的问题。我希望能够在不修改标记的情况下获得这种效果(即,我不希望在处理后添加内联样式属性),而是希望在幕后完成更多。
猜你喜欢
  • 1970-01-01
  • 2012-08-13
  • 2021-03-11
  • 1970-01-01
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 1970-01-01
相关资源
最近更新 更多