Skip to content

Commit

Permalink
feat: useRoute and useRouter
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Aug 22, 2022
1 parent 337bde7 commit ea35594
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 27 deletions.
78 changes: 78 additions & 0 deletions examples/composables/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import Vue, { defineComponent, watch, ref, onUnmounted } from 'vue'
import VueRouter from 'vue-router'
import { useRoute, useRouter } from 'vue-router/composables'

Vue.use(VueRouter)

const Home = defineComponent({
setup () {
const route = useRoute()
const router = useRouter()

// should be /
const startRoute = route.fullPath

console.log('got to Home', startRoute)

const watchCount = ref(0)

watch(() => route.query.n, () => {
console.log('watched')
watchCount.value++
})

onUnmounted(() => {
console.log('unmounted')
})

function navigate () {
router.push({ query: { n: 1 + (Number(route.query.n) || 0) }})
}
return { route, navigate, watchCount, startRoute }
},
template: `
<div>
<h2>Home</h2>
<p id="start-route">{{ startRoute }}</p>
<p id='watch-count'>{{ watchCount }}</p>
<p id="fullpath">{{ route.fullPath }}</p>
<button id="nav" @click="navigate">Navigate</button>
</div>
`
})

const About = defineComponent({
setup () {
const route = useRoute()
return { route }
},
template: `
<div>
<h2>About</h2>
<p id="fullpath">{{ route.fullPath }}</p>
</div>
`
})

const router = new VueRouter({
mode: 'history',
base: __dirname,
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
})

new Vue({
router,
template: `
<div id="app">
<h1>Basic</h1>
<ul>
<li><router-link to="/">/</router-link></li>
<li><router-link to="/about">/foo</router-link></li>
</ul>
<router-view class="view"></router-view>
</div>
`
}).$mount('#app')
7 changes: 7 additions & 0 deletions examples/composables/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!DOCTYPE html>
<link rel="stylesheet" href="/global.css">
<a href="/">&larr; Examples index</a>
<hr />
<div id="app"></div>
<script src="/__build__/shared.chunk.js"></script>
<script src="/__build__/composables.js"></script>
1 change: 1 addition & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ <h1>Vue Router Examples</h1>
<li><a href="keepalive-view">Keepalive View</a></li>
<li><a href="multi-app">Multiple Apps</a></li>
<li><a href="restart-app">Restart App</a></li>
<li><a href="composables">Composables</a></li>
</ul>
</body>
</html>
3 changes: 2 additions & 1 deletion examples/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ module.exports = {
resolve: {
alias: {
vue: 'vue/dist/vue.esm.js',
'vue-router': path.join(__dirname, '..', 'src')
'vue-router': path.join(__dirname, '..', 'src'),
'vue-router/composables': path.join(__dirname, '..', 'src/composables.js')
}
},

Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@
"rollup-watch": "^4.0.0",
"selenium-server": "^3.141.59",
"terser": "^4.2.0",
"typescript": "^3.5.2",
"vue": "^2.6.12",
"typescript": "^4.7.0",
"vue": "^2.7.0",
"vue-loader": "^15.9.3",
"vue-server-renderer": "^2.6.12",
"vue-template-compiler": "^2.6.12",
"vue-server-renderer": "^2.7.0",
"vue-template-compiler": "^2.7.0",
"vuepress": "^1.5.3",
"vuepress-theme-vue": "^1.1.1",
"webpack": "^4.35.2",
Expand Down
46 changes: 46 additions & 0 deletions src/composables.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { getCurrentInstance, shallowReactive, effectScope } from 'vue'

export function useRouter () {
const i = getCurrentInstance()
if (process.env.NODE_ENV !== 'production' && !i) {
throwNoCurrentInstance('useRouter')
}

return i.proxy.$root.$router
}

export function useRoute () {
const i = getCurrentInstance()
if (process.env.NODE_ENV !== 'production' && !i) {
throwNoCurrentInstance('useRoute')
}

const root = i.proxy.$root
if (!root._$route) {
const route = effectScope(true).run(
() => shallowReactive(Object.assign({}, root.$router.currentRoute))
)
root._$route = route

root.$router.afterEach(to => {
Object.assign(route, to)
})
}

return root._$route
}

// TODO:
// export function useLink () {}

// TODO:
// export function onBeforeRouteUpdate () {}

// TODO:
// export function onBeforeRouteLeave () {}

function throwNoCurrentInstance (method) {
throw new Error(
`[vue-router]: Missing current instance. ${method}() must be called inside <script setup> or setup().`
)
}
29 changes: 29 additions & 0 deletions test/e2e/specs/composables.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const bsStatus = require('../browserstack-send-status')

module.exports = {
...bsStatus(),

'@tags': ['history'],

'useRoute() + useRouter()': function (browser) {
browser
.url('http://localhost:8080/composables/')
.waitForElementVisible('#app', 1000)
.assert.count('li', 2)
.assert.count('li a', 2)
.assert.containsText('.view', 'Home')

.click('li:nth-child(2) a')
.assert.containsText('.view', 'About')
.click('li:nth-child(1) a')
.assert.containsText('.view', 'Home')
.assert.containsText('#start-route', '/')
.assert.containsText('#fullpath', '/')

.click('button#nav')
.assert.containsText('#fullpath', '/?n=1')

.end()
}

}
Loading

0 comments on commit ea35594

Please sign in to comment.