Can I refer class name from css module in the setup function of vue3?
<script setup>
console.log(this.$style.myClass) // this won't work
</setup>
<style lang="scss" module>
.myClass {
}
</style>
There is a warning in the Vue docs against the use of getCurrentInstance (see: https://twitter.com/romainlanz/status/1486279206149492744?s=20)
Vue exposes an api for css modules useCssModule for such use cases (see: https://vuejs.org/api/sfc-css-features.html#usage-with-composition-api)
<script setup>
import { useCssModule } from 'vue'
const $style = useCssModule()
console.log($style.myClass) // This Works ✅
</setup>
<style lang="scss" module>
.myClass {}
</style>
I used the same example above, with both approaches, (Demo) to show you that the 2 will produce the same thing, just that useCssModule is a 'lot safer' to use than getCurrentInstance
vue-loader injects the $style property (via a __cssModules wrapper object) onto the component instance, which can be accessed in <script setup> from getCurrentInstance():
<script setup>
import { getCurrentInstance } from 'vue'
const { $style } = getCurrentInstance().type.__cssModules
console.log('myClass', $style.myClass)
</script>
demo
However, use this solution with caution, as __cssModules is a private/internal property, which can be renamed or removed in the future without warning.
Related
I want to access the "name" variable from <script> in my <script setup> block. I cant seem to figure out how to do it. I have tried importing options from '*.vue' but that prompts me to install module '*.vue'.
<script>
export default {
name: 'some name'
}
</script>
<script setup>
//use the 'name' variable here
</script>
Unfortunately, this thing can't be done. You could use ref and access its value anywhere in the file.
<template>
<h1>{{ name }}</h1>
</template>
<script setup>
import {ref} from 'vue';
const name = ref('Jorgen');
</script>
If you want to access it's value inside <script setup> you have to use .value.I have provided the following example in case you want to use it inside a method within <script setup>,
<script setup>
import {ref} from 'vue';
const name = ref('Jorgen');
const showMyName = () => {
alert(name.value);
}
</script>
In brief, if you want to use name inside the template don't use .value, if you want to use name inside use .value
You can access options exported from <script> by creating a circular dependency to the Vue component:
<script>
export default { name: "MyComponent" }
</script>
<script setup>
// HACK: Create a circular dependency to this file to get access to options.
import ThisComponent from "./MyComponent.vue"
console.log(`Setting up ${ThisComponent.name}`);
</script>
It also works with TypeScript (lang="ts").
I'm migrating from Vue 2 to Vue 3. In Vue 2, it's possible to register a component globally like this: main.js
new Vue({
el: '#app'
})
A global registration of a component: my-component.js
Vue.component('my-component', {
template: '<div>Hi!</div>'
})
I'm using Webpack for import Single File Components in other components, and then i'm bundling it in one file. With Vue 2, that was easy because Vue instance was globally registered. Now with Vue 3, that doesn't work any more because of Vue.createApp({}).mount('#app'). I was trying to do something like this: main.js
const app = createApp({});
export const app;
And in: my-component.js
import { app } from './main.js';
app.component('my-component', {
template: '<div>Hi!</div>'
})
And at the end: close-app.js
import { app } from './main.js';
app.mount('#app');
And in: index.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js"></script>
<script type="application/javascript" src="my-component.js"></script>
<div id="app">
<my-component></my-component>
</div>
<script type="application/javascript" src="close-app.js"></script>
I'm importing the app because of Webpack. Webpack is bundling it in self-invoking functions, but that doesn't work. I know there is a way to declare it globally like this: window.app = app;, but that's not a good idea. Can someone help me with that?
Components Webpacks
Since Vue 3 component registration has to be invoked on an app instance, and you're importing each component Webpack individually, I don't think you can avoid globals. Using a global app instance (window.app) in your components might be the easiest solution, especially if you want to minimize the changes.
Alternatively, you could build the components as UMD modules, where the component definition is exported as a global, import the UMD module with the <script> tag (as you're already doing), and call app.component() for each of them:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js"></script>
<!-- sets MyComponent global -->
<script type="application/javascript" src="./my-component.umd.js"></script>
<div id="app">
<my-component></my-component>
</div>
<script>
const app = Vue.createApp({})
app.component(MyComponent.name, MyComponent)
app.mount('#app')
</script>
Component Module Scripts
In main.js, use createApp from the global Vue that you've imported in the <script> tag:
export const app = Vue.createApp({})
Then import your scripts as modules with <script type="module">:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js"></script>
<script type="module" src="./my-component.js"></script>
<div id="app">
<my-component></my-component>
</div>
<script type="module" src="./close-app.js"></script>
demo
I have been using "element-ui" and now moving forward to new version of Vue3.
Seems they published a new version called "element-plus" but the tutorial is not updated.
import Vue from 'vue'; // not working in Vue3
import ElementUI from 'element-plus';
import 'element-ui/lib/theme-chalk/index.css';
...
Vue.use(ElementUI); // no "Vue" in Vue3 anymore
...
createApp(App).mount('#app') // the new project creation
https://element-plus.org/#/en-US/component/quickstart
Anyone manged to do it right and it works?
If you are using vue 3 you need to import createApp as well as css from 'element-plus/...' folder. Then you instance your app using the vue function imported, basically you pass your main app component to the function as an argument:
import { createApp } from 'vue'
import App from './YourMainApp.vue'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
let app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
You can also do it very easy without any js bundler.
Here is a sample:
var Main = {
data() {
return {
message: 'Hello World!'
}
},
methods: {
click() {
console.log('click()');
}
}
};
const app = Vue.createApp(Main);
app.use(ElementPlus);
app.mount("#app")
<html>
<head>
<link rel="stylesheet" href="//unpkg.com/element-plus/theme-chalk/index.css">
</head>
<body>
<script src="//unpkg.com/vue#next"></script>
<script src="//unpkg.com/element-plus/dist/index.full.js"></script>
<div id="app">
<el-button type="primary" size="medium" #click="click">{{message}}</el-button>
</div>
</body>
</html>
Could someone explain to me what is the difference between importing VUE in the script tag like below...
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
and creating a vue project using the CLI which will connect to the back-end.
Will there be a difference in the production of my Web App or will it be identical?
When will it be recommended for me to use either option?
By using vue-cli you open yourself to many new possibilities - like using webpack to build your application, npm to manage dependencies, and most importantly - Single file components.
Hello.vue (example single file component)
<template>
<p>{{ greeting }} World!</p>
</template>
<script>
import LibraryName from 'library-name' // <- thats how you can import dependencies
export default {
data: function() {
return {
greeting: "Hello"
};
},
methods: {
exampleMethod () {
// do stuff
}
}
}
</script>
<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>
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();
});
});