From 643d07336f4bbdf7ff38783c6981d47b55efdd4d Mon Sep 17 00:00:00 2001 From: "qingwei.li" Date: Mon, 29 Jan 2018 17:56:10 +0800 Subject: [PATCH 1/6] feat: funtional router-link --- src/components/link.js | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/components/link.js b/src/components/link.js index 10d3d118d..44b4c9989 100644 --- a/src/components/link.js +++ b/src/components/link.js @@ -9,6 +9,7 @@ const eventTypes: Array = [String, Array] export default { name: 'RouterLink', + functional: true, props: { to: { type: toTypes, @@ -28,10 +29,10 @@ export default { default: 'click' } }, - render (h: Function) { - const router = this.$router - const current = this.$route - const { location, route, href } = router.resolve(this.to, current, this.append) + render (h: Function, { props, children, parent, data }) { + const router = parent.$router + const current = parent.$route + const { location, route, href } = router.resolve(props.to, current, props.append) const classes = {} const globalActiveClass = router.options.linkActiveClass @@ -43,24 +44,25 @@ export default { const exactActiveClassFallback = globalExactActiveClass == null ? 'router-link-exact-active' : globalExactActiveClass - const activeClass = this.activeClass == null + const activeClass = props.activeClass == null ? activeClassFallback - : this.activeClass - const exactActiveClass = this.exactActiveClass == null + : props.activeClass + const exactActiveClass = props.exactActiveClass == null ? exactActiveClassFallback - : this.exactActiveClass + : props.exactActiveClass const compareTarget = location.path ? createRoute(null, location, null, router) : route + const extend = _Vue.util.extend classes[exactActiveClass] = isSameRoute(current, compareTarget) - classes[activeClass] = this.exact + classes[activeClass] = props.exact ? classes[exactActiveClass] : isIncludedRoute(current, compareTarget) const handler = e => { if (guardEvent(e)) { - if (this.replace) { + if (props.replace) { router.replace(location) } else { router.push(location) @@ -68,27 +70,24 @@ export default { } } + data.class = extend(data.class || {}, classes) + const on = { click: guardEvent } - if (Array.isArray(this.event)) { - this.event.forEach(e => { on[e] = handler }) + if (Array.isArray(props.event)) { + props.event.forEach(e => { on[e] = handler }) } else { - on[this.event] = handler - } - - const data: any = { - class: classes + on[props.event] = handler } - if (this.tag === 'a') { + if (props.tag === 'a') { data.on = on data.attrs = { href } } else { // find the first child and apply listener and href - const a = findAnchor(this.$slots.default) + const a = findAnchor(children) if (a) { // in case the is a static node a.isStatic = false - const extend = _Vue.util.extend const aData = a.data = extend({}, a.data) aData.on = on const aAttrs = a.data.attrs = extend({}, a.data.attrs) @@ -99,7 +98,7 @@ export default { } } - return h(this.tag, data, this.$slots.default) + return h(props.tag, data, children) } } From 34d8f9524dcf5f527b290611dff6750cd15be2f7 Mon Sep 17 00:00:00 2001 From: "qingwei.li" Date: Mon, 29 Jan 2018 19:55:28 +0800 Subject: [PATCH 2/6] fix(router-link): add type annotation --- src/components/link.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/link.js b/src/components/link.js index 44b4c9989..03d9370c8 100644 --- a/src/components/link.js +++ b/src/components/link.js @@ -29,7 +29,7 @@ export default { default: 'click' } }, - render (h: Function, { props, children, parent, data }) { + render (h: Function, { props, children, parent, data }: any) { const router = parent.$router const current = parent.$route const { location, route, href } = router.resolve(props.to, current, props.append) From 1c05d1aaf5ad1c16041f59cbe36a58022095d7c8 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Mon, 2 Apr 2018 22:55:41 +0200 Subject: [PATCH 3/6] fix: replace this by props --- src/components/link.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/link.js b/src/components/link.js index b6d619c53..0655e339b 100644 --- a/src/components/link.js +++ b/src/components/link.js @@ -44,12 +44,12 @@ export default { const exactActiveClassFallback = globalExactActiveClass == null ? 'router-link-exact-active' : globalExactActiveClass - const activeClass = this.activeClass == null + const activeClass = props.activeClass == null ? activeClassFallback - : this.activeClass - const exactActiveClass = this.exactActiveClass == null + : props.activeClass + const exactActiveClass = props.exactActiveClass == null ? exactActiveClassFallback - : this.exactActiveClass + : props.exactActiveClass const compareTarget = location.path ? createRoute(null, location, null, router) : route From ac64999039aba0d9a27fd75742bc1925238e8f38 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 10 Apr 2018 13:35:14 +0200 Subject: [PATCH 4/6] test(link): test preservation of custom classes --- examples/index.html | 1 + examples/router-link/app.js | 27 +++++++++++++++++++++++++++ examples/router-link/index.html | 14 ++++++++++++++ test/e2e/specs/router-link.js | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 examples/router-link/app.js create mode 100644 examples/router-link/index.html create mode 100644 test/e2e/specs/router-link.js diff --git a/examples/index.html b/examples/index.html index f2bdf7225..e024d8295 100644 --- a/examples/index.html +++ b/examples/index.html @@ -17,6 +17,7 @@

Vue Router Examples

  • Redirect
  • Route Props
  • Route Alias
  • +
  • Router Link
  • Transitions
  • Data Fetching
  • Navigation Guards
  • diff --git a/examples/router-link/app.js b/examples/router-link/app.js new file mode 100644 index 000000000..36542ff28 --- /dev/null +++ b/examples/router-link/app.js @@ -0,0 +1,27 @@ +import Vue from 'vue' +import VueRouter from 'vue-router' + +Vue.use(VueRouter) + +const Home = { template: '

    Home

    ' } + +const router = new VueRouter({ + mode: 'history', + base: __dirname, + routes: [ + { path: '/', component: Home } + ] +}) + +new Vue({ + router, + template: ` +
    +

    Router Link lol

    +
      +
    • /
    • +
    + +
    + ` +}).$mount('#app') diff --git a/examples/router-link/index.html b/examples/router-link/index.html new file mode 100644 index 000000000..abe63b876 --- /dev/null +++ b/examples/router-link/index.html @@ -0,0 +1,14 @@ + + + +← Examples index +
    + + diff --git a/test/e2e/specs/router-link.js b/test/e2e/specs/router-link.js new file mode 100644 index 000000000..b7eca3b8b --- /dev/null +++ b/test/e2e/specs/router-link.js @@ -0,0 +1,32 @@ +// This test should be done in a unit test once we migrate to jest + +module.exports = { + 'router link': function (browser) { + browser + .url('http://localhost:8080/router-link/') + .waitForElementVisible('#app', 1000) + // assert correct href with base + .assert.cssClassPresent('li:nth-child(1) a', 'custom-class') + .assert.containsText('.view', 'Home') + + browser.end() + + function assertActiveLinks (n, activeA, activeLI, exactActiveA, exactActiveLI) { + browser.click(`li:nth-child(${n}) a`) + activeA.forEach(i => { + browser.assert.cssClassPresent(`li:nth-child(${i}) a`, 'router-link-active') + }) + activeLI && activeLI.forEach(i => { + browser.assert.cssClassPresent(`li:nth-child(${i})`, 'router-link-active') + }) + exactActiveA.forEach(i => { + browser.assert.cssClassPresent(`li:nth-child(${i}) a`, 'router-link-exact-active') + .assert.cssClassPresent(`li:nth-child(${i}) a`, 'router-link-active') + }) + exactActiveLI && exactActiveLI.forEach(i => { + browser.assert.cssClassPresent(`li:nth-child(${i})`, 'router-link-exact-active') + .assert.cssClassPresent(`li:nth-child(${i})`, 'router-link-active') + }) + } + } +} From 9b83eb1915c76d381661eef0ba8e0b9fdf53accc Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 10 Apr 2018 14:32:04 +0200 Subject: [PATCH 5/6] test(link): add tests for nested params and custom props --- examples/router-link/app.js | 27 ++++++++++++++++++++++++--- test/e2e/specs/router-link.js | 17 ++++++++++++++++- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/examples/router-link/app.js b/examples/router-link/app.js index 36542ff28..3283bcb24 100644 --- a/examples/router-link/app.js +++ b/examples/router-link/app.js @@ -3,13 +3,27 @@ import VueRouter from 'vue-router' Vue.use(VueRouter) -const Home = { template: '

    Home

    ' } +const Home = { template: '

    {{ $route.fullPath }}

    ' } +const Sub = { template: '

    Nested View

    ' } +const SubNested = { template: '

    Sub

    {{ $route.params.id }}
    ' } + +const CustomLink = { + props: ['disabled', 'n'], + template: '' +} + +Vue.component('CustomLink', CustomLink) const router = new VueRouter({ mode: 'history', base: __dirname, routes: [ - { path: '/', component: Home } + { path: '/', component: Home }, + { path: '/other', component: Home }, + { path: '/sub/:id', component: Sub, children: [ + { path: 'nested1', component: SubNested, name: 'sub1' }, + { path: 'nested2', component: SubNested, name: 'sub2' } + ]} ] }) @@ -19,7 +33,14 @@ new Vue({

    Router Link lol

      -
    • /
    • +
    • /
    • +
    • CustomLink
    • +
    • /
    • +
    • /other
    • +
    • /sub/1
    • +
    • /sub/2
    • +
    • /sub/:id/nested1
    • +
    • /sub/:id/nested2
    diff --git a/test/e2e/specs/router-link.js b/test/e2e/specs/router-link.js index b7eca3b8b..4f89f94e3 100644 --- a/test/e2e/specs/router-link.js +++ b/test/e2e/specs/router-link.js @@ -7,7 +7,22 @@ module.exports = { .waitForElementVisible('#app', 1000) // assert correct href with base .assert.cssClassPresent('li:nth-child(1) a', 'custom-class') - .assert.containsText('.view', 'Home') + .assert.cssClassPresent('li:nth-child(1) a', 'otherClass') + .assert.cssClassPresent('li:nth-child(1) a', 'router-link-active') + + .assert.containsText('li:nth-child(2) button', 'N CustomLink') + + .assert.attributeContains('li:nth-child(3) a', 'style', 'color:') + .assert.attributeContains('li:nth-child(3) a', 'style', 'font-size: 8px') + + .click('li:nth-child(5) a') + .assert.attributeContains('li:nth-child(7) a', 'href', '/router-link/sub/1/nested1') + .assert.attributeContains('li:nth-child(8) a', 'href', '/router-link/sub/1/nested2') + .click('li:nth-child(6) a') + .assert.attributeContains('li:nth-child(7) a', 'href', '/router-link/sub/2/nested1') + .assert.attributeContains('li:nth-child(8) a', 'href', '/router-link/sub/2/nested2') + + browser.expect.element('li:nth-child(2) button').to.have.attribute('disabled') browser.end() From db674f4e5df5856401823e3aff5c4d7f9aaf1b91 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 10 Apr 2018 14:34:53 +0200 Subject: [PATCH 6/6] chore(lint): fix --- examples/router-link/app.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/router-link/app.js b/examples/router-link/app.js index 3283bcb24..f39a9cd5c 100644 --- a/examples/router-link/app.js +++ b/examples/router-link/app.js @@ -20,10 +20,14 @@ const router = new VueRouter({ routes: [ { path: '/', component: Home }, { path: '/other', component: Home }, - { path: '/sub/:id', component: Sub, children: [ - { path: 'nested1', component: SubNested, name: 'sub1' }, - { path: 'nested2', component: SubNested, name: 'sub2' } - ]} + { + path: '/sub/:id', + component: Sub, + children: [ + { path: 'nested1', component: SubNested, name: 'sub1' }, + { path: 'nested2', component: SubNested, name: 'sub2' } + ] + } ] })