Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
alextoudic committed Nov 24, 2014
0 parents commit a1cf3e0
Show file tree
Hide file tree
Showing 34 changed files with 1,109 additions and 0 deletions.
7 changes: 7 additions & 0 deletions dev/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
node_modules
example/bundle.js
example/node_modules
example/bower_components
example/.server
example/public
151 changes: 151 additions & 0 deletions dev/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# vue-router

Routing plugin for Vue.js (v0.11). Based on Vue.js Guide about routing and using pagejs.

Basically, this plugin is just a wrapper for pagejs. It creates a global ViewModel in which your components will be rendered using v-component and v-transition so you can define methods which will be called before enter, on enter and/or on leave.

### Getting started

First install the plugin

`npm install vue-page --save`

### Initialize

Then initialize the plugin with your routes (see [pagejs](http://visionmedia.github.io/page.js) for more info on routes).

```javascript
var Vue = require('Vue'),
vuePage = require('vue-page');

Vue.use(vuePage, {
rootElement: '#app', //element in which the components will injected
class: 'page', //class of the components' wrappers (default is view)
base: '/base', //optionnal
routes: {
'/fr': {
'/accueil': 'home',
'/a-propos': 'about'
},
'/en': {
'/home': 'home',
'/about': 'about',
},
'/page/:id': 'pageId',
'/hello/:name': 'greetings',
'*': 'lost' //not found
},
default: '/base/en/home' //redirection for '/' if needed
});
```

This configuration will create the following routes (on right are the components names):

'/base/fr/accueil' -> 'home'

'/base/fr/a-propos' -> 'about'

'/base/en/home' -> 'home'

'/base/en/about' -> 'about'

'/page/:id' -> 'pageId'

'/hello/:name' -> 'greetings'

'*' -> 'lost'

Each component have to be defined in Vue.

### Usage

This plugin won't force you to implement your components with any specific syntax. Moreover, it allows you to define methods which will be fired by v-transition.

```javascript
var Vue = require('Vue'),
TweenMax = require('TweenMax');
var template = require('./template.html');

module.exports = Vue.component('home', {
template: template,
events: {
'router:update': function () {
console.log('url changed');
}
},
methods: {
helloVue: function () {
Vue.router.show('/hello/VueJS');
},

beforeEnter: function () {
TweenMax.set(this.$el, {
x: -window.innerWidth/2
});
},
enter: function (cb) {
TweenMax.to(this.$el, 0.8, {
x: 0,
onComplete: cb
});
},
leave: function (cb) {
TweenMax.to(this.$el, 0.8, {
x: -window.innerWidth/2,
onComplete: cb
});
}
}
});
```

As you can see in this component example, the plugin fires events. On startup, it fires 'router:start' and on each url change 'router:update'. So you can listen those events to do whatever you want.

You can also define beforeEnter, enter and leave as methods but they're all optionnal. It becomes pretty handy if you want fancy transitions between your pages. For enter and leave don't forget to call the callbacks, the world won't collapse but your DOM will be dirty as v-transition uses it to clean up.

You also have a Vue.router.show method which call the pagejs method so you can redirect your user on a other url.

### Params

All property from pagejs context are in cloned in a context property on your component using v-with. Thanks to that, if I go to /hello/world which fires /hello/:name and call my greetings component, I will be able to use name in my template as following

```html
<h1>Hello {{context.params.name}}</h1>
```

And of course, it doesn't need any specific development in my component instanciation

```javascript
var Vue = require('Vue');
var template = require('./template.html');

module.exports = Vue.component('greetings', {
template: template,
methods: {
beforeEnter: function () {
TweenMax.set(this.$el, {
y: -20,
opacity: 0
});
},
enter: function (cb) {
TweenMax.to(this.$el, 0.4, {
y: 0,
opacity: 1,
onComplete: cb
});
},
leave: function (cb) {
TweenMax.to(this.$el, 0.4, {
y: 20,
opacity: 0,
onComplete: cb
});
}
}
});
```

See, nothing but animations.

One more time, you should see [pagejs documentation](http://visionmedia.github.io/page.js/) to know what properties you can get from context.
1 change: 1 addition & 0 deletions dev/example/Gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var gulp = require('./gulp');
25 changes: 25 additions & 0 deletions dev/example/app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Vue Router</title>
<link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="/styles/main.css">
</head>

<body>
<div class="container">
<nav>
<a href="/base/en/home">Home</a>
<a href="/base/fr/accueil">Accueil</a>
<a href="/base/en/about">About</a>
<a href="/base/page/1">Page 1</a>
<a href="/base/page/2">Page 2</a>
</nav>
<div id="app">
</div>
</div>
</body>

<script type="text/javascript" src="/scripts/bundle.js"></script>

</html>
104 changes: 104 additions & 0 deletions dev/example/app/scripts/VuePage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
var page = require('page');

exports.install = function (Vue, args) {
var Router = Vue.extend({
created: function () {
if (args.default) {
page('/', function () {
window.location = args.default;
});
}

for (var route in this.$options.routes) {
this.parseRoute([route], this.$options.routes);
}
},

attached: function () {
page();
this.$broadcast('router:start');
},

methods: {
parseRoute: function (fragments, list) {
var route = fragments[fragments.length-1];

if (typeof list[route] == 'string') {
page(fragments.join(""), (function (ctx) {

Vue.nextTick((function () {

this.context = {
path: ctx.path,
canonicalPath: ctx.canonicalPath,
querystring: ctx.querystring,
pathname: ctx.pathname,
state: ctx.state,
title: ctx.title,
params: {}
};

for (var obj in ctx.params) {
this.context.params[obj] = ctx.params[obj];
}

this.currentView = list[route];
this.$broadcast('router:update');

}).bind(this));

}).bind(this));
}
else {
for (var subRoute in list[route]) {
this.parseRoute(fragments.concat(subRoute), list[route]);
}
}
},

show: function (path) {
page(path);
}
}
});

if (args.base) {
page.base(args.base);
}

var viewClass = (args.class) ? args.class : 'view';

Vue.page = new Router({
el: args.rootElement,
template: '<div class="'+viewClass+'" v-component="{{currentView}}" v-with="context: context" v-transition="view"></div>',
routes: args.routes,
data: {
currentView: null,
context: null
}
});

Vue.transition('view', {
beforeEnter: function () {
if (this.beforeEnter) {
this.beforeEnter();
}
},
enter: function (el, done) {
if (this.enter) {
this.enter(done);
}
else {
done();
}
},
leave: function (el, done) {
if (this.leave) {
this.leave(done);
}
else {
done();
}
}
});
};
27 changes: 27 additions & 0 deletions dev/example/app/scripts/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
var Vue = require('Vue'),
vuePage = require('./VuePage'),
home = require('./pages/home/controller'),
pageId = require('./pages/pageId/controller'),
about = require('./pages/about/controller'),
greetings = require('./pages/greetings/controller'),
lost = require('./pages/lost/controller');

Vue.use(vuePage, {
rootElement: '#app',
class: 'page',
base: '/base',
routes: {
'/fr': {
'/accueil': 'home',
'/a-propos': 'about'
},
'/en': {
'/home': 'home',
'/about': 'about',
},
'/page/:id': 'pageId',
'/hello/:name': 'greetings',
'*': 'lost'
},
default: '/base/en/home'
});
23 changes: 23 additions & 0 deletions dev/example/app/scripts/pages/about/controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
var Vue = require('Vue');
var template = require('./template.html');

module.exports = Vue.component('about', {
template: template,
methods: {
enter: function (cb) {
TweenMax.staggerFromTo('span', 0.2, {
y: -10,
opacity: 0
},{
y: 0,
opacity: 1
}, 0.1, cb);
},
leave: function (cb) {
TweenMax.staggerTo('span', 0.2, {
y: 10,
opacity: 0
}, 0.1, cb);
}
}
});
1 change: 1 addition & 0 deletions dev/example/app/scripts/pages/about/template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1><span>A</span><span>B</span><span>O</span><span>U</span><span>T</span></h1>
28 changes: 28 additions & 0 deletions dev/example/app/scripts/pages/greetings/controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
var Vue = require('Vue');
var template = require('./template.html');

module.exports = Vue.component('greetings', {
template: template,
methods: {
beforeEnter: function () {
TweenMax.set(this.$el, {
y: -20,
opacity: 0
});
},
enter: function (cb) {
TweenMax.to(this.$el, 0.4, {
y: 0,
opacity: 1,
onComplete: cb
});
},
leave: function (cb) {
TweenMax.to(this.$el, 0.4, {
y: 20,
opacity: 0,
onComplete: cb
});
}
}
});
1 change: 1 addition & 0 deletions dev/example/app/scripts/pages/greetings/template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>Hello {{context.params.name}}</h1>
Loading

0 comments on commit a1cf3e0

Please sign in to comment.