Giter Site home page Giter Site logo

eva.js's Introduction




eva.js is a complete solution to
building modern webs with Vue.js.

NPM version NPM downloads david dm

tl;dr

// model
app.model()
// router
app.router()
// bootstrap
app.start()

Play with the JSBin example or the simple webpack example 😀

Table of Contents

Sites using eva.js

Feel free to add your project here!

Features

  • Battery included, Vue 2 and its friends (Vuex & Vue-Router)
  • Small APIs, just Vue and the official plugins you already play well with!
  • Support server-side rendering, of course!
  • Inspired by the choo framework which is inpired by the elm architecture

Install

$ npm install --save eva.js

In case you may want to use it directly in browser instead, view https://unpkg.com/eva.js/dist/, and add:

<!-- global variable `EVA` is available as a constructor(class) -->
<!-- note that, you should use new EVA.default() to create app instance in browser -->
<script src="/path/to/eva.js"></script>

If you use the commonjs version and wanna include the runtime for vue template, follow the official guide:

Usage

import EVA from 'eva.js'

// Create app instance
const app = new EVA()

// A counter model
app.model({
  state: {count: 0},
  mutations: {
    INCREMENT(state) {state.count++}
  }
})

// A home view
const Home = {
  computed: {
    count() {
      return this.$store.state.count
    }
  },
  render(h) {
    return (
      <div>
        <h1>Home</h1>
        <button on-click={() => this.$store.commit('INCREMENT')}>
          {this.count}
        </button>
      </div>
    )
  }
}

// Apply views to relevant routes
// route(path, view, child_routes)
app.router(route => [
  route('/', Home)
])

// Start app
const App = {
  render(h) {
    return (
      <div id="app">
        <router-view></router-view>
      </div>
    )
  }
}
app.start(App, '#app')
// equal to
// app.start(App)
// app.mount('#app')

Concepts

Models

A model contains it's initial state and the methods you use to update its state, in fact, it's a typical Vuex module too.

Top-level model:

// An app instance only have at most one top-level model
app.model({
  state: {count: 0},
  mutations: {
    INCREMENT(state) {state.count++}
  }
})

Named/Namespaced model:

// An app could have multiple named models
app.model({
  name: 'user',
  state: {login: false},
  mutations: {
    LOG_IN(state) {state.login = true}
  }
})

By default only state are registered locally under provided name, eg state.user.login. But mutations actions getters are still in global namespace, to enforce name for those too, please change name to namespace:

app.model({
  namespace: 'user',
  state: {login: false},
  mutations: {
    LOG_IN(state) {state.login = true}
  },
  actions: {
    login({commit}) {
      commit('LOG_IN') //=> user/LOG_IN
    }
  }
})

Check out official docs for modules in vuex: http://vuex.vuejs.org/en/modules.html

In most cases using namespaces is beneficial, as having clear boundaries makes it easier to follow logic.

Helpers:

As how you use Vuex^2, you can use its helpers too:

const {mapState, mapActions, mapGetters} = require('eva.js')
// or ES6 modules
import {mapState, mapActions, mapGetters} from 'eva.js'

// of course you can directly import from 'vuex' too
import {mapState, mapActions, mapGetters} from 'vuex'

Router

The router could render the component which matches the URL path. It has a route helper for creating an actual route object used in vue-router. routes are passed in as a nested array.

app.router(route => [
  route('/', Home),
  route('/settings', Settings, [
    route('/profile', SettingsProfile),
    route('/password', SettingsPassword)
  ])
])

// use an object as route argument:
route({path: '/', component: Home, /*...*/})

// use an object as router argument:
app.router({
  mode: 'history',
  routes: []
})

The router state is effortlessly synced in vuex store.

Views

A view is a simple Vue component, that easy :)

Vue constructor

If you wan to access Vue constructor directly, simply do:

import {Vue} from 'eva.js'
// or without any change
// import Vue from 'vue'
// works too

Vue.use(yourPlugin)

Access $store and $router outside component

You can initialize your app and bootstrap it later:

// ./src/app.js
import EVA from 'eva.js'

const app = new EVA()

app.model() //...
app.router() //...

export default app.start()

// ./src/index.js
import app from './app'
app.mount('#app')

// ./some/other/file.js
import app from './path/to/src/app.js'

app.$router.push('/somewhere')

Server-side rendering

Similar to the official hackernews example:

// ./src/app.js
import EVA from 'eva.js'
import App from './App.vue'

const app = new EVA()

export default app.start(App)
// without selector!
// otherwise it will be mounted to the selector

Then for the server-entry.js:

// ./src/server-entry.js
import app from './app'

export default context => {
  // you can access app.$router / app.$store
  return Promise.all(operations)
    .then(() => {
      return app.instance
    })
}

For client-entry.js:

import app from './app'

app.mount('#app')

Promise polyfill

