Last active
March 26, 2020 01:37
-
-
Save javisperez/26e7bc828b075496c0e564dbb1462387 to your computer and use it in GitHub Desktop.
[UPDATED] 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
/** | |
* Note: this is an updated version of the original plugin: | |
* https://gist.github.com/fnlctrl/1cf9da63493e0fe78181a4f4e2cc6f64 | |
* | |
* 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) | |
* | |
* Update: Added an internal Vue instance so it doesn't require | |
* the declaration of the "loadingData" variable in the component. | |
* Also, as the "loadingData" is a boolean type variable i've renamed it to "isLoadingData". | |
* | |
* Author: fnlCtrl([email protected]) | |
* Updated by: Javis Perez <https://www.github.com/javisperez> | |
* License: MIT | |
*/ | |
function install(Vue) { | |
if (install.installed) return; | |
install.installed = true; | |
let vm = new Vue({ | |
data() { | |
return { | |
isLoadingRouteData: false | |
}; | |
} | |
}); | |
Vue.prototype.$routeData = vm; | |
const isVersion1 = Vue.version[0] === '1', | |
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 () { | |
this.$routeData.isLoadingRouteData = true; | |
var promise = this.$options.fetchRouteData.apply(this, arguments); | |
Promise.resolve(promise).then(() => this.$routeData.isLoadingRouteData = 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