Lightweight Vue bindings for MobX based on Composition API.
Demo: https://codesandbox.io/s/mobx-vue-lite-demo-4mctz
yarn add mobx-vue-lite
Creates an observable object with the given properties, methods and computed values.
<template>
<div>Count: {{ state.count }}</div>
<div>Doubled: {{ state.double }}</div>
<button @click="state.increment">Increment</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { useLocalObservable } from 'mobx-vue-lite'
export default defineComponent({
setup() {
const state = useLocalObservable(() => ({
count: 0,
get double() {
return this.count * 2
},
increment() {
this.count++
}
}))
return { state }
}
})
</script>
Is a renderless Vue component, which applies observer to its children.
// main.js
import { createApp } from 'vue'
import Observer from 'mobx-vue-lite'
const app = createApp(App)
app.use(Observer)
<template>
<Observer>
<div>Name: {{ data.name }}</div>
<button @click="changeName">Change name</button>
</Observer>
</template>
<script setup lang="ts">
import { observable, runInAction } from 'mobx'
import { Observer } from 'mobx-vue-lite'
const data = observable({ name: 'John' })
const changeName = () => {
runInAction(() => {
data.name = 'Jane'
})
}
</script>
Create a global observer from a local observer.
// store.ts
import { createGlobalObservable, useLocalObservable } from 'mobx-vue-lite'
export const useGlobalObservable = createGlobalObservable(() => {
return useLocalObservable(() => ({
count: 0,
get double() {
return this.count * 2
},
increment() {
this.count++
}
}))
})
<template>
<div>Count: {{ state.count }}</div>
<div>Doubled: {{ state.double }}</div>
<button @click="state.increment">Increment</button>
</template>
<script setup lang="ts">
import { useGlobalObservable } from './store'
// Can be reused in any component and state will be in sync
const state = useGlobalObservable()
</script>
You can watch the state and its changes through Vue's watch:
import { watch } from 'vue'
const state = useLocalObservable(() => ({
count: 0,
increment() {
this.count++
}
}))
// watch the whole state
watch(state, (value) => {
console.log(value)
})
// watch part of a state
watch(() => state.value.count, (count) => {
console.log(count)
})
For Vue 2 users, install @vue/composition-api
<template>
<div>Count: {{ state.count }}</div>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api'
import { useLocalObservable } from 'mobx-vue-lite'
export default defineComponent({
setup() {
const state = useLocalObservable(() => ({
count: 0
}))
return { state }
}
})
</script>
Class observables should work out-of-the-box. Just wrap the component with the <Observer />
component.
<template>
<Observer>
<h1 v-text="state.count" />
<button @click="state.decrement">-</button>
<button @click="state.increment">+</button>
</Observer>
</template>
<script setup lang="ts">
import { Observer } from 'mobx-vue-lite'
import { CounterStore } from 'counterStore'
const state = new CounterStore();
</script>
API is inspired from https://github.com/mobxjs/mobx-react-lite.
MIT License © 2021 Robert Soriano