From cb136b509b41b19d3f1d1151dbe2f26db1124bd1 Mon Sep 17 00:00:00 2001 From: Jonathan Hartman Date: Fri, 20 Jan 2017 09:58:33 -0700 Subject: [PATCH 1/2] Issue:1102 - Allow injecting router to discrete Vue instances and ensure the $route (getter) returns consisten value --- examples/discrete-components/app.js | 37 +++++++++++++++++++ examples/discrete-components/index.html | 41 +++++++++++++++++++++ examples/index.html | 1 + src/index.js | 9 ++++- test/unit/specs/discrete-components.spec.js | 22 +++++++++++ 5 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 examples/discrete-components/app.js create mode 100644 examples/discrete-components/index.html create mode 100644 test/unit/specs/discrete-components.spec.js diff --git a/examples/discrete-components/app.js b/examples/discrete-components/app.js new file mode 100644 index 000000000..2b42ac368 --- /dev/null +++ b/examples/discrete-components/app.js @@ -0,0 +1,37 @@ +import Vue from 'vue' +import VueRouter from 'vue-router' + +// 1. Use plugin. +// This installs and , +// and injects $router and $route to all router-enabled child components +Vue.use(VueRouter) + +// 2. Define route components +const Home = { template: '
Component: home
' } +const Foo = { template: '
Component: foo
' } +const Bar = { template: '
Component: bar
' } + +// 3. Create the router +const router = new VueRouter({ + mode: 'history', + base: __dirname, + routes: [ + { path: '/', component: Home }, + { path: '/foo', component: Foo }, + { path: '/bar', component: Bar } + ] +}) + +// 4. Create extended base Vue with router injected here (all +// children should inherit the same router). +const BaseVue = Vue.extend({ router }) + +// Discrete components means that a new Vue instance will be created +// and bound on multiple *independent* nodes (eg. one Vue instance +// per node); but the router should act as a singleton and keep all +// instances in sync. +document.querySelectorAll('.app').forEach((node) => { + new BaseVue({ + el: node + }) +}) diff --git a/examples/discrete-components/index.html b/examples/discrete-components/index.html new file mode 100644 index 000000000..3300621b1 --- /dev/null +++ b/examples/discrete-components/index.html @@ -0,0 +1,41 @@ + + + +← Examples index +
+
+
    +
  • /
  • +
  • /foo
  • +
  • /bar
  • +
+ $route.path value: {{ $route.path }} +
+
+
    +
  • /
  • +
  • /foo
  • +
  • /bar
  • +
+ $route.path value: {{ $route.path }} +
+
+
    +
  • /
  • +
  • /foo
  • +
  • /bar
  • +
+ $route.path value: {{ $route.path }} +
+
+
+ + $route.path value: {{ $route.path }} +
+ + diff --git a/examples/index.html b/examples/index.html index afde345b1..cd7a7a1f3 100644 --- a/examples/index.html +++ b/examples/index.html @@ -23,6 +23,7 @@

Vue Router Examples

  • Scroll Behavior
  • Lazy Loading
  • Auth Flow
  • +
  • Discrete Components
  • diff --git a/src/index.js b/src/index.js index 3061ca79f..f06c83ba7 100644 --- a/src/index.js +++ b/src/index.js @@ -15,6 +15,7 @@ export default class VueRouter { static install: () => void; static version: string; + apps: Array; app: any; options: RouterOptions; mode: string; @@ -26,6 +27,7 @@ export default class VueRouter { constructor (options: RouterOptions = {}) { this.app = null + this.apps = [] this.options = options this.beforeHooks = [] this.afterHooks = [] @@ -69,6 +71,7 @@ export default class VueRouter { `before creating root instance.` ) + this.apps.push(app) this.app = app const history = this.history @@ -89,7 +92,11 @@ export default class VueRouter { } history.listen(route => { - this.app._route = route + this.apps.forEach((app) => { + if (app) { + app._route = route + } + }) }) } diff --git a/test/unit/specs/discrete-components.spec.js b/test/unit/specs/discrete-components.spec.js new file mode 100644 index 000000000..a0d1bf077 --- /dev/null +++ b/test/unit/specs/discrete-components.spec.js @@ -0,0 +1,22 @@ +import Vue from 'vue' +import VueRouter from '../../../src/index' + +describe('[Vue Instance].$route bindings', () => { + describe('boundToSingleVueInstance', () => { + it('updates $route on all instances', () => { + const router = new VueRouter({ + routes: [ + { path: '/', component: { name: 'foo' }}, + { path: '/bar', component: { name: 'bar' }} + ] + }) + const app1 = new Vue({ router }) + const app2 = new Vue({ router }) + expect(app1.$route.path).toBe('/') + expect(app2.$route.path).toBe('/') + router.push('/bar') + expect(app1.$route.path).toBe('/bar') + expect(app2.$route.path).toBe('/bar') + }) + }) +}) From 5e6ab6db9ff1151b0dffa7fa352788953231e771 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 23 Jan 2017 15:51:22 -0500 Subject: [PATCH 2/2] avoid initializing the router more than once --- src/index.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index f06c83ba7..faa1b0374 100644 --- a/src/index.js +++ b/src/index.js @@ -15,8 +15,8 @@ export default class VueRouter { static install: () => void; static version: string; - apps: Array; app: any; + apps: Array; options: RouterOptions; mode: string; history: HashHistory | HTML5History | AbstractHistory; @@ -72,6 +72,12 @@ export default class VueRouter { ) this.apps.push(app) + + // main app already initialized. + if (this.app) { + return + } + this.app = app const history = this.history @@ -93,9 +99,7 @@ export default class VueRouter { history.listen(route => { this.apps.forEach((app) => { - if (app) { - app._route = route - } + app._route = route }) }) }