如何防止Vue.js自动合并CSS类?

How to prevent Vue.js from automatically merging CSS classes?

我最近开始使用 Vue.js,我真的很喜欢它,但我遇到了一些我不知道该怎么做的事情。我已经搜索并阅读了文档,但没有找到解决方案。

当您将 CSS class 添加到您的任何组件时 Vue.js 将自动添加或合并 CSS classes 与根元素在您的子组件中。

这是一个不错的功能,但我需要为特定组件停用此功能,因为我希望将 classes 添加到根元素的子元素中。

我做这个fiddle是为了说明http://jsfiddle.net/rasmuswoelk/9m2j0a9s/3

<div id="demo">
  <child-component class="some-class"></child-component>
</div>

(正在自动添加 "some-class" 并添加绿色背景色)

如何防止 Vue.js 自动合并 CSS classes?

我认为您会希望将整个内容包装在另一个 <div></div> 中,因为 Vue 会合并顶部元素上的 类。如果您只想要 <h1> 的样式,请尝试这样做:

template: `<div><h1 class="child">Hello</h1></div>`

这应该会给你预期的行为,如果它不起作用请告诉我。

已更新 我不同意将应用于组件的 class 由该组件移动到内部元素是直观的,所以我的建议仍然是:将其作为道具传递。

但是,有一些注意事项,您可以做您想做的事。该组件将有一个属于外部元素的 classes 列表。在 mounted 中,它查看 $el.classList 并找到不在已知外部元素 class 中的 classes。那些被应用到内部元素并从外部元素中移除。警告:如果外部元素 classes 之一应用于组件,它将不会移动到内部元素。并且不会捕获对已应用 class 的任何更新。

Vue.component('child-component', {
  template: `<div :class="outerClasses"><h1 :class="childClasses">Hello</h1></div>`,
  data() {
    return {
      outerClasses: ['child'],
      childClasses: []
    };
  },
  mounted() {
    this.childClasses = Array.from(this.$el.classList).filter((c) => !this.outerClasses.includes(c));
    for (const c of this.childClasses) this.$el.classList.remove(c);
  }
});

var demo = new Vue({
  el: '#demo'
});
.child {
  border: 1px solid red;
  padding: 20px;
  text-align: center;
}

.some-class {
  background-color: green;
}
<script src="//vuejs.org/js/vue.min.js"></script>
<div id="demo">
  <child-component class="some-class a b c"></child-component>
</div>

您不能将模板中的包装器 div 抽象出来,并且尝试使组件以 div 不存在的方式工作只会导致混淆和不正确的样式。

假设您设法让您的组件将外部 class 应用于其模板中的嵌套元素(这正是您想要的)。现在,当人们使用该组件并对其应用 class 时,样式将应用于输入元素,就好像整个组件仅由输入元素组成,没有这样的包装器 div (这就是你想要的行为)。

这样做的问题是某些样式会起作用(如 background-color,或任何外观样式),但其他影响布局的样式将不起作用(如 position: absolute,因为它将导致输入元素相对于包装器 div 定位,这不是预期的)。

使用该组件的人应该了解模板的结构,以便他们可以正确设置样式,因为实际上 一个包装器 div 他们在那里需要考虑。

我应该提一下,您可以通过使用 Web 组件或影子 DOM 抽象出包装器 div,但这超出了 Vue 的上下文。

更简单的方法(imo)是将传入的class属性和动态class属性绑定到数据,并在[=13=期间将它们从vnode(虚拟节点)中删除]勾.

Vue.component('child-component', {
  template: `
    <div class="child">
      <h1 :class="staticClass">Hello</h1>
    </div>
  `,
  
  data() {
    return {
      staticClass: [],
    }
  },

  created() {
    // dynamic :class prop
    this.staticClass.push(this.$vnode.data.class)
    // delete if not applying on this.$el
    delete this.$vnode.data.class
    
    // static class attr
    this.staticClass.push(this.$vnode.data.staticClass)
    // delete if not applying on this.$el
    delete this.$vnode.data.staticClass
  },
});

var demo = new Vue({
  el: '#demo',

  data: {
    dynamicClass: 'dynamic-class'
  },
});
.child {
  border: 1px solid red;
  padding: 20px;
  text-align: center;
}

.some-class {
  background-color: green;
}

.dynamic-class {
  border: 1px solid yellow;
}
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>

<div id="demo">
  <child-component :class="dynamicClass" class="some-class"></child-component>
</div>