I am able to register a custom vue.js component with
// registerVue.component('my-component', {template: '<div class="my-class">A custom component!</div>'})
Also see https://v2.vuejs.org/v2/guide/components.html
How can I include css classes for my component?
I would expect something like
Vue.component('my-component', {template: '<div class="my-class">A custom component!</div>',css: '#... my css stylesheet...'})
but there does not seem to be a css
option.
I know that I could
a) define all css classes in a global css stylesheet or
b) use singe-file-vue-components (would require build tool supporing *.vue files, see https://v2.vuejs.org/v2/guide/single-file-components.html)
but I would prefer to
c) specify a css stylesheet for the component when registering the component.
=> How to do so?
Best Answer
there does not seem to be a css option.
That is correct. You cannot do what you describe. The documentation on single file components is pretty clear that one of the advantages is that you can do this with them and cannot do it without them.
In many Vue projects, global components will be defined using
Vue.component
, followed bynew Vue({ el: '#container' })
to target acontainer element in the body of every page.This can work very well for small to medium-sized projects, whereJavaScript is only used to enhance certain views. In more complexprojects however, or when your frontend is entirely driven byJavaScript, these disadvantages become apparent:
[...]No CSS support means that while HTML and JavaScript aremodularized into components, CSS is conspicuously left out
Here is a way to achieve what you're looking for:
export const ContactUs = Vue.component('mycomponent-contact-us',{props: {backgroundColor: {type: String,required: false,default: "red"}},data: function(){return {}},template: `<div><span class='contact_us_text' >Contact Us Component and its bg color will be {{backgroundColor}}</span></div>`,mounted: function(){var css_text = `.contact_us_text{color: `+this.backgroundColor+`;}`;var css = document.createElement('style');css.type='text/css';css.setAttributeNode( document.createAttribute('scopped') );css.appendChild( document.createTextNode( css_text ) );this.$el.appendChild( css );}});
Its true that you cannot add <style>
inside a Vue template or add CSS withincomponent directly, unless you bind it or define your css globally. But you can create a custom component that will dynamically do it for you. sample
Keep in mind that Vue components are effectively macros.
Where render
is the substitution function, and the vueDefinition
(defn3
below) is effectively a class
for the given tagName
.
A template
is just a convenient syntactic-sugar shorthand that will be compiled
(with some vue-usage pattern restrictions) into a render
function if you don't provide your own render
function.
const defn3 = {tagName: 'ae-css',mounted() {const vueDefinition = this.$options;this.$el.appendChild(document.createTextNode(vueDefinition.css));},css: `* {color: blue;}`,render(h) {return h('style');}}Vue.component(defn3.tagName, defn3);
With that solution in hand, there are a number of good reasons why you probably don't want something as simplistic as what I just provided.
Namely, you want to have your css modularized such that it does not affect any aspects of your page you did not intend it to. For that, you either need carefully designed css rules with your intended inheritance and scope; probably using a class=..
. But a better approach would be to just use Vue's facilities that offer similar capabilities automatically.
If you want to use modern browser architecture capabilities for this, then you might want your components to be real browser DOM WebComponents
that make use of the shadowDOM and keep your internal elements and styles encapsulated within a shadowRoot
. See this library, for doing that in Vue.
You can embed a style tag within your template root element:
Vue.component('my-component', {template: `<div class="my-class" my-component>A custom component!<style>.my-class[my-component] {// ... my-component styles}</style></div>`})
Try this:
this.$el.style.cssText = "border: 5px solid blue;"