Skip to content

gaoupon/movue

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Movue npm version Build Status Coverage Status License

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

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

About

MobX integration for Vue.js.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 97.4%
  • JavaScript 2.6%