Some browsers do not have native Promise, like IE, but vuex requires Promise. Thus eva.js provides an lightweight Promise polyfill with promise-polyfill.

import 'eva.js/promise-polyfill'
import EVA from 'eva.js'
// ... your app code

API

new EVA([options: object])

Create an app instance.

options.mode

The router mode, can be either hash (default) or history.

app.model(model: object)

Register a model, a.k.a. store module in Vuex. You can omit the name and namespace property to make it top-level.

app.router(handler: function)

Register routes.

app.use(plugin: function, [options: object])

The same as Vue.use, you can apply any Vue plugin.

app.start([App: object], [selector: string])

Create app instance. Optionally mount App component to a domNode if selector is defined.

If App is not specified, we use a default value:

const defaultApp = {
  render(h) {
    return <div id="app"><router-view></router-view></div>
  }
}

If selector is not specified, we won't mount the app instance to dom.

app.mount(selector)

Mounted app instance to dom, must be call after app.start([App]) (without selector argument). Default selector is #app

app.syncRouterInStore()

keep vue-router and vuex store in sync, i.e. keep router state in vuex store.

The method will be called automatically in app.start(), you can also call it manually before app.start() and app.start() won't call it again.

app.$store

The vuex store instance.

app.$router

The vue-router instance.

app.instance

The Vue instance created by app.start(), most likely you will use this in server-side rendering.

Development

# build and watch source files
$ npm run watch

# launch server for simple html example
$ http-server .
# run webpack example
$ npm run webpack

# build for publish to npm
# cjs and umd and compressed umd
$ npm run build

License

MIT © EGOIST

eva.js's People

Contributors

egoist avatar greenkeeperio-bot avatar zigomir avatar

Stargazers

Sadegh Barati avatar  avatar xuyanchao avatar ljy avatar  avatar 奇山流云 avatar bigboy avatar  avatar David Dias avatar Nikolaus Schlemm avatar Rasmus Hallström avatar  avatar Daniel Angel avatar Joyce Wang avatar Karl Lindberg & Kilian Güntner avatar misakar avatar BYUNGI avatar Goudarz Jafari avatar Richard Thiel avatar Brian Lee avatar trkw avatar Ellomend avatar Sundar Joshi avatar yeraycaballero avatar Maylis Agniel avatar David Authier avatar Rémi B avatar Oskar avatar Matt Walker avatar Jon avatar Jon-Kyle avatar Yotam avatar Tiberiu Ichim avatar GrandSong avatar 文蔺 avatar Niklas Rämö avatar  avatar CrownHuang avatar santiblanko avatar Roeefl avatar Charlike Mike Reagent avatar Jonas Oppenlaender avatar  avatar Samuel avatar cybai (Haku) avatar Rita Zerrizuela avatar  avatar Pete Houston avatar 9r0k avatar Ed Costello avatar Ku  avatar Anton Kulakov avatar Matthias Hager avatar Josh Teneycke avatar  avatar Marvin ROGER avatar Gerald avatar Justin Bennett avatar leo avatar xream avatar videogramme avatar listen avatar Riderman de Sousa Barbosa avatar AJ avatar Ned Baldessin avatar Christof Leuenberger avatar Kamil Dąbrowski avatar William Wanyama avatar Julius Mziray avatar Zehang Lin avatar sascha fuchs avatar Santiago avatar Daniel Rubin avatar Icebob avatar Mardari Igor avatar Rildo Moraes avatar Donghua Li avatar  avatar Raí Siqueira avatar Alan Ktquez avatar NOOB avatar Marco Ferreira avatar David Mamane avatar Sebastian Szczepański avatar Sebastian Senf avatar Allan Raquin avatar Heru Rusdianto avatar Kohei Ito avatar Diovane Monteiro avatar Yassine A. avatar David Feinberg avatar Jake Ingman avatar Ryan avatar chenls avatar Tristan Bessoussa avatar Souhail KAOUSSI avatar Peter Brinck avatar Vitaliy Abramov avatar young avatar Luc Vancrayelynghe avatar

Watchers

James Cloos avatar Randy avatar Adam Macias avatar hbc avatar Xianliang Wu avatar  avatar Azamat avatar  avatar  avatar  avatar

eva.js's Issues

Use peerDependencies for vue and vuex etc?

Doing this would mean you don't have to continually do updates to this project to make sure you are using the latest and greatest.

You could probably limit it to MINOR version numbers:

2.0.x

Not sure if it would work with the current RC versions though?

Give access to the Vue object (e.g. vue-resource in models)

I register VueResource with app.use() and it works fine from within my components, as I can access this.$http. However, if we want to use VueResource outside of the components (inside of models for example), we have to access it directly on the vue instance, through vue.http. But eva does not provide access to the underlying vue instance. Or maybe I am missing something?

Add tests

There're a few tests on the way:

  • app.model
  • app.use
  • app.router
  • app.start
  • ...more

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.