Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Routing

WinJS applications aresingle-page applications, where page navigation is completed on the browser side without requesting HTML from the server again. HTML is only loaded once during application initialization. All pages are composed of different components, and page switching is actually switching between different components. You just need to associate different route paths with corresponding components in the configuration.

Route Type Configuration

Please refer tohistory configuration.

Configuring Routes

Configure routes throughroutes in the configuration file, formatted as an array of route information.

For example:

ts
// .winrc.tsexport default {  routes: [    { path:'/', component:'index' },    { path:'/user', component:'user' },  ],}

WinJS splits bundles by page by default for faster page loading speeds. Since the loading process is asynchronous, you often need to write or reference something likenprogress to add loading styles to your project and improve the experience.

Tip

You can set the network to slow speed in Chrome Devtools > Network tab, then switch routes to check if component loading is working.

path

  • Type:string

path only supports two types of placeholder configurations: the first is dynamic parameters in the form of:id, and the second is* wildcards, which can only appear at the end of the route string.

✅ The following are currentlysupported route path configuration forms:

txt
/groups/groups/admin/users/:id/users/:id/messages/files/*/files/:id/*

❌ The following are currentlynot supported route path configuration forms:

txt
/users/:id?/tweets/:id(\d+)/files/*/cat.jpg/files-*

name

Named routes

Besidespath, you can also provide aname for any route:

ts
export default {  routes: [    {      path:'/user/:username',      name:'user',      component:'index'    }  ]}

To link to a named route, you can pass an object to therouter-link component'sto property:

html
<router-link :to="{ name: 'user', params: { username: 'erina' }}">  User</router-link>

This has the same effect as callingrouter.push imperatively:

ts
router.push({ name:'user', params: { username:'erina' } })

Both methods can navigate to the path/user/erina.

alias

A redirect means that when a user visits/home, the URL will be replaced by/, and then matched as/. So what is an alias?

Aliasing/ as/home means that when a user visits/home, the URL remains/home, but it will be matched as if the user is visiting/.

The corresponding route configuration is:

ts
export default {  routes: [    {      path:'/',      component:'index',      alias:'/home'    }  ]}

Through aliases, you can freely map UI structure to any URL without being constrained by the nested structure of the configuration. Make aliases start with/ to make paths in nested routes absolute paths. You can even combine both and provide multiple aliases with an array:

