【问题标题】:How to prevent Vue.js from automatically merging CSS classes?如何防止 Vue.js 自动合并 CSS 类?
【发布时间】:2017-03-31 10:49:03
【问题描述】:

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

当您向任何组件添加 CSS 类时,Vue.js 会自动添加或合并 CSS 类与子组件中的根元素。

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

我做了这个小提琴来说明http://jsfiddle.net/rasmuswoelk/9m2j0a9s/3

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

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

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

【问题讨论】:

  • 您在寻找scoped-css
  • 所以你想得到&lt;div class="child"&gt;&lt;h1 class="some-class"&gt;Hello&lt;/h1&gt;&lt;/div&gt;
  • @Saurabh 不——它与作用域 css 无关。
  • @str 是的,基本上。必须有一种非 hacky 的方式来实现这一点。
  • 这对我来说听起来像是一个 XY 问题。 Vue 正确地合并了这些类,因为 &lt;child-component&gt; 标记实际上被替换为该组件的模板的根元素,它本身可能有类。你不能阻止 Vue 这样做。您能否更详细地解释一下您希望组件如何工作?您说您希望将该类添加到根元素的子元素中,那么为什么不制作一个道具(例如“customClass”),然后您可以将其绑定到您想要的特定子组件的类,例如@987654323 @?

标签: javascript vue.js vuejs2


【解决方案1】:

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

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

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>

【讨论】:

  • 当然可以。但这个想法是使用传递 props 的常规方式,因此对于使用组件的其他开发人员来说更直观。
  • 好吧,所以这是可能的。但我想如果我只是将它作为道具传递,它会少很多hacky。我会将您的答案标记为正确,因为它实际上解决了我正在寻找的问题 - 即使我希望有一种更简单的方法:-)
【解决方案2】:

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

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

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

【讨论】:

  • 是的,但它必须是动态类。因此,如果我制作一个组件,例如&lt;form-input class="input-big" /&gt; 它将自动将类添加到包装器元素中,因为我需要将它传递给组件内的实际输入,因此它将修改它而不是包装:&lt;div class="input-wrap-for-doing-stuff"&gt;&lt;input type="text" /&gt;&lt;icon name="search"&gt;&lt;/div&gt;。如果这是有道理的。换行实际上只是用于定位图标、工具提示等。
  • 那么不要叫它class,在child-class调用它作为props传下去,那么vue就不会合并了。
【解决方案3】:

您不能抽象出模板中的包装 div,并且试图使组件以好像该 div 不存在的方式工作只会导致混乱和不正确的样式。

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

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

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

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

【讨论】:

    【解决方案4】:

    更简单的方法(imo)是将传入的类属性和动态类prop绑定到数据,并在created()钩子期间将它们从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>

    【讨论】:

      猜你喜欢
      • 2011-07-11
      • 1970-01-01
      • 2021-12-05
      • 2015-03-28
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 2013-12-28
      • 2017-08-02
      相关资源
      最近更新 更多