Is it possible to get Component-scoped CSS i.e.
<style scoped>
...
</style>
WITHOUT using Single File Components?
For example, I have a component:
// MyComponent.ts
import { Vue, Component } from 'vue-property-decorator'
#Component({
template: '<h1>Not a Single File Component</h1>'
})
export default class MyComponent extends Vue {}
How can I add style such as:
h1 {
color: blue;
}
but have it scoped to MyComponent.ts only?
Since to use this component I would import it as:
import MyComponent from './MyComponent'
which is not a single file component and does not have a <style scoped>...</style>
You could do style binding like so:
#Component({
template: '<h1 :style="color: blue;">Not a Single File Component</h1>'
})
Alternatively, you could assign the h1 an id and reference the id in the stylesheet specifically.
#Component({
template: '<h1 id="whatever-this-is">Not a Single File Component</h1>'
})
...
<style>
#whatever-this-is {
color: blue;
}
</style>
Related
Some of my single-file components need to take hover color from props.
My solution is that i set css variables in the following way (the main part is in the mounted(){...})
<template>
<div class="btnWrapper" ref="btnWrapper">...</div>
</template>
...
...
props() {
color1: {type: String, default: 'blue'},
},
mounted () {
this.$refs.btnWrapper.style.setProperty('--wrapHoverColor', this.color1)
}
...
...
<style scoped>
.btnWrapper {
--wrapHoverColor: pink;
}
.btnWrapper:hover {
background-color: var(--wrapHoverColor) !important;
}
</style>
This solution seems kind of woowoo.
But maybe there is no better way with pseudo elements, which are hard to control from js.
Do you guys ever take pseudo element's properties from props in vue components?
You have two different ways to do this.
1 - CSS Variables
As you already know, you can create CSS variables from what you want to port from JS to CSS and put them to your root element :style attr on your components created hooks, and then use them inside your CSS codes with var(--x).
<template>
<button :style="style"> Button </button>
</template>
<script>
export default {
props: ['color', 'hovercolor'],
data() {
return {
style: {
'--color': this.color,
'--hovercolor': this.hovercolor,
},
};
}
}
</script>
<style scoped>
button {
background: var(--color);
}
button:hover {
background: var(--hovercolor);
}
</style>
2 - Vue Component Style
vue-component-style is a tiny (~1kb gzipped) mixin to do this internally. When you active that mixin, you can write your entire style section inside of your component object with full access to the component context.
<template>
<button class="$style.button"> Button </button>
</template>
<script>
export default {
props: ['color', 'hovercolor'],
style({ className }) {
return [
className('button', {
background: this.color,
'&:hover': {
background: this.hovercolor,
},
});
];
}
}
</script>
I had tried to use Jest for snapshot testing for Vue SFC. And I missed styles inside the generated snapshot file, only class names. Is it possible to add style rules to snapshot?
<template>
<div class="woof"></div>
</template>
<script>
import Vue from 'vue-class-component';
export default class Component extends Vue {};
</script>
<style lang="scss">
.woof {
background-color: red; // <- this part is missing inside snapshot file
}
</style>
import { shallowMount } from '#vue/test-utils';
import Component from './Component.vue';
describe('Component testing', () => {
it('looks as expected', () => {
const wrapper = shallowMount(Component);
expect(wrapper).toMatchSnapshot();
});
});
I am coming from React and Vue frankly seems to be way different to me even from Javascript prospective.
From the boiler plate code (HelloWorld.vue), Say we have the following code snippet
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
>vue-cli documentation</a
>.
</p>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
</style>
Here, I am unable to comprehend how does our export default knows What we need to export
Since the question was marked closed due to duplicate, Sharing the difference between the both
Consider, In case of react (or take it as any function) if we created a function
const someFunc = () => (
<div>
<h1> Test Component </h1>
</div>
)
export default someFunc
Here i am exporting my somefunc which I can import and use it with whatever way I want in other component
import Whatever from "./location"
But in the above Vue snippet, I cannot comprehend the significance of
export default {
name: "HelloWorld",
props: {
msg: String
}
};
What is the significance of exporting this object?
Also, where would If suppose I need to will I write my functions, class?
Everything inside the curly braces on export default {} including methods and data will be exported, and can be imported using import like in your example on React
import Whatever from "./location"
Just to answer your question
Also, where would If suppose I need to will I write my functions, class?
Methods and other data can be included inside the curly braces on export default {}. For example,
<script>
export default {
name: "HelloWorld",
props: {
message: {
type: String
}
},
data() {
return {
// put any data here, e.g.,
isVueDeveloper: true
}
},
methods: {
// put any methods here, e.g.,
firstMethod() {
return;
}
}
}
</script>
Component
<template lang="html">
<div class="chat-log">
<chat-message v-for="message in messages" :message="message"></chat-message>
</div>
</template>
<script>
export default {
props: ["messages"]
}
</script>
<style lang="css">
.chat-log .chat-message:nth-child(even) {
background-color: #ccc;
}
.chat-log {
overflow-y: auto;
max-height: 400px;
}
</style>
When I change the above script code to below. I get errors..
<script>
export default {
props: ["messages"]
},
created() {
$(".chat-log").scrollTop($(".chat-log").prop('scrollHeight'));
}
</script>
Error Details
Unexpected token, expected ;
Issue comes only when adding the created method, Am I missing anything?
The created lifecyle method goes within the body of the Vue component itself, not outside. I mean:
export default {
props: ["messages"],
created() {
$(".chat-log").scrollTop($(".chat-log").prop('scrollHeight'));
}
}
Vue.js Lifecycle
Your created(){} method should be encapsulated within your export default {} block.
In other words, change your code this:
export default {
props: ["messages"],
created() {
$(".chat-log").scrollTop($(".chat-log").prop('scrollHeight'));
}
},
I am experimenting with single file .vue components and my first successful build surprised me with the scope of the component style. Generally speaking, I was under the impression that single file components would be self-contained, including the scope of their components.
The component .vue file is
<template>
<div>
Hello {{who}}
</div>
</template>
<script>
module.exports = {
data: function () {
return {
who: "John"
}
}
}
</script>
<style>
div {
color: white;
background-color: blue;
}
</style>
It is built via webpackthough the following webpack.config.js
module.exports = {
entry: './entry.js',
output: {
filename: 'bundle.js'
},
devServer: {
inline: true
},
module: {
rules: [{
test: /\.vue$/,
loader: 'vue-loader'
}]
}
}
and the entry.js
import Vue from 'vue/dist/vue.js'
import ComponentOne from './component1.vue'
//Vue.component('component-one', ComponentOne)
new Vue({
el: "#time",
data: {
greetings: "bonjour"
},
components: { ComponentOne }
})
The HTML file binding all together is
<!DOCTYPE html>
<html lang="en">
<body>
Greetings:
<div id="time">
{{greetings}}
<component-one></component-one>
</div>
<script src='bundle.js'></script>
</body>
</html>
The rendered result is
The style definitions from component-one for div are also applied to the parent div (with id=time). Is this expected behaviour? Shouldn't the styling be confined to the component?
Note: I can assign an id to the div in my component's template and would therefore contain the styling - my question is about why this behaviour is expected in the context of components self-containement.
The scope of the styling will not be limited to the scope of the component, unless you explicitly mark the style with the scoped attribute:
<style scoped>
div {
color: white;
background-color: blue;
}
</style>
Furthermore, since you are using webpack to create a single bundled file, there would be no way for the browser to separate the styles from one component to the next, since all would be loaded and parsed at the same time.
If you wanted to lessen the footprint of a component on other components, you'd need to both scope your styles and utilize code splitting, although in your case, simply marking the style would be sufficient.