I defined a route in vue:

/users/:userId

Which point to UserComponent:

<template><div>{{username}}</div></template>

and I use computed from @vue/composition-api to get the data.

the problem is when the route change to another userId, by navigate to another user, the user in the html template not changed as what I expected. also it doesn't do redirect when the the user is not in the list.

So what I can do to fix that?

here is my code:

<template><div>{{username}}</div></template><script lang="ts">import { computed, defineComponent, ref, getCurrentInstance } from '@vue/composition-api';export const useUsername = ({ user }) => {return { username: user.name };};export default defineComponent({setup(props, { root }) {const vm = getCurrentInstance();const userToLoad = computed(() => root.$route.params.userId);const listOfUsers = [{ userId: 1, name: 'user1' },{ userId: 2, name: 'user2' },];const user = listOfUsers.find((u) => u.userId === +userToLoad.value);if (!user) {return root.$router.push('/404');}const { username } = useUsername({ user });return { username };},});</script>
9

Best Answer


You can just do this:

import { useRoute } from 'vue-router';export default {setup() {const route = useRoute();// Now you can access params like:console.log(route.params.id);}};

From the vue-router documentation:

import { useRouter, useRoute } from 'vue-router'export default {setup() {const router = useRouter()const route = useRoute()function pushWithQuery(query) {if (!user) {router.push({name: '404',query: {...route.query}})}}}}

A had the same problem. I use vue 2 and @vue/composition-api

My resolution:

Created: src/router/migrateRouterVue3.js

import { reactive } from '@vue/composition-api';import router from './index';const currentRoute = reactive({...router.currentRoute,});router.beforeEach((to, from, next) => {Object.keys(to).forEach(key => {currentRoute[key] = to[key];});next();});// eslint-disable-next-line import/prefer-default-exportexport function useRoute() {return currentRoute;}

after that, I can usage:

// import { useRoute } from 'vue-router';import { useRoute } from '@/router/migrateRouterVue3';

Resolution for you:

// replace:// const userToLoad = computed(() => root.$route.params.userId);// to: import { useRoute } from '@/router/migrateRouterVue3';//...const route = useRoute();const userToLoad = computed(() => route.params.userId);

You can pass the parameters as props to your components. Props are reactive by default.

This is how the route configuration could look like:

 {path: '/users/:userId',name: Users,component: YourComponent},

You can then use the props in your component with watchEffect()

<template><div>{{username}}</div></template><script lang="ts">import { computed, defineComponent, ref, getCurrentInstance, watchEffect } from '@vue/composition-api';export const useUsername = ({ user }) => {return { username: user.name };};export default defineComponent({props: {userId: {type: String, required: true },setup(props, { root }) {const vm = getCurrentInstance();const user = ref()const userToLoad = computed(() => props.userId);const listOfUsers = [{ userId: 1, name: 'user1' },{ userId: 2, name: 'user2' },];watchEffect(() => user.value = listOfUsers.find((u) => u.userId === +userToLoad.value))if (!user) {return root.$router.push('/404');}const { username } = useUsername({ user });return { username };},});</script>

watchEffect() will run immediately when defined and when reactive dependencies.change

function useRoute() {const vm = getCurrentInstance()if (!vm) throw new Error('must be called in setup')return vm.proxy.$route}

https://github.com/vuejs/composition-api/issues/630

The following useRoute hook will make route reactive so that it's doable:

const route = useRoute();const fooId = computed(()=>route.params.fooId);

let currentRoute = null;export const useRoute = () => {const self = getCurrentInstance(); const router = self.proxy.$router;if (!currentRoute) {const route = { ...self.proxy.$route };const routeRef = shallowRef(route);const computedRoute = {};for (const key of Object.keys(routeRef.value)) {computedRoute[key] = computed(() => routeRef.value[key]);}router.afterEach((to) => {routeRef.value = to;});currentRoute = reactive(computedRoute);}return currentRoute;};

The vue2-helpers package provides a useRoute function you can use in Vue 2.7 (and 2.6, 2.5 also).

Installation

# Vue 2.7$ npm install vue2-helpers@2# Vue 2.5 and 2.6$ npm install vue2-helpers@1

Usage

import { useRoute } from 'vue2-helpers/vue-router';const route = useRoute();const id: string | undefined = route.params.id;
const { proxy } = getCurrentInstance();

then use proxy to access $router or $route

Add please this code: watchEffect(() => userToLoad);