2
votes

I am trying to use Vue.js without needing a build step. But Vue doesn't have a style property.

So I had an idea to create a custom "style" property on my Vue component instance and then inject the content of this property in the DOM when the component is created or mounted.

The only problem is I can't understand how to do it. (I looked at the plugins docs). I would need to create some sort of a plugin that would first check if a "style" property exists and then take it and insert it in the DOM. Also I don't want to use the Vue.component() function because I want to import and export using ES6. Here is how the result would look like:

// MyComponent.js
export default {
  template: `<div>My component</div>`,

  style: `
    .hello {
      background: #ccc;
    }
  `,
}

// App.js
import MyComponent from './MyComponent.js'

new Vue({
  el: '#app',

  components: {
    MyComponent
  }
})

When MyComponent is created, it should take the value of the "style" property and add it to the DOM like this. Any ideas would be much appreciated.

$('body').append('<style>' + STYLE + '</style>')

Here is a plugin using Vue.component() function. But I don't want to use the component function.

https://github.com/NxtChg/pieces/tree/master/js/vue/vue-css

1

1 Answers

3
votes

You can use computed inline styles using v-bind:style or just :style for short. It will map the given object to correct CSS styles. Use camelCase, i.e. backgroundColor instead of background-color.

If you want global style, you can inject a style tag into head using the mounted life-cycle hook. You should remove it again in destroyed.

EDIT: I misunderstood your post, updated answer

var app = new Vue({
  el: '#app',
  data: {
    subject: 'World'
  },
  computed: {
    subjectStyle() {
      return {
        color: 'yellow',
        backgroundColor: 'rebeccapurple',
      };
    }
  },
  mounted() {
    const css = `
      body {
        background-color: #eee;
        font-family: 'Comic Sans MS', sans-serif;
      }
    `;
    this.styleTag = document.createElement('style');
    this.styleTag.appendChild(document.createTextNode(css));
    document.head.appendChild(this.styleTag);
  },
  destroyed() {
    this.styleTag.remove();
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  Hello, <span :style="subjectStyle">{{ subject }}</span>!
</div>

Below is some code for a plugin that will allow each Vue instance to specify some styling. The styling will be injected into <head> and removed again when the component is destroyed.

const StylePlugin = {
  install(Vue) {
    Vue.mixin({
      mounted() {
        const css = this.$options.style;
        if (!css) return;
        this.$styleTag = document.createElement('style');
        this.$styleTag.appendChild(document.createTextNode(css));
        document.head.appendChild(this.$styleTag);
      },
      destroyed() {
        if (this.$styleTag) {
          this.$styleTag.remove();
        }
      }
    });
  }
};

Vue.use(StylePlugin);

var app = new Vue({
  el: '#app',
  data: {
    subject: 'World'
  },
  style: `
    body {
      background-color: rebeccapurple;
      color: white;
      font-family: 'Comic Sans MS', sans-serif;
    }
  `,
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  Hello, World
</div>