vue-class-component syntax with typescript - vue.js

The example on https://github.com/vuejs/vue-class-component (for the component syntax that's new in vuejs3) but I'm using straight type script instead of babel. I therefore tried:
<script lang="ts">
import Vue from "vue"
import Component from "vue-class-component"
#Component({
props: {
propMessage: String
}
})
export default class MyComponent extends Vue {
helloMsg = "Hello, " + this.propMessage
}
</script>
Unfortunately, this.propMessage can't be found. How do I have to change the syntax to make it found?

I would guess this.props.propMessage would work (but i can't test it right now) and you may have already tried.
I recommend you using #Prop decorator from vue-property-decorator which provide a clearer syntax on the long-end.
It would give something like :
#Component
export default class MyComponent extends Vue {
#Prop() propMessage !: string;
helloMsg = "Hello, " + this.propMessage;
}
Good luck

Related

Vue 3 use dynamic component with dynamic imports

I use Vue 3 and I have a dynamic component. It takes a prop called componentName so I can send any component to it. It works, kind of.
Part of the template
<component :is="componentName" />
The problem is that I still need to import all the possible components. If I send About as a componentName I need to import About.vue.
Part of the script
I import all the possible components that can be added into componentName. With 30 possible components, it will be a long list.
import About "#/components/About.vue";
import Projects from "#/components/Projects.vue";
Question
It there a way to dynamically import the component used?
I already faced the same situation in my template when I tried to make a demo of my icons which are more than 1k icon components so I used something like this :
import {defineAsyncComponent,defineComponent} from "vue";
const requireContext = require.context(
"#/components", //path to components folder which are resolved automatically
true,
/\.vue$/i,
"sync"
);
let componentNames= requireContext
.keys()
.map((file) => file.replace(/(^.\/)|(\.vue$)/g, ""));
let components= {};
componentNames.forEach((component) => { //component represents the component name
components[component] = defineAsyncComponent(() => //import each component dynamically
import("#/components/components/" + component + ".vue")
);
});
export default defineComponent({
name: "App",
data() {
return {
componentNames,// you need this if you want to loop through the component names in template
};
},
components,//ES6 shorthand of components:components or components:{...components }
});
learn more about require.context

How to import my own class or method globally in Vue?

I have a class and method that I need to import globally, so that I could avoid importing it again in each Vue file. I usually import my own class and method in each Vue file like this:
// in myFunc.js
export const fn = {
myFunc: function(param) { alert(param) }
}
// then I use it like this
import {fn} from '#/assets/js/myFunc.js';
fn.myFunc('Lorem ipsum');
In main.js, I tried the following code, which does not work:
import {fn} from '#/assets/js/myFunc.js';
Vue.mixin({
components: { fn },
})
How do I import the class/methods globally?
import Vue from 'vue'
import { fn } from '#/assets/js/myFunc.js';
Vue.prototype.$fn = fn
And then in your component.
this.$fn.myFunc()
Adding Instance Properties.
There may be data/utilities you’d like to use in many components, but
you don’t want to pollute the global scope. In these cases, you can
make them available to each Vue instance by defining them on the
prototype.

Vue.js how to load dependent components

Vue.js : how to load dependent components?
From router currently using component as follows:
import A from './A';
export default {
components : {
'new-comp-A' : NewCompA
}
}
...
But this renders the template before import causing errors. Is there a better way for loading dependencies?
The template uses the - did you register the component correctly.
Your casing is incorrect. Use either 'NewCompA' or 'new-comp-a' for the name.
In fact, it would be even easier to use
import NewCompA from 'wherever/the/component/is/defined'
export default {
components: {
NewCompA
}
}
Your template can then use either
<NewCompA></NewCompA>
<!-- or -->
<new-comp-a></new-comp-a>
See https://v2.vuejs.org/v2/guide/components-registration.html#Name-Casing
After looking at your code again, it does not seem normal. You are assigning the variable A to your component, but trying to import it with the variable NewCompA..
You need to change the following:
From this:
import A from './A';
export default {
components : {
'new-comp-A' : NewCompA
}
}
...
To this:
import A from './A';
export default {
components : {
'NewCompA' : A
}
}
...
and use it like this:
<new-comp-a>

Why do I need to declare props twice in vue-class-component?

When working with vue-class-component, I need to declare my props both in the #Component decorator AND in the class itself. It seems rather redundant and error prone.
Is this intended or am I missing something here?
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
// Here we declare that score and counter are props
#Component({
props: {
score:Number,
counter:Number
}
})
// Now I have to declare score and counter again ?
// Adding to the confusion is the fact that Typescript types are
// written differently from Vue types (number vs Number)
export default class ScoreBar extends Vue {
score:number
counter:number
created(){
console.log(`score prop is ${this.score} counter is ${this.counter}`)
}
}
</script>

Capitalize ${NAME} in File and Code Templates

Problem
In Preferences -> Editor -> File and Code Templates I have a template for React with:
import React from 'react';
class ${NAME} extends React.Component {
render() {
return (
<div>
#[[$END$]]#
</div>
);
}
}
export default ${NAME};
Is there a way to capitalize the ${NAME}?
We have a convention of naming our files starting with a lowercase but in React components are meant to be capitalized.
Additional Information
I'm aware of the IntelliJ's ability to refactor and that you can use a Live Templates to accomplish this but I would like to remove this extra step :).
This is possible in Live Templates where you can define and reference a expression like capitalize(fileNameWithoutExtension()) but I couldn't find anywhere to define expressions in File and Code Templates.
So after doing some research I came up with this:
import React from 'react';
#set($capitalizedFilename = $NAME.substring(0,1).toUpperCase() + $NAME.substring(1))
class $capitalizedFilename extends React.Component {
render() {
return (
<div>
#[[$END$]]#
</div>
);
}
}
export default $capitalizedFilename;
An IntelliJ IDEA file template is a Velocity template. Velocity allows you to use standard String methods on variables (see this question for some examples).
Here is all cases for WebStorm File template:
#set($NAME_CAP = $NAME.substring(0,1).toUpperCase() + $NAME.substring(1))
#set($NAME_LOW = $NAME.substring(0,1).toLowerCase() + $NAME.substring(1))
#set($NAME_UPPER = $NAME.toUpperCase())
Velocity's StringUtils is also available:
#set($NAME_CAPITALIZED = ${StringUtils.capitalizeFirstLetter($NAME)})
import React from 'react';
class ${NAME_CAPITALIZED} extends React.Component {
// ...
}