0

我已经构建了一个无渲染的基本图标 Vue 组件,它只输出其插槽中的任何内容,但在插槽组件中添加了一些附加属性。我设置的属性之一是class="icon"允许我将所有图标的样式放在一个地方。

图标.vue

<script>
import Vue from "vue";

export default {
  name: "u-icon",
  render(createElement) {
    const svg = this.$slots.default[0];
    const attrs = svg.data.attrs;

    attrs.xmlns = "http://www.w3.org/2000/svg";
    attrs.class = "icon";
    attrs["aria-hidden"] = "true";
    attrs.focusable = "false";
    attrs.role = "img";

    return this.$slots.default;
  },
};
</script>

<style>
.icon {
  // ...
}
</style>

关闭图标.vue

然后我可以更轻松地创建许多不同的图标组件,例如这个关闭图标组件。

<template>
  <u-icon>
    <svg viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
      <line x1="4" y1="4" x2="20" y2="20"></line>
      <line x1="4" y1="20" x2="20" y2="4"></line>
    </svg>
  </u-icon>
</template>

<script>
import icon from "~/icon.vue";
export default {
  name: "close-icon",
  components: {
    "u-icon": icon,
  },
};
</script>

实际结果

问题是当我使用close-icon组件并设置class如下:

<close-icon class="foo"/>

呈现的输出没有结合这两个类"icon foo"

<svg class="foo" ...>
  ...
</svg>

预期结果

如何确保该类不被覆盖而是附加到,以便输出为:

<svg class="icon foo" ...>
  ...
</svg>

如果可能,应该对我所做的任何更改进行更改,Icon.vue并且我想避免更改,Close-Icon.vue因为还有大量其他图标。

4

1 回答 1

1

class并且style绑定不是$attrs的一部分-来源

我不确定为什么您的代码甚至可以在没有class绑定的情况下工作,close-icon 但是如果您想添加/修改现有 VNode 的类(来自默认插槽),您应该使用svg.data.staticClass而不是svg.data.attrs.class

下面的示例甚至处理了静态类也直接放在svg内部元素上的情况close-icon- 渲染<svg class="foo bar icon" ...

Vue.component("u-icon", {  
  render(createElement) {
    const svg = this.$slots.default[0];
    const attrs = svg.data.attrs;
    
    attrs.xmlns = "http://www.w3.org/2000/svg";
    attrs["aria-hidden"] = "true";
    attrs.focusable = "false";
    attrs.role = "img";
    
    svg.data.staticClass = (svg.data.staticClass || "") + " icon";

    return this.$slots.default;
  },
});

Vue.component("close-icon", {
  template:`
  <u-icon>
    <svg viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" class="bar">
      <line x1="4" y1="4" x2="20" y2="20"></line>
      <line x1="4" y1="20" x2="20" y2="4"></line>
    </svg>
  </u-icon>
  `
})

new Vue({
  el: "#app"
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<div id="app">
  <close-icon class="foo"></close-icon>
</div>

于 2021-10-07T10:18:24.480 回答