mobx-vue
Version:
Vue bindings for MobX
77 lines (76 loc) • 3.55 kB
JavaScript
import { __assign } from "tslib";
/**
* @author Kuitos
* @homepage https://github.com/kuitos/
* @since 2018-05-22 16:39
*/
import { Reaction } from 'mobx';
import Vue from 'vue';
import collectDataForVue from './collectData';
// @formatter:off
// tslint:disable-next-line
var noop = function () { };
var disposerSymbol = Symbol('disposerSymbol');
function observer(Component) {
var name = Component.name || Component._componentTag || (Component.constructor && Component.constructor.name) || '<component>';
var originalOptions = typeof Component === 'object' ? Component : Component.options;
// To not mutate the original component options, we need to construct a new one
var dataDefinition = originalOptions.data;
var options = __assign(__assign({ name: name }, originalOptions), { data: function (vm) {
return collectDataForVue(vm || this, dataDefinition);
},
// overrider the cached constructor to avoid extending skip
// @see https://github.com/vuejs/vue/blob/6cc070063bd211229dff5108c99f7d11b6778550/src/core/global-api/extend.js#L24
_Ctor: {} });
// we couldn't use the Component as super class when Component was a VueClass, that will invoke the lifecycle twice after we called Component.extend
var superProto = typeof Component === 'function' && Object.getPrototypeOf(Component.prototype);
var Super = superProto instanceof Vue ? superProto.constructor : Vue;
var ExtendedComponent = Super.extend(options);
var _a = ExtendedComponent.prototype, $mount = _a.$mount, $destroy = _a.$destroy;
ExtendedComponent.prototype.$mount = function () {
var _this = this;
var _a, _b;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var mounted = false;
this[disposerSymbol] = noop;
var nativeRenderOfVue;
var reactiveRender = function () {
reaction.track(function () {
if (!mounted) {
$mount.apply(_this, args);
mounted = true;
nativeRenderOfVue = _this._watcher.getter;
// rewrite the native render method of vue with our reactive tracker render
// thus if component updated by vue watcher, we could re track and collect dependencies by mobx
_this._watcher.getter = reactiveRender;
}
else {
nativeRenderOfVue.call(_this, _this);
}
});
return _this;
};
var reaction = new Reaction(name + ".render()", reactiveRender);
// @ts-expect-error
this[disposerSymbol] = ((_a = reaction.getDisposer_) === null || _a === void 0 ? void 0 : _a.call(reaction)) || ((_b = reaction.getDisposer) === null || _b === void 0 ? void 0 : _b.call(reaction));
return reactiveRender();
};
ExtendedComponent.prototype.$destroy = function () {
this[disposerSymbol]();
$destroy.apply(this);
};
var extendedComponentNamePropertyDescriptor = Object.getOwnPropertyDescriptor(ExtendedComponent, 'name') || {};
if (extendedComponentNamePropertyDescriptor.configurable === true) {
Object.defineProperty(ExtendedComponent, 'name', {
writable: false,
value: name,
enumerable: false,
configurable: false,
});
}
return ExtendedComponent;
}
export { observer, observer as Observer, };