[RFC] mobx-vue v3
See original GitHub issueIntroduction
Since mobx v6 and vue v3 was released for a while, it’s time to support mobx v6 and vue v3.
Current Feature Request
Vue 3 Compatibility #50 Module Browser Build #49 Can I use mobx-vue without decorated class properties? #47 Add Documentation re Optimizing Rendering #36 Nuxt support #26 #32
Deprecate vue-class-component
Thoughts about mobx-vue https://github.com/mobxjs/mobx-vue/issues/3#issuecomment-573934357
I’m kinda wondering what direction this project might take with a “new vue” on the horizon. Since vue seems to move away from classes and therefore decorators is there a happy path to using mobx with vue in 2020?
vue-class-component has their own problem https://github.com/vuejs/vue-class-component/issues/406
Naive proto design (only for vue3)
No.1 idea
export a vue plugin for vue3
import { createApp } from 'vue';
import MobxVuePlugin from 'mobx-vue';
import App from './App.vue';
createApp(App)
.use(MobxVuePlugin, { name: 'MyObserver' /** optional Observer component name */ })
.mount('#app');
Using Observer Component in your app
<template>
<Observer>
<div>name: {{data.name}}</div>
<button @click="changeName">change</button>
</Observer>
</template>
<script setup>
import { runInAction, observable } from mobx;
const data = observable({ name: "iChenLei" });
const changeName = () => {
runInAction(() => { data.name = "Kuitos" });
};
</script>
No.2 idea
export a observer
function to hack vue export default
, no need to install as plugin, you can use it directly.
<template>
<UserComponent />
<ProfileComponent />
</template>
<script>
import { observer } from 'mobx-vue';
export default observer({
setup() {
// balabala
}
});
</script>
<!-- use @ decorator -->
<script>
import { observer } from 'mobx-vue';
@observer
export default {
setup() {
// balabala
}
};
</script>
But it not easy to do this , we need hack the vue @internel (e.g. $
, $options
, $forceUpdate
)
// vue 3 internal component properties map
const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
$: i => i,
$el: i => i.vnode.el,
$data: i => i.data,
$props: i => (__DEV__ ? shallowReadonly(i.props) : i.props),
$attrs: i => (__DEV__ ? shallowReadonly(i.attrs) : i.attrs),
$slots: i => (__DEV__ ? shallowReadonly(i.slots) : i.slots),
$refs: i => (__DEV__ ? shallowReadonly(i.refs) : i.refs),
$parent: i => getPublicInstance(i.parent),
$root: i => getPublicInstance(i.root),
$emit: i => i.emit,
$options: i => (__FEATURE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type),
$forceUpdate: i => () => queueJob(i.update),
$nextTick: i => nextTick.bind(i.proxy!),
$watch: i => (__FEATURE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP)
} as PublicPropertiesMap)
And when you use <script setup>
, it’s also diffcult to implement a useful observer
function.(any suggestion for this welcome)
No.3 idea
add the template sugar like <template pug>
, <template functional>
.
<tempalte observer>
<UserProfile />
<template>
It looks like best solution for mobx-vue and vue sfc? But it need mobx-vue maintainer to maintian different tools to support this feature. (e.g. mobx-vue-loader
for webpack
, rollup-plugin-mobx-vue
for vite
and rollup
, …etc). Not a reliable choice i think. I didn’t see any api allow us to change the <template>
behavior. It’s parsed by @vue/compiler-sfc
and no public api.
My opinion
Deprecate vue-class-component
and make vue sfc
as first class support.
Summary
Any idea and disscussion welcome, maybe you can design the final mobx-vue v3 api.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:9
- Comments:18 (4 by maintainers)
I’m currently using MobX 6 with Vue 3. Here is the plugin I wrote (it’s actually Quasar boot file): Works like a charm. Hope this helps.
Please don’t deprecate vue-class-component support. It’s the only reason I use mobx-vue. If you want to support composition API in addition to classes that would be fine. You could release the composition support now and do another release later when vue-class-component finalizes v3 support.