I have a bit of code that makes an api call to a server and returns some JSON.
It did exist as a method in my component but as it is getting a bit long I want to extract it to it's own file
In vuejs what is the best practice here.
should it be a component without a template? How would this work?
will I just create an es6 module?
I would suggest using a mixin here.
In a file like myCoolMixin.js define your mixin...
export default {
methods: {
myAwesomeMethod() {
//do something cool...
}
}
}
You can define anything in a mixin just like a component. e.g. data object, computed or watched properties, etc. Then you simply include the mixin in your component.
import myCoolMixin from '../path/to/myCoolMixin.js'
export default {
mixins: [myCoolMixin],
data: function() {
return: {
//...
}
},
mounted: function() {
this.myAwesomeMethod(); // Use your method like this!
}
}
More on Mixins here: https://v2.vuejs.org/v2/guide/mixins.html
Mixins work, or you could create a plugin. Here's the docs example:
MyPlugin.install = function (Vue, options) {
// 1. add global method or property
Vue.myGlobalMethod = function () {
// something logic ...
}
// 2. add a global asset
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// something logic ...
}
...
})
// 3. inject some component options
Vue.mixin({
created: function () {
// something logic ...
}
...
})
// 4. add an instance method
Vue.prototype.$myMethod = function (methodOptions) {
// something logic ...
}
}
Vue Plugins
Related
OK, i have a web page with some steps for the user and a mixin that handle those steps properties and logic, like current/next step value, checks to enable user advancing from each step to the next, etc.
Now i have to add a new functionality to be executed only after a certain step, so what i would like to be able to do is to call the original mixin method that is called everytime the user advance to the next step to add this functionality.
To be more clear, the mixin is (obviously) used in many pages of the webapp, so i would like to override the culprit mixin method in the component extending it, call the original mixin method to reuse its logic and then call oher methods for the new functionality.
Is it possibile?
sure you can, try it so:
// MyMixin.js
export default {
methods: {
myMethod() {
//...
}
}
}
// Component.vue
<script>
import MyMixin from 'path-to-mixins/MyMixin'
export default {
//...
mixins: [MyMixin],
methods: {
// there is overrinding you mixin method called myMethod
myMethod() {
// then some logic before to use your mixin method
// and call your mixin method as below
MyMixin.methods.myMethod()
}
}
//...
}
</script>
The previous answer does not work, in many cases...
you can directly access the function from the import but you need to bind the scope to this so the function uses your component data and/or other overriden functions
// Mixin.js
export default {
methods: {
aMethod() {
//...
}
}
}
// Component.vue
import Mixin from './Mixin'
export default {
//...
mixins: [Mixin],
methods: {
aMethod() {
// you need to bind the method to `this` when running so that the mixin uses your component data.
Mixin.methods.aMethod.call(this);
}
}
//...
}
if the mixin you are importing is already a vue constructor, this can happend if you used Vue.extend to create the mixin, in this case you need to use the options to access your method
You can access the mixin function using the options of the mixin
// Mixin.js
export default Vue.extend({
extends: OtherComponent
methods: {
aMethod() {
//...
}
}
})
// Component.vue
import Mixin from './Mixin'
export default {
//...
mixins: [Mixin],
methods: {
aMethod() {
// you need to bind the method to `this` when running so that the mixin uses your component data.
Mixin.options.methods.aMethod.call(this);
}
}
//...
}
I am using the modules mode of the store and in my projects.js inside my store folder I have:
export const getters = {
loadedProjects(state) {
return state.loadedProjects;
}
}
now in my computed how should I call it?
I’m trying like that:
computed: {
loadedProjects() {
return this.$store.getters.projects.loadedProjects;
},
}
but I get this error:
Cannot read property ‘loadedProjects’ of undefined
I had the same problem, if you are using the modules mode you can call your getters like that (in your case): this.$store.getters['projects/loadedProjects'];
So try to change your computed like that:
computed: {
loadedProjects() {
return this.$store.getters['projects/loadedProjects'];
},
}
You have to call your getter like this:
loadedProjects() {
return this.$store.getters['projects/loadedProjects'];
}
$store.getters['moduleName/getterName']
So I have a loader screen in my app, and the idea is to show the loader screen on the beforeCreate hook so the user can't see the stuff being rendered, and then on the mounted hook remove the loader screen.
This is fun and nice for when you have two or three view/components, but currently my app has a lot more than that, and adding it to each component/view doesn't make much sense for me.
So I was wondering, is there any way to add something to the beforeCreate and mounted hooks on a global scope. Something like this:
main.js
Vue.beforeCreate(() => {
//Show the loader screen
});
Vue.mounted(() => {
//Hide the loader screen
});
That way it would be applied to every component and view
You can use mixins for this purposes, and import in components.
//mixins.js
export default {
beforeCreate() {},
mounted() {}
}
And in component add mixins: [importedMixins]
You will have access to 'this'.
Actualy you can use and vuex to (mapGetters, mapActions etc.)
If you don't want include mixins in every component, try to use vue plugins system (https://v2.vuejs.org/v2/guide/plugins.html):
MyPlugin.install = function (Vue, options) {
// 1. add global method or property
Vue.myGlobalMethod = function () {
// something logic ...
}
// 2. add a global asset
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// something logic ...
}
...
})
// 3. inject some component options
Vue.mixin({
created: function () {
// something logic ...
}
...
})
// 4. add an instance method
Vue.prototype.$myMethod = function (methodOptions) {
// something logic ...
}
}
And use your plugin like this Vue.use(MyPlugin, { someOption: true })
There is something very silimar to your request in vue-router. I've never used afterEach but beforeEach works perfectly.
router.beforeEach((to, from, next) => {
/* must call `next` */
})
router.beforeResolve((to, from, next) => {
/* must call `next` */
})
router.afterEach((to, from) => {})
Here is a documentation
There is also a hook called 'beforeRouteEnter'.
Link to beforeRouteEnter docs
How does one avoid code duplication when using something like computed properties across multiple components?
An example is that I have a computed property to get the parent route name - it's pretty simple:
computed: {
parent_route () {
return this.$route.matched[0].name
}
}
I am finding that I use this computed property across multiple components. How could I store this in one place that all my components can use?
You can use Mixins. For the most general case there's the Global Mixin (use with care):
Vue.mixin({
computed: {
parent_route () {
return this.$route.matched[0].name
}
}
})
The this.parent_route computed property is now automatically defined in all components.
But you should avoid abusing global mixins. Instead, you can apply them locally using Option Merging (the mixins option):
var mixin = {
computed: {
parent_route () {
return this.$route.matched[0].name
}
}
};
new Vue({
mixins: [mixin],
data: function () {},
created: function () {
console.log(this.parent_route) // should be ok
}
})
You can use mixins. Create myMixin.js file with:
export const myMixin = {
computed: {
parent_route () {
return this.$route.matched[0].name
}
}
}
Then you can import it in your vue component like this:
import {myMixin} from '../myMixin.js' //valid path to myMixin.js file here
and register it:
...
data {...},
mixins: [myMixin],
methods: {...}
...
More on mixins:
https://v2.vuejs.org/v2/guide/mixins.html
Using the vue-router package, it is easy to match dynamic segments:
router.map({
'/user/:username': {
component: {
template: '<p>username is {{$route.params.username}}</p>'
}
}
})
However, I couldn't figure out how to use the value a component method, e.g.
router.map({
'/user/:username': {
component: {
ready: function() {
// How to access the param here?
alert($route.params.username);
}
}
}
})
How can I access the matched segment in the component method?
Is almost as what you posted
// inside your component
this.$route.params.username
The key is that in the template you don't need to refer to the this scope, but in methods you have to use it
The $route object is injected in every router maped compeonents , as per your case you would use the params method to get the key/value passed .
router.map({
'/user/:username': {
component: {
ready: function() {
// How to access the param
// use the scope 'this'
alert(this.$route.params.username);
}
}
}
})
for more info check out http://router.vuejs.org/en/api/route-object.html