Vue3 uses nested routes and Property 'xxx' does not exist on type encountered

1, In Vue3, the difference between the use of rouyou and Vue2

First, if you habitually use this$ Router, you will definitely get an error report, because Vue3 does not have this and uses a new API, so we need to introduce the function useRouter in router at this time

import { defineComponent, reactive} from "vue"
import { useRouter } from "vue-router"
export default defineComponent({
	setup() {
    const router = useRouter()
    console.log("router----",router)
    console.log("Information about the current route",router.currentRoute.value)
    return {}
    }
})

2, Vue3 uses nested routing to realize that the same button changes with the change of routing


Realize the information switching according to the route

If it is Vue2, you may think that this is not to directly define a mate attribute in the route, and the tag will respond directly according to {{$router.xxx}}?
Can only say: that bird food

But this is Vue3. You can't use $router directly. You can only implement it by introducing router

------- router.js -----

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'

const routes: Array<RouteRecordRaw> = [

  {
    path: '/',
    name: 'Index',
    redirect: '/index/home', // Use redirection to select the first sub route by default
    component: () => import(/* webpackChunkName: "index" */ '../views/Index.vue'),
    children: [
      {
        path: 'index/home',
        name: 'indexHome',
        meta: { title: 'Information square', toGo: {name:'Release information',pathName:'/index/release'}},
        component: () => import(/* webpackChunkName: "index" */ '../views/home/home.vue')
      },
      {
        path: 'index/release',
        name: 'Release',
        meta: {title:'Release information',toGo: {name:'Information square',pathName:'/index/home'}},
        component: () => import(/* webpackChunkName: "index" */ '../views/home/release.vue')
      }
    ]
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

Page header common component core fragment

import { defineComponent, reactive, watch } from "vue"
import { useRouter } from "vue-router"

export default defineComponent({
  setup() {
    const router = useRouter()

    let btnObj = reactive({ ...router.currentRoute.value })

    watch(
      () => router.currentRoute.value,
      (newValue, oldValue) => {
        console.log("watch", newValue);
        btnObj.meta = newValue.meta;
      },
      { immediate: true }
    )

    const goRouter = (val: string) => {
      router.push(val);
    }

    return {
      goRouter,
      btnObj,
    }
  },
})

The above is a normal way of writing

3, Error demonstration and problems

import { defineComponent, reactive, watch } from "vue"
import { useRouter } from "vue-router"

export default defineComponent({
  setup() {
    const router = useRouter()

    let btnObj = reactive({ router.currentRoute.value })

    watch(
      () => router.currentRoute.value,
      (newValue, oldValue) => {
        console.log("watch", newValue);
        btnObj= newValue
      },
      { immediate: true }
    )

    return {
      btnObj
    }
  },
})

It seems that there is nothing wrong with being used to vue2. I need to add it to be reactive. I'll just replace it after listening. It's OK.
At this time, as soon as you run, you will find that this is still wrong

let btnObj = reactive({ router.currentRoute.value });

If you say it's OK, then you'll think what's going on. Although I can't say mistakes in a very standardized way, I guess it's purely my own guess: because the router itself has reactive or other attributes / the router's address is given to btnObj, which leads to that btnObj will affect the router, which is not OK. (this is a deep and shallow clone)
All right, let's use the structure assignment of es6

let btnObj = reactive({ ...router.currentRoute.value })

That's good. Once it runs, it can be. Why doesn't it respond? In fact, we have to talk about the writing of vue3

Your original writing method is to write the attribute directly in data, which defaults to responsive, but here:

watch(
      () => router.currentRoute.value,
      (newValue, oldValue) => {
        console.log("watch", newValue);
        btnObj= newValue
      },
      { immediate: true }
    )

btnObj= newValue here is equivalent to overwriting the btnObj of a whole agent, which makes it impossible to change the value of your btnObj on the label responsively. Therefore, there is no problem that you can only change the met object in btnObj.

4, Property 'xxx' does not exist on type

This is because TS thinks that your copy type does not exist or the type you defined does not match or meet the requirements. It can make:
For example:
This in vue2 xxx can directly add a xxx to this, but it must be defined and reused in Vue3 TS, otherwise the attribute will not be detected

1. Set the object type to any

let _this: any = null;

2. Use as assertion

(_this as any).xxx = null;

  1. The simplest is to define first and then use

let _this : number = 1
_this = _this + 1

4. Use characters to obtain object properties

_this["xxx"] = 1;

If there are any mistakes or other methods above, you can discuss them in the comment area. Discussion can improve learning efficiency, inspect!!!!!

Keywords: Front-end TypeScript Vue

Added by quad on Mon, 07 Mar 2022 19:32:17 +0200