Use style tags inside vuejs template and update from data model

前端 未结 2 1639
没有蜡笔的小新
没有蜡笔的小新 2020-12-09 04:33

I would like to dynamically update styles inside style tags.

However creating a container model for Vue, removes the style tags. I know sty

相关标签:
2条回答
  • 2020-12-09 05:25

    vue-loader (and Vue template compiler Vue.compile(..)) both will filter out any <style> tags that are encountered in the template.

    A simple solution to get around this, is to take advantage of Vue's built-in<component> 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>
    

    A unique ID (or some other data-attribute) is required to "scope" the styles to just this component.

    This is a nice solution as you can use v-for loops to generate the style content if required (which can be reactive to changes in your components 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>
    
    0 讨论(0)
  • 2020-12-09 05:27

    Here's what I think is a good workaround/solution.

    It is just a custom component, so it's as reusable as it gets. All of Vue's goods like v-if can all be used.

    Another pro is that the styles generated will be there only as long as the component is!

    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>

    The one drawback I see is that since the name of the tag is <v-style> (or whatever you chose to call it) and not <style>, the IDEs may not color it nicely. But otherwise it'll just be like a regular <style> tag.


    Standard solution: using v-bind:style

    This doesn't modify style tags, but the standard way of setting styles is using object style bindings.

    Basically you'd use a :style attribute and assign to it the CSS properties of the style in the form of an object. Demo below.

    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>

    0 讨论(0)
提交回复
热议问题