Skip to content
This repository was archived by the owner on Feb 17, 2022. It is now read-only.

nighca/movue

Folders and files

NameName
Last commit message
Last commit date

Latest commit

8c6aa45 · Feb 17, 2022

History

67 Commits
Mar 16, 2018
Mar 16, 2018
Aug 1, 2017
Aug 1, 2017
Aug 4, 2017
Aug 1, 2017
Feb 17, 2022
Nov 28, 2017
Oct 23, 2019
Oct 23, 2019
Aug 1, 2017
Mar 16, 2018
Oct 23, 2019

Repository files navigation

Movue npm version Build Status Coverage Status License

Deprecated: This project is not maintained any longer. Since there is an official solution for MobX-Vue.js binding: mobx-vue, you may want to check that.


MobX integration for Vue.js, inspired by vue-rx.

Movue aims for providing simple and reliable integration between Mobx and Vue.js, which sometimes means less convenience. You may want to try mobx-vue if you are facing more complex situation. :)

Why movue

Why MobX + movue, instead of Vuex?

Install

npm i movue --save

If you use yarn,

yarn add movue

Usage

Import Movue in your project and use it in Vue:

import Vue from 'vue'
import Movue from 'movue'
import * as mobx from 'mobx'

Vue.use(Movue, mobx)

You can pass the min parts of MobX to reduce bundle size:

import { reaction } from 'mobx'

Vue.use(Movue, { reaction })

Now you can use data from MobX store in your Vue component:

// given MobX store
const todoStore = observable({
  todos: [],
  get unfinishedTodos() {/* ... */},
  addTodo: action(function() {/* ... */}),
  toggleTodo: action(function() {/* ... */})
  setTodos: action(function() {/* ... */})
})

// given vue component
export default {
  data() {/* ... */},
  computed: {/* ... */},
  // you should use data from MobX store only in `fromMobx` properties
  fromMobx: {
    unfinishedTodos() {
      return todoStore.unfinishedTodos
    }
  },
  methods: {
    toggleTodo(...args) {
      todoStore.toggleTodo(...args)
    }
  }
}

Properties defined in fromMobx can be used in the template or other parts of viewModel just like normal Vue computed properties:

<template>
  <p>Count of unfinished todos: {{unfinishedTodos.length}}</p>
</template>

Like computed properties, we can define getter & setter for fromMobx properties:

export default {
  fromMobx: {
    todos: {
      // getter
      get() {
        return todoStore.todos
      },
      // setter
      set(todos) {
        todoStore.setTodos(todos)
      }
    }
  }
}

You can use helper methods to simplify your code:

import { mapFields, mapMethods } from 'movue'

export default {
  fromMobx: mapFields(todoStore, ['todos', 'unfinishedTodos']),
  methods: {
    // `...` requires object spread syntax support
    ...mapMethods(todoStore, ['addTodo', 'toggleTodo']),
    someOtherMethod() {/* ... */}
  }
}

movue works well with vue-class-component:

import { FromMobx } from 'movue'

@Component({/* ... */})
class Todo extends Vue {
  // get todos
  @FromMobx get todos() {
    return todoStore.todos
  }
  // you don't need decorator for setters
  set todos(todos) {
    todoStore.setTodos(todos)
  }
  // you can also set value with a component method
  setTodos(todos) {
    todoStore.setTodos(todos)
  }
}

API Reference

mapFields(store: object, fieldNames: string[]): Object

mapFields do fields' map for you:

const fields = mapFields(todoStore, ['todos', 'unfinishedTodos'])
// equals
const fields = {
  todos() { return todoStore.todos },
  unfinishedTodos() { return todoStore.unfinishedTodos }
}
mapFields(store: object, fieldNames: {[fieldAlias: string]: string}): Object

You can use aliases for fields:

const fields = mapFields(todoStore, {
  todoList: 'todos',
  unfinishedTodoList: 'unfinishedTodos'
})
// equals
const fields = {
  todoList() { return todoStore.todos },
  unfinishedTodoList() { return todoStore.unfinishedTodos }
}
mapFields(store: object, fieldNames: {[fieldAlias: string]: { get: string, set?: string }}): Object

Also you can specify a setter for the field:

const fields = mapFields(todoStore, {
  todoList: {
    get: 'todos'
  },
  unfinishedTodoList: 'unfinishedTodos',
  newTodoItemName: {
    get: 'newItemName',
    set: 'setNewItemName'
  }
})
// equals
const fields = {
  todoList() { return todoStore.todos },
  unfinishedTodoList() { return todoStore.unfinishedTodos },
  newTodoItemName: {
    get() { return todoStore.newItemName },
    set(value) { todoStore.setNewItemName(value) }
  }
}
mapFields(store: object, fieldNames: {[fieldAlias: string]: { get: (store: object) => any, set?: (store: object, value: any) => void }}): Object

You can specify a complex setter and getter for the field:

const fields = mapFields(todoStore, {
  todoList: {
    get: 'todos'
  },
  unfinishedTodoList: 'unfinishedTodos',
  newTodoItemName: {
    get(store) {
      // store === todoStore
      return store.newItemName
    },
    set(store, value) {
      // store === todoStore
      store.setNewItemName(value)
    }
  }
})
// equals
const fields = {
  todoList() { return todoStore.todos },
  unfinishedTodoList() { return todoStore.unfinishedTodos },
  newTodoItemName: {
    get() { return todoStore.newItemName },
    set(value) { todoStore.setNewItemName(value) }
  }
}
mapMethods(store: object, methodNames: string[]): Object

mapMethods do methods' map for you:

const methods = mapMethods(todoStore, ['addTodo', 'toggleTodo'])
// equals
const methods = {
  addTodo: todoStore.addTodo.bind(todoStore),
  toggleTodo: todoStore.toggleTodo.bind(todoStore)
}
mapMethods(store: object, methodNames: {[methodAlias: string]: string}): Object

You can use aliases for methods:

const methods = mapMethods(todoStore, {
  addTodoItem: 'addTodo',
  checkTodoItem: 'toggleTodo'
})
// equals
const methods = {
  addTodoItem: todoStore.addTodo.bind(todoStore),
  checkTodoItem: todoStore.toggleTodo.bind(todoStore)
}
FromMobx(target: Vue, key: string): void

FromMobx helps to use movue together with vue-class-component. You should use FromMobx as decorator for class property accessors:

@Component({/* ... */})
class Todo extends Vue {
  @FromMobx get todos() {
    return todoStore.todos
  }
}

License

Apache-2.0