diff --git a/docs/en/SUMMARY.md b/docs/en/SUMMARY.md
index 587f60f02..138f4bbe3 100644
--- a/docs/en/SUMMARY.md
+++ b/docs/en/SUMMARY.md
@@ -13,6 +13,7 @@
   - [Named Routes](essentials/named-routes.md)
   - [Named Views](essentials/named-views.md)
   - [Redirect and Alias](essentials/redirect-and-alias.md)
+  - [Passing props](essentials/passing-props.md)
   - [HTML5 History Mode](essentials/history-mode.md)
 - Advanced
   - [Navigation Guards](advanced/navigation-guards.md)
diff --git a/docs/en/api/options.md b/docs/en/api/options.md
index b72f2ad50..5de3e690a 100644
--- a/docs/en/api/options.md
+++ b/docs/en/api/options.md
@@ -13,6 +13,7 @@
     name?: string; // for named routes
     components?: { [name: string]: Component }; // for named views
     redirect?: string | Location | Function;
+    props?: boolean | string | Function;
     alias?: string | Array<string>;
     children?: Array<RouteConfig>; // for nested routes
     beforeEnter?: (to: Route, from: Route, next: Function) => void;
diff --git a/docs/en/essentials/passing-props.md b/docs/en/essentials/passing-props.md
new file mode 100644
index 000000000..b6e20bdf2
--- /dev/null
+++ b/docs/en/essentials/passing-props.md
@@ -0,0 +1,72 @@
+# Passing props
+
+Using `$route` in your component creates a tight coupling with the route which limits the flexibility of the component as it can only be used on certain urls.
+
+To decouple this component from the router use props:
+
+**❌ Coupled to $route**
+
+``` js
+const User = {
+  template: '<div>User {{ $route.params.id }}</div>'
+}
+const router = new VueRouter({
+  routes: [
+    { path: '/user/:id', component: User }
+  ]
+})
+```
+
+**👍 Decoupled with props**
+
+``` js
+const User = {
+  props: ['id'],
+  template: '<div>User {{ id }}</div>'
+}
+const router = new VueRouter({
+  routes: [
+    { path: '/user/:id', component: User, props: true }
+  ]
+})
+```
+
+This allows you to use the component anywhere, which makes the component easier to reuse and test.
+
+### Boolean mode
+
+When props is set to true, the route.params will be set as the component props.
+
+### Object mode
+
+When props is an object, this will be set as the component props as-is.
+Useful for when the props are static.
+
+``` js
+const router = new VueRouter({
+  routes: [
+    { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
+  ]
+})
+```
+
+### Function mode
+
+You can create a function that returns props.
+This allows you to to cast the parameter to another type, combine static values with route-based values, etc.
+
+``` js
+const router = new VueRouter({
+  routes: [
+    { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
+  ]
+})
+```
+
+The url: `/search?q=vue` would pass `{query: "vue"}` as props to the SearchUser component.
+
+Try to keep the props function stateless, as it's only evaluated on route changes.
+Use a wrapper component if you need state to define the props, that way vue can react to state changes.
+
+
+For advanced usage, checkout the [example](https://github.com/vuejs/vue-router/blob/dev/examples/route-props/app.js).
diff --git a/examples/index.html b/examples/index.html
index 358d5f3fa..afde345b1 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -15,6 +15,7 @@ <h1>Vue Router Examples</h1>
     <li><a href="route-matching">Route Matching</a></li>
     <li><a href="active-links">Active Links</a></li>
     <li><a href="redirect">Redirect</a></li>
+    <li><a href="route-props">Route Props</a></li>
     <li><a href="route-alias">Route Alias</a></li>
     <li><a href="transitions">Transitions</a></li>
     <li><a href="data-fetching">Data Fetching</a></li>
diff --git a/examples/route-props/Hello.vue b/examples/route-props/Hello.vue
new file mode 100644
index 000000000..1205c6da5
--- /dev/null
+++ b/examples/route-props/Hello.vue
@@ -0,0 +1,17 @@
+<template>
+  <div>
+    <h2 class="hello">Hello {{name}}</h2>
+  </div>
+</template>
+
+<script>
+
+export default {
+  props: {
+    name: {
+      type: String,
+      default: 'Vue!'
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/examples/route-props/app.js b/examples/route-props/app.js
new file mode 100644
index 000000000..d39e682b3
--- /dev/null
+++ b/examples/route-props/app.js
@@ -0,0 +1,39 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+import Hello from './Hello.vue'
+
+Vue.use(VueRouter)
+
+function dynamicPropsFn (route) {
+  const now = new Date()
+  return {
+    name: (now.getFullYear() + parseInt(route.params.years)) + '!'
+  }
+}
+
+const router = new VueRouter({
+  mode: 'history',
+  base: __dirname,
+  routes: [
+    { path: '/', component: Hello }, // No props, no nothing
+    { path: '/hello/:name', component: Hello, props: true }, // Pass route.params to props
+    { path: '/static', component: Hello, props: { name: 'world' }}, // static values
+    { path: '/dynamic/:years', component: Hello, props: dynamicPropsFn } // custom logic for mapping between route and props
+  ]
+})
+
+new Vue({
+  router,
+  template: `
+    <div id="app">
+      <h1>Route props</h1>
+      <ul>
+        <li><router-link to="/">/</router-link></li>
+        <li><router-link to="/hello/you">/hello/you</router-link></li>
+        <li><router-link to="/static">/static</router-link></li>
+        <li><router-link to="/dynamic/1">/dynamic/1</router-link></li>
+      </ul>
+      <router-view class="view"></router-view>
+    </div>
+  `
+}).$mount('#app')
diff --git a/examples/route-props/index.html b/examples/route-props/index.html
new file mode 100644
index 000000000..0ebff0640
--- /dev/null
+++ b/examples/route-props/index.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<link rel="stylesheet" href="/global.css">
+<a href="/">&larr; Examples index</a>
+<div id="app"></div>
+<script src="/__build__/shared.js"></script>
+<script src="/__build__/route-props.js"></script>
diff --git a/src/components/view.js b/src/components/view.js
index c2d0e4c82..5cb8e9e67 100644
--- a/src/components/view.js
+++ b/src/components/view.js
@@ -1,3 +1,5 @@
+import { resolveProps } from '../util/props'
+
 export default {
   name: 'router-view',
   functional: true,
@@ -56,6 +58,7 @@ export default {
         matched.instances[name] = undefined
       }
     }
+    data.props = resolveProps(route, component, matched.props && matched.props[name])
 
     return h(component, data, children)
   }
diff --git a/src/create-route-map.js b/src/create-route-map.js
index c04ddd497..e00448ed5 100644
--- a/src/create-route-map.js
+++ b/src/create-route-map.js
@@ -44,6 +44,7 @@ function addRouteRecord (
     name,
     parent,
     matchAs,
+    props: typeof route.props === 'undefined' ? {} : (route.components ? route.props : { default: route.props }),
     redirect: route.redirect,
     beforeEnter: route.beforeEnter,
     meta: route.meta || {}
diff --git a/src/util/props.js b/src/util/props.js
new file mode 100644
index 000000000..c8889f2ba
--- /dev/null
+++ b/src/util/props.js
@@ -0,0 +1,26 @@
+
+import { warn } from './warn'
+
+export function resolveProps (route, component, config) {
+  switch (typeof config) {
+
+    case 'undefined':
+      return
+
+    case 'object':
+      return config
+
+    case 'function':
+      return config(route)
+
+    case 'boolean':
+      if (!config) {
+        return
+      }
+      return route.params
+
+    default:
+      warn(false, `props in "${route.path}" is a ${typeof config}, expecting an object, function or boolean.`)
+  }
+}
+
diff --git a/test/e2e/nightwatch.config.js b/test/e2e/nightwatch.config.js
index f3dd11859..08daf7ab8 100644
--- a/test/e2e/nightwatch.config.js
+++ b/test/e2e/nightwatch.config.js
@@ -1,4 +1,5 @@
 // http://nightwatchjs.org/guide#settings-file
+
 module.exports = {
   'src_folders': ['test/e2e/specs'],
   'output_folder': 'test/e2e/reports',
@@ -7,7 +8,7 @@ module.exports = {
 
   'selenium': {
     'start_process': true,
-    'server_path': 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar',
+    'server_path': require('selenium-server').path,
     'host': '127.0.0.1',
     'port': 4444,
     'cli_args': {
diff --git a/test/e2e/specs/route-props.js b/test/e2e/specs/route-props.js
new file mode 100644
index 000000000..7327be96e
--- /dev/null
+++ b/test/e2e/specs/route-props.js
@@ -0,0 +1,25 @@
+module.exports = {
+  'route-props': function (browser) {
+    browser
+    .url('http://localhost:8080/route-props/')
+      .waitForElementVisible('#app', 1000)
+      .assert.count('li a', 4)
+
+      .assert.urlEquals('http://localhost:8080/route-props/')
+      .assert.containsText('.hello', 'Hello Vue!')
+
+      .click('li:nth-child(2) a')
+      .assert.urlEquals('http://localhost:8080/route-props/hello/you')
+      .assert.containsText('.hello', 'Hello you')
+
+      .click('li:nth-child(3) a')
+      .assert.urlEquals('http://localhost:8080/route-props/static')
+      .assert.containsText('.hello', 'Hello world')
+
+      .click('li:nth-child(4) a')
+      .assert.urlEquals('http://localhost:8080/route-props/dynamic/1')
+      .assert.containsText('.hello', 'Hello ' + ((new Date()).getFullYear() + 1)+ '!')
+
+      .end()
+  }
+}