【问题标题】:Use style tags inside vuejs template and update from data model在 vuejs 模板中使用样式标签并从数据模型更新
【发布时间】:2018-09-06 01:42:50
【问题描述】:

我想动态更新样式inside样式标签。

但是,为 Vue 创建容器模型会删除 style 标记。 我知道样式标签应该放在页面的头部,但这只是为了方便使用。

所以我想要的是一个包含元素和样式标签的包装器:

<div class="setting">
  <style>
    .setting input {
      background: {{bgColor}};
    }
  </style>
  <input class="setting" type="text" v-model="bgColor">
</div>

输入的值应该更新css样式的值。 无论何时使用简单的 div 元素都可以,但样式标签似乎是个问题

javascript设置如下:

new Vue({
    el: '.setting',
    data: {
      bgColor: 'red'
    }
});

但是,当样式标签具有特定 id 时,这可以工作,但我无法将其绑定到输入字段。

<style id="setting">
  #blue {
    background: {{bg}}
  }
  #blue:hover {
    background: {{bgHover}}
  }
</style>

<div id="blue"></div>

和js:

new Vue({
    el: '#setting',
    data: {
      bg: 'blue',
      bgHover: 'red'
    }
});

谁能帮助我了解如何在样式标签之间实现更新值。 jsfiddle set up

谢谢。

【问题讨论】:

标签: javascript vue.js vuejs2


【解决方案1】:

我认为这是一个很好的解决方法/解决方案。

它只是一个自定义组件,因此可以尽可能地重复使用。 v-if之类的Vue的所有商品都可以使用。

另一个优点是生成的样式只有在组件存在时才会存在

Vue.component('v-style', {
  render: function (createElement) {
    return createElement('style', this.$slots.default)
  }
});


// demo usage, check the template
new Vue({
  el: '#app',
  data: {
    bgColor: 'red'
  }
})
<script src="https://unpkg.com/vue"></script>

<div id="app" class="stuff">
  <v-style>
    .stuff input {
      background: {{bgColor}};
    }
  </v-style>

  Remove "red" and type "yellow":
  <input class="setting" type="text" v-model="bgColor">
</div>

我看到的一个缺点是,由于标签的名称是 &lt;v-style&gt;(或您选择的任何名称)而不是 &lt;style&gt;,IDE 可能无法很好地着色它。但否则它就像一个普通的&lt;style&gt; 标签。


标准解决方案:使用v-bind:style

这不会修改style标签,但是设置样式的标准方法是使用object style bindings

基本上,您会使用:style 属性并以对象的形式为其分配样式的CSS 属性。演示如下。

new Vue({
  el: '.setting',
  data: {
    bgColor: 'red'
  },
  computed: {
    inputStyles() {
      return {
        background: this.bgColor
      }
    }
  }
});
<script src="https://unpkg.com/vue"></script>

<div class="setting">
  Remove "red" and type "yellow":
  <input class="setting" type="text" v-model="bgColor" :style="inputStyles">
</div>

【讨论】:

  • v 风格的东西非常聪明.. 开箱即用的好想法!
【解决方案2】:

vue-loader(和 Vue 模板编译器 Vue.compile(..))都会过滤掉在 template 中遇到的任何 &lt;style&gt; 标签。

解决这个问题的一个简单解决方案是利用 Vue 的内置&lt;component&gt; component

<template>
  <div>
    <component is="style">
      .foo[data-id="{{ uniqueId }}"] {
        color: {{ color }};
      }
      .foo[data-id="{{ uniqueId }}"] .bar {
        text-align: {{ align }}
      }
    </component>
    <div class="foo" :id="id" :data-id="uniqueId">
      <div class="bar">
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    id: {
      type: String,
      default: null
    }
  },
  computed: {
    uniqueId() {
      // Note: this._uid is not considered SSR safe though, so you
      // may want to use some other ID/UUID generator that will
      // generate the same ID server side and client side. Or just
      // ensure you always provide a unique ID to the `id` prop
      return this.id || this._uid;
    },
    color() {
      return someCondition ? 'red' : '#000';
    },
    align() {
      return someCondition ? 'left' : 'right';
    }
  }
}
</script>

需要一个唯一的 ID(或其他一些数据属性)才能将样式“范围”到这个组件。

这是一个不错的解决方案,因为如果需要,您可以使用 v-for 循环生成样式内容(可以对组件数据/道具/计算道具的更改做出反应)

<component is="style" type="text/css">
  <template v-for="item in items">
    [data-id="{{ uniqueId }}"] div.bar[data-div-id="item.id"]::before {
      content: "{{ item.content }}";
      color: {{ item.color }};
    }
  </template>
</component>

【讨论】:

  • 不错的解决方法!我不得不使用&lt;component is="'style'"&gt; 来阻止 VS Code 快乐
【解决方案3】:

我刚刚创建了一个计算属性并在模板中作为 v-html 使用它

<div v-html="css"></div>
computed: {
    css () {
        return `<style>${this.item.css}</style>`
    }
}

【讨论】:

    猜你喜欢
    • 2018-01-03
    • 2014-03-20
    • 2018-09-02
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 2014-08-01
    • 2010-12-27
    • 2021-05-26
    相关资源
    最近更新 更多