ts
export default {  routes: [    {      path:'/users',      component:'users',      routes: [        // Render UserList for these 3 URLs        // - /users        // - /users/list        // - /people        { path:'', component:'/users/UserList', alias: ['/people','list'] },      ]    }  ]}

meta

When defining routes, we can configure themeta field to extend route meta information and record some route-related information:

js
const router = new VueRouter({  routes: [    {      path:'/foo',      component: Foo,      routes: [        {          path:'bar',          component: Bar,          // a meta field          meta: {            title:'bar',            requiresAuth:true          },        },      ],    },  ],});

component

  • Type:string

Configure the React component path used for rendering after location and path matching. It can be an absolute path or a relative path. If it's a relative path, it will start searching fromsrc/pages.

If pointing to a file in thesrc directory, you can use@, for examplecomponent: '@/layouts/basic'. It's recommended to use@ to organize route file locations.

routes

Configure child routes, usually used when you need to add layout components for multiple paths.

For example:

js
export default {  routes: [    { path:'/login', component:'login' },    {      path:'/',      component:'@/layouts/index',      routes: [        { path:'/list', component:'list' },        { path:'/admin', component:'admin' },      ],    },  ],}

In the global layoutsrc/layouts/index, render child routes through<router-view />:

tsx
export default function Page() {  return (    <div style={{ padding:20 }}>      <router-view />    </div>  )}

This way, accessing/list and/admin will include thesrc/layouts/index layout component.

redirect

  • Type:string

Configure route redirection.

For example:

js
export default {  routes: [    { path:'/', redirect:'/list' },    { path:'/list', component:'list' },  ],}

Accessing/ will redirect to/list and be rendered by thesrc/pages/list file.

The redirect target can also be a named route. The following example redirects from/home to/:

ts
export default {  routes: [    {      path:'/home',      redirect: {        name:'homepage'      }    }  ]}

wrappers

  • Type:string[]

Configure wrapper components for route components. Wrapper components can combine more functionality into the current route component. For example, it can be used for route-level permission verification:

js
export default {  routes: [    {      path:'/user', component:'user',      wrappers: [        '@/wrappers/auth',      ],    },    { path:'/login', component:'login' },  ]}

Then insrc/wrappers/auth,

jsx
export default (props)=> {  const {isLogin }= useAuth();  if (isLogin) {    return <router-view />;  }else {    return <router-link to="/login" />;  }}

This way, when accessing/user, permission verification is performed through theauth component. If passed,src/pages/user is rendered, otherwise it redirects to/login.

Note

Each component inwrappers will add a nested route layer to the current route component. If you want the route structure to remain unchanged, it's recommended to use Higher-Order Components (HOC). First implement the wrapper logic in the HOC, then use the HOC to decorate the corresponding route component.

Example:

jsx
// src/hocs/withAuth.tsxconst withAuth = (Component)=> ()=> {  const {isLogin }= useAuth();  if (isLogin) {    return <router-view />;  }else {    return <router-link to="/login" />;  }}
jsx
// src/pages/user.tsxconst TheOldPage = ()=> {  // ...}export default withAuth(TheOldPage)

Conventional Routing

When using conventional routing, all(j|t)sx? files undersrc/pages are treated as routes. If you need to modify the default rules, you can use theconventionRoutes configuration.

In addition to configured routing, WinJS also supports conventional routing. Conventional routing, also known as file-based routing, means you don't need to write configuration manually. The file system becomes the routes, and route configuration is analyzed from directory and file structure and naming, ultimately generating the corresponding route structure.

If there is no routes configuration, WinJS will enter conventional routing mode, then analyze thesrc/pages directory to get the route configuration.

For example, the following file structure:

bash
.  └── pages    ├── index.tsx    └── users.tsx

Will generate the following route configuration:

js
[  { path:'/', name:'index', component:'@/pages/index' },  { path:'/users', name:'users', component:'@/pages/users' },]

Configuring Extended Properties

We can set extended properties for pages in two ways, allowingconventional routing to read custom page properties such asmeta.

  • Using thedefinePageMeta method (Recommended)
ts
definePageMeta(meta: PageMeta)=> metainterface PageMeta {  name?: string  alias?: string | string[]  [key: string]: unknown}
  • Using therouteProps property

Example:

vue
<script setup>  import { ref }from 'vue';  import { definePageMeta }from 'winjs';  // You can get the currently set meta field in the route interceptor (router.beforeEach)  // 1. Recommended: use definePageMeta()  definePageMeta({    meta: {      title:'pageMeta'    }  })  // 2. export const routeProps  export const routeProps = {    meta: { requireAuth:true }  }  const title = ref('Welcome to Your Vue.js App.');</script><template>  <div class="page page-hello">    <div class="page-content">      <!-- Example of static asset path -->      <img class="logo" src="@/assets/img/logo.png" alt="logo" />    </div>  </div></template>

Note

The above solution only works inconventional routing mode. That is, when it is detected that the WinJS configuration file.winrc does not contain theroutes property, this feature will be automatically enabled.

Dynamic Routes

By convention, directories or files with the$ prefix are dynamic routes. If no parameter name is specified after$, it represents* wildcard. For example, the following directory structure:

For example:

  • src/pages/users/$id.tsx will become/users/:id
  • src/pages/users/$id/settings.tsx will become/users/:id/settings

A complete example, with the following file structure:

+ pages/  + foo/    - $slug.tsx  + $bar/    - $.tsx  - index.tsx

Will generate the following route configuration:

javascript
[  { path:'/', name:'index', component:'@/pages/index.tsx' },  { path:'/foo/:slug', name:'fooSlug', component:'@/pages/foo/$slug.tsx' },  { path:'/:bar/*', name:'bar', component:'@/pages/$bar/$.tsx' }];

Global Layout

By convention,src/layouts/index.tsx is the global layout. It returns a Vue component and renders nested routes through<router-view />.

With the following directory structure:

bash
.└── src    ├── layouts   └── index.tsx    └── pages        ├── index.tsx        └── users.tsx

Will generate the following routes:

js
[  {    path:'/',    component:'@/layouts/index',    routes: [      { path:'', name:'index', component:'@/pages/index' },      { path:'users', name:'users', component:'@/pages/users' },    ],  },]

You can uselayout: false to fine-tune and disable theglobal layout display for a specific route. This option only takes effect at the first level:

ts
  routes: [  {    path:'/',    name:'index',    component:'./index',    // 🟢 Works    layout:false  },  {    path:'/users',    name:'users',    routes: [      // 🔴 Does not work, at this point the layout of this route is not the global layout, but `/users`      { layout:false }    ]  }]

A custom globallayout format looks like this:

tsx
export default function Layout() {  return <router-view />}

Different Global Layouts

You may need to output different global layouts for different routes. WinJS does not support such configuration, but you can still differentiatelocation.path insrc/layouts/index.tsx and render different layouts.

For example, if you want to output a simple layout for/login:

jsx
export default defineComponent(()=> {  setup()  {    const route = useRoute();    // Use `useAppData` to get more route information    // const { clientRoutes } = useAppData()    if (route.path=== '/login') {      return ()=> (        <div>          <SimpleLayout>            <router-view />          </SimpleLayout>        </div>      )    }    return ()=> (      <div>        <Header />        <router-view />        <Footer />      </div>    );  }});

Nested Routes

Although in WinJS, conventional routing does not support configuring different global layouts, we can create nested routes through the "directory convention" below, where both the current directory and subdirectories are child routes.

Assuming the directory structure of src/pages is as follows:

bash
.├── docs.vue├── hello   ├── child.vue   └── style.less├── hello.vue└── index.vue

Note

The folder and current-level route should have the same name.

bash
./src/pages├── ${name}   └── a.vue[tsx]└── ${name}.vue[tsx]

Among them, the example code inhello.vue is:

vue
<template>  <div class="page page-hello">    <h3>Hello parent</h3>    <router-view />  </div></template>

Then, the route configuration automatically generated by WinJS is as follows:

json
{  "hello": {    "path":"hello",    "id":"hello",    "name":"hello",    "parentId":"@@/global-layout"  },  "hello/child": {    "path":"child",    "id":"hello/child",    "name":"helloChild",    "parentId":"hello"  },  "index": {    "path":"/",    "id":"index",    "name":"index",    "parentId":"@@/global-layout"  },  "docs": {    "path":"docs",    "id":"docs",    "name":"docs",    "parentId":"@@/global-layout"  },  "@@/global-layout": {    "id":"@@/global-layout",    "path":"/",    "isLayout":true  }};

404 Route

By convention,src/pages/404.tsx is the 404 page and must return a Vue component. The default value ofname isNotFound.

For example, the following directory structure:

bash
.└── pages    ├── 404.tsx    ├── index.tsx    └── users.tsx

Will generate routes:

js
[  { path:'/', name:'index', component:'@/pages/index' },  { path:'/users', name:'users', component:'@/pages/users' },  { path:'/:pathMatch(.*)*', name:'NotFound', component:'@/pages/404' },]

In this way, if you access/foo, neither/ nor/users can match, it will fallback to the 404 route and be rendered throughsrc/pages/404.tsx.

404 only takes effect automatically with conventional routing. If using configured routing, you need to configure the 404 wildcard route yourself.

Tip

Different versions of vue-router, 4.x and 3.x will have differences in the generated 404-related code. For 4.x, refer to404 Route. For 3.x, refer to404 Route.

4.x corresponds to Vue3, and the generated code is as follows:

js
[  { path:'/', name:'index', component:'@/pages/index' },  { path:'/users', name:'users', component:'@/pages/users' },  { path:'/:pathMatch(.*)*', name:'NotFound', component:'@/pages/404' },]

2.x corresponds to Vue2, and the generated code is as follows:

js
[  { path:'/', name:'index', component:'@/pages/index' },  { path:'/users', name:'users', component:'@/pages/users' },  // Must be placed at the last position in the route table, otherwise any route access will enter 404  { path:'/*', name:'NotFound', component:'@/pages/404' },]

Page Navigation

For programmatic navigation or within components, please use theuseRouter API

html
<script lang="ts" setup>  import { useRouter, useRoute }from 'winjs';  const router = useRouter()  const route = useRoute()  const onHello = ()=> {    router.push({      name:'search',      query: {        ...route.query,      },    })  }  // These three forms are equivalent  router.push('/users/posva#bio');  router.push({ path:'/users/posva', hash:'#bio' });  router.push({ name:'users', params: { username:'posva' }, hash:'#bio' });  // Only change hash  router.push({ hash:'#bio' });  // Only change query  router.push({ query: { page:'2' } });  // Only change param  router.push({ params: { username:'jolyne' } });  // Navigate to the previous route  router.back();  // Navigate to the forward history record  router.go(1);  // Replace the record in the history stack  router.replace('/new');</script>

For more details,see here

router-link

See details

router-view

See details

RouterLink Component

See details

For example:

jsx
export default function Page () {  return (    <div>      <router-link to="/users">Users Page</router-link>    </div>  )}

Then clickingUsers Page will navigate to the/users address.

Note:

  • RouterLink is only used for internal navigation within a single-page application. For external URL navigation, please use thea tag

Runtime Configuration

You can control vue and vue-router related configuration through export in the conventionalsrc/app.tsx

router

Configure router configuration

ts
// src/app.tsxexport const router: RouterConfig = {  // @ts-ignore  scrollBehavior(to,from) {    console.log('scrollBehavior', to, from);  },};

onMounted({app, router})

Vue app mount success callback. Here you can get the app instance and router instance, and can register global components, route interceptors, etc.

ts
export function onMounted({app,router }: any) {  console.log('onMounted', app, router);  app.provide('win-hello', {    h:'hello',    w:'word',  });}

rootContainer(container)

Modify the root component when handing over to vue-router for rendering.

For example, to wrap an outer parent component

ts
import { h }from 'vue'export function rootContainer(container) {  return h(ThemeProvider,null, container);}

[8]ページ先頭

©2009-2025 Movatter.jp