Last active
July 21, 2020 21:30
-
-
Save fnlctrl/1cf9da63493e0fe78181a4f4e2cc6f64 to your computer and use it in GitHub Desktop.
VueRouteData plugin for [email protected] and vue@1or2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* VueRouteData plugin for [email protected] and vue@1or2, | |
* implemented according to https://github.com/vuejs/vue-router/issues/296#issuecomment-235481643 | |
* | |
* This plugin looks for `$options.fetchRouteData`, | |
* and watches `$route` using `$options.fetchRouteData` as handler. | |
* | |
* Before `fetchRouteData` executes, this plugin sets 'loadingRouteData' to true, | |
* and when it finishes executing, the plugin sets 'loadingRouteData' to false, | |
* so `fetchRouteData` can either be normal functions or async functions. | |
* Note: you need to define `loadingRouteData` in component's data option to get this working. | |
* | |
* It also injects two helper functions, `$setAsyncData` and `$reloadRouteData`, | |
* for details see below. | |
* | |
* Usage: (babel and Promise polyfill required) | |
* import VueRouter from '...' | |
* import VueRouteData from '...' | |
* Vue.use(VueRouter).use(VueRouteData) | |
* | |
* Author: fnlCtrl([email protected]) | |
* License: MIT | |
*/ | |
function install(Vue) { | |
if (install.installed) return; | |
install.installed = true; | |
const isVersion1 = Vue.version[0] == '1'; | |
const mixin = { | |
[isVersion1 ? 'init' : 'beforeCreate']() { | |
if (this.$options.fetchRouteData) { | |
!this.$options.methods && (this.$options.methods = {}); | |
/** | |
* Utility method for setting async data (promises or then-ables) on an instance | |
* @param promises - {key: promise} | |
*/ | |
this.$options.methods.$setAsyncData = promises => Promise.all( | |
Object | |
.keys(promises) | |
.map(key => Promise | |
.resolve(promises[key]) | |
.then(val => Vue.set(this, key, val)) | |
) | |
); | |
/** | |
* Utility method for reloading route data | |
*/ | |
this.$options.methods.$reloadRouteData = | |
() => this.$options.fetchRouteData(this.$route); | |
} | |
}, | |
created: initWatcher, | |
beforeDestroy: destroyWatcher, | |
/* Keep-alive support */ | |
[isVersion1 ? 'attached' : 'activated']: initWatcher, | |
[isVersion1 ? 'detached' : 'deactivated']: destroyWatcher | |
}; | |
Vue.mixin(mixin); | |
function initWatcher() { | |
if (this.$options.fetchRouteData && !this._unwatch$route) { | |
this._unwatch$route = this.$watch( | |
'$route', | |
function () { | |
Vue.set(this, 'loadingRouteData', true); | |
var promise = this.$options.fetchRouteData.apply(this, arguments); | |
Promise.resolve(promise).then(() => Vue.set(this, 'loadingRouteData', false)); | |
}, | |
{immediate: true} | |
); | |
} | |
} | |
} | |
function destroyWatcher() { | |
this._unwatch$route && this._unwatch$route(); | |
this._unwatch$route = null; | |
} | |
export default { | |
install | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey man thx for this :) is just what i needed ๐
I've made an update to your original plugin, i hope you don't mind. Here's my updated version:
https://gist.github.com/javisperez/26e7bc828b075496c0e564dbb1462387
My update just adds an internal Vue instance with a data property for the "loadingData" variable, so is not required to declare it first, instead it just refer to the internal vue instance as "$routeData" and variable would be like:
(oh yes, also i renamed it as is a boolean and makes a little more sense to me :) ).
Great work man, thank you again ๐