Использование тегов стиля внутри шаблона vuejs и обновление из модели данных

Я хотел бы динамически обновлять стили 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'
    }
});

Однако, если у тегов стиля есть определенный идентификатор, это может сработать, но я не могу связать его с полем ввода.

<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 настроен

Благодарю.

Ответы

Ответ 1

Вот что я думаю, это хороший обходной путь/решение.

Это просто пользовательский компонент, поэтому его можно использовать многократно. Можно использовать все товары Vue, такие как v-if.

Еще один аргумент в пользу того, что сгенерированные стили будут там , только если компонент!

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>

Ответ 2

vue-loader (и компилятор шаблонов Vue Vue.compile(..)) оба отфильтровывают любые встречающиеся теги <style>.

Простое решение, позволяющее обойти это, - воспользоваться встроенным в Vue компонентом<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>

Уникальный "идентификатор" (или какой-либо другой атрибут данных) необходим для "охвата" стилей только этим компонентом.

Это хорошее решение, поскольку вы можете использовать циклы v-for для генерации содержимого стиля, если это необходимо (что может реагировать на изменения в ваших компонентах data/props/computed props)

<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>