Vue3的學習---5

一生万物万物归一發表於2024-08-15

5.路由

5.1 Vue路由

5.1.1 Vue路由基礎

Vue路由例項:

<body>
    <div id="app">
        <p>
            <!-- 這裡使用router-link標籤來實現路由跳轉 -->
            <router-link to="/home">首頁</router-link><br>
            <router-link to="/about">關於</router-link>
        </p>
        <!-- 路由出口(這裡顯示路由的內容) -->
        <router-view></router-view>
    </div>

    <script src="../js/vue3.js"></script>
    <script src="../js/vue-router.js"></script>
    <script>
        // 1、定義路由元件
        const Home = {
            template: '<div>首頁</div>'
        }
        const About = {
            template: '<div>關於</div>'
        }

        // 2、定義路由規則(每一個路徑對映一個路由元件)
        const routes = [
            {
                path: '/home',
                component: Home
            }, {
                path: '/about',
                component: About
            }
        ]

        // 3、建立Vue路由例項
        const router = VueRouter.createRouter({
            // 配置路由模式
            history: VueRouter.createWebHashHistory(),
            // 配置路由規則(如果路由規則名為routes,那麼可以簡寫為:routes)
            routes: routes
        })

        // 4、將路由物件掛載到Vue例項上
        Vue.createApp({

        }).use(router).mount('#app')
    </script>
</body>

5.1.2 巢狀路由

<body>
    <div id="app">
        <div>
            <p>
                <router-link to="/home">首頁</router-link><br>
                <router-link to="/about">關於</router-link>
            </p>
            <router-view></router-view>
        </div>
    </div>

    <script src="../js/vue3.js"></script>
    <script src="../js/vue-router.js"></script>
    <script>
        const Home = {
            template: `<div>
                        <p>首頁</p>
                        <router-link to="/home/login">登入</router-link><br>
                        <router-link to="/home/register">註冊</router-link>
                        <router-view></router-view>
                    </div>`
        }
        const About = {
            template: '<div>關於</div>'
        }
        const Login = {
            template: '<div>登入</div>'
        }
        const Register = {
            template: '<div>註冊</div>'
        }

        const routes = [
            {
                path: '/',
                redirect: '/home'
            }, {
                path: '/home',
                component: Home,
                children: [
                    {
                        path: '/home',
                        redirect: '/home/login'
                    }, {
                        path: '/home/login',
                        component: Login
                    }, {
                        path : '/home/register',
                        component: Register
                    }
                ]
            }, {
                path: '/about',
                component: About
            }
        ]

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

        Vue.createApp({

        }).use(router).mount('#app')
    </script>
</body>

5.1.3 路由傳參

5.1.3.1 params形式傳參

params 形式傳參是 Vue Router 中一種透過 URL 傳遞引數的方式。具體來說,它允許你在路由路徑中定義引數,並在導航時透過這些引數傳遞資料。這種方式通常用於動態路由,其中路由路徑的一部分是可變的。

<body>
    <div id="app">
        <p>
            <router-link to="/home">首頁</router-link><br>
            <router-link :to="{ name: 'About', params: { id: userID, name: userName } }">關於</router-link>
        </p>
        <router-view></router-view>
    </div>

    <script src="../js/vue3.js"></script>
    <script src="../js/vue-router.js"></script>
    <script>
        const Home = {
            template: '<div>首頁</div>'
        }
        const About = {
            template: `<div>
                        關於<br>
                        引數1:{{ $route.params.id }}<br>
                        引數2:{{ $route.params.name }}
                    </div>`,
            props: ['id', 'name']
        }

        const routes = [
            {
                path: '/',
                redirect: Home
            }, {
                path: '/home',
                name: 'Home',
                component: Home,
                props: true
            }, {
                path: '/about/:id/:name',  // 明確定義引數 id 和 name
                name: 'About',
                component: About,
                props: true
            }
        ]

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

        Vue.createApp({
            data() {
                return {
                    userID: 123,
                    userName: '張三'
                }
            }
        }).use(router).mount('#app')
    </script>
</body>
5.1.3.2 query形式傳參

query 形式傳參是 Vue Router 中另一種透過 URL 傳遞引數的方式。與 params 形式不同,query 引數是透過 URL 的查詢字串(query string)傳遞的,通常顯示在 URL 的問號後面,例如 http://example.com/about?id=123&name=張三

<body>
    <div id="app">
        <p>
            <router-link to="/home">首頁</router-link><br>
            <router-link :to="{ path: '/about', query: {id: userID, name: userName} }">關於</router-link>
        </p>
        <router-view></router-view>
    </div>

    <script src="../js/vue3.js"></script>
    <script src="../js/vue-router.js"></script>
    <script>
        const Home = {
            template: `<div>首頁</div>`
        }
        const About = {
            template: `<div>
                        關於<br>
                        引數1:{{ $route.query.id }}<br>
                        引數2:{{ $route.query.name }}
                    </div>`
        }

        const routes = [
            {
                path: '/',
                redirect: '/home',
            },
            {
                path: '/home',
                component: Home
            },
            {
                path: '/about',
                component: About
            }
        ]

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

        Vue.createApp({
            data() {
                return {
                    userName: '張三',
                    userID: 123
                }
            }
        }).use(router).mount('#app')
    </script>
</body>
5.1.3.3 params方式與query的區別

paramsquery 是 Vue Router 中兩種不同的傳參方式,它們在用法和表現上有一些顯著的區別:

  1. URL 結構
  • params 傳參
    • 引數直接嵌入在路徑中,例如 /about/123/張三
    • URL 結構為 /about/:id/:name
    • 引數是路徑的一部分,不可省略。
  • query 傳參
    • 引數透過查詢字串傳遞,例如 /about?id=123&name=張三
    • URL 結構為 /about,引數附加在 URL 後面,用問號 ? 分隔。
    • 引數是可選的,可以省略。
  1. 定義方式
  • params 傳參
    • 在路由配置中定義路徑引數,例如 path: '/about/:id/:name'
    • 在導航時透過 params 屬性傳遞引數,例如 :to="{ name: 'About', params: { id: userID, name: userName } }"
  • query 傳參
    • 在路由配置中不需要定義引數。
    • 在導航時透過 query 屬性傳遞引數,例如 :to="{ name: 'About', query: { id: userID, name: userName } }"
  1. 訪問方式
  • params 傳參
    • 在元件中透過 $route.params 訪問引數,例如 {{ $route.params.id }}
  • query 傳參
    • 在元件中透過 $route.query 訪問引數,例如 {{ $route.query.id }}
  1. 引數的可見性和可變性
  • params 傳參
    • 引數直接顯示在 URL 中,使用者可以直接看到和修改。
    • 引數是路徑的一部分,不可省略,且必須與路徑定義匹配。
  • query 傳參
    • 引數顯示在 URL 的查詢字串中,使用者也可以看到和修改。
    • 引數是可選的,可以省略,且不需要與路徑定義匹配。
  1. 適用場景
  • params 傳參
    • 適用於需要將引數作為路徑一部分的場景,例如動態路由、資源標識等。
    • 引數是路徑的一部分,不可省略,適用於必須傳遞引數的場景。
  • query 傳參
    • 適用於可選引數、過濾條件、排序等場景。
    • 引數是可選的,可以省略,適用於引數不是必須的場景。
5.1.3.4 restful風格傳參

如果我們即想使用params方式傳參,又不想在重新整理是丟失引數,那麼我們可以使用restful風格傳參。

<body>
    <div id="app">
        <p>
            <router-link to="/home">首頁</router-link><br>
            <router-link to="/about/123/'張三'">關於</router-link>
        </p>
        <router-view></router-view>
    </div>

    <script src="../js/vue3.js"></script>
    <script src="../js/vue-router.js"></script>
    <script>
        const Home = {
            template: '<div>首頁</div>'
        }
        const About = {
            template: `<div>
                        關於<br>
                        ID: {{ $route.params.id }}<br>
                        姓名: {{ $route.params.name }}
                    </div>`
        }

        const routes = [
            {
                path: '/',
                redirect: '/home'
            }, {
                path: '/home',
                name: Home,
                component: Home
            }, {
                path: '/about/:id/:name',
                name: About,
                component: About
            }
        ]

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

        Vue.createApp({

        }).use(router).mount('#app')
    </script>
</body>

5.2 程式設計式路由

程式設計式路由是指在Web應用中透過編寫程式碼來實現頁面之間的導航,而不是透過使用者點選連結(如<a>標籤)來實現。這種方式允許開發者根據應用的邏輯和狀態來控制導航行為,從而實現更復雜和動態的使用者體驗。

程式設計式路由的主要用途:

  1. 條件導航:根據應用的狀態或使用者的操作來決定導航到哪個頁面。
  2. 動態引數傳遞:在導航時傳遞動態引數,如使用者ID、查詢引數等。
  3. 前進和後退:實現頁面的前進和後退功能,類似於瀏覽器的前進和後退按鈕。
  4. 重定向:根據某些條件自動重定向使用者到不同的頁面。

5.2.1 利用JS實現路由轉跳

<body>
    <div id="app">
        <button @click="toHome">首頁</button>
        <button @click="toAbout">關於</button>
        <button @click="toLogin">登入</button><br>
        <button @click="toForward">前進</button>
        <button @click="toBack">後退</button>
        <router-view></router-view>
    </div>

    <script src="../js/vue3.js"></script>
    <script src="../js/vue-router.js"></script>
    <script>
        const Home = {
            template: '<div>首頁</div>'
        }
        const About = {
            template: `<div>
                        關於<br>
                        ID: {{ $route.query.id }}<br>
                        name: {{ $route.query.name }}
                    </div>`
        }
        const Login = {
            template: '<div>登入</div>'
        }

        const routes = [
            {
                path:'/',
                redirect:'/home'
            }, {
                path:'/home',
                component: Home
            }, {
                path:'/about',
                component: About
            }, {
                path:'/login',
                component: Login
            }
        ]

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

        Vue.createApp({
            data() {
                return {
                    userID: 123,
                    userName: '張三'
                }
            },
            methods: {
                toHome() {
                    this.$router.push('/home')
                },
                toAbout() {
                    this.$router.push({path:'/about', query: {id: this.userID, name: this.userName}})
                },
                toLogin() {
                    this.$router.push('/login')
                },
                toForward() {
                    // this.$router.forward()
                    this.$router.go(1)
                },
                toBack() {
                    // this.$router.back()
                    this.$router.go(-1)
                }
            }
        }).use(router).mount('#app')
    </script>
</body>

5.2.2 透過watch實現路由監聽

透過watch屬性設定監聽$route變化,達到監聽路由跳轉的目的。

<body>
    <div id="app">
        <router-link to="/home">首頁</router-link><br>
        <router-link to="/about">關於</router-link>
        <router-view></router-view>
    </div>

    <script src="../js/vue3.js"></script>
    <script src="../js/vue-router.js"></script>
    <script>
        const Home = { template: '<div>首頁</div>' }
        const About = { template: '<div>關於</div>' }

        const routes = [
            { path: '/', redirect: '/home' },
            { path: '/home', component: Home },
            { path: '/about', component: About }
        ]

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

        Vue.createApp({
            // 路由監聽
            watch: {
                $route(newRoute, oldRoute) {
                    console.log(newRoute, oldRoute)
                }
            }
        }).use(router).mount('#app')
    </script>
</body>

5.2.3 導航守衛

路由守衛(Route Guards)是用於控制路由訪問許可權的一種機制,它們可以在導航到某個路由之前、之後或過程中執行一些邏輯,比如驗證使用者許可權、載入資料等。

以下是一些常見的路由守衛型別:

  1. beforeEach: 全域性前置守衛。
  2. beforeResolve: 全域性解析守衛。
  3. afterEach: 全域性後置鉤子。
  4. beforeEnter: 路由獨享的守衛。
  5. beforeRouteEnter: 元件內的守衛。
  6. beforeRouteUpdate: 元件內的守衛。
  7. beforeRouteLeave: 元件內的守衛。
<body>
    <div id="app">
        <p>
            <!-- 這裡使用router-link標籤來實現路由跳轉 -->
            <router-link to="/home">首頁</router-link><br>
            <router-link to="/about">關於</router-link><br>
            <router-link to="/login">登入</router-link>
        </p>
        <!-- 路由出口(這裡顯示路由的內容) -->
        <router-view></router-view>
    </div>

    <script src="../js/vue3.js"></script>
    <script src="../js/vue-router.js"></script>
    <script>
        const Home = {
            template: '<div>首頁</div>'
        }
        const About = {
            template: '<div>關於</div>'
        }
        const Login = {
            template: '<div>登入</div>'
        }

        const routes = [
            {
                path: '/',
                redirect: '/login' 
            }, {
                path: '/home',
                component: Home
            }, {
                path: '/about',
                component: About
            }, {
                path: '/login',
                component: Login
            }
        ]

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

        // 路由守衛
        router.beforeEach((to, from, next)=>{
            // 建立守衛規則
            const nextRoute = ['/home', '/about']
            // 使用isLogin來模擬是否登入
            let isLogin = true
            // 判斷topath是否需要驗證,如果當前路由是登入頁面,並且未登入,則跳轉到登入頁面
            // indexOf()是用來判斷陣列中是否存在某個元素的,如果存在,則返回元素的索引值,否則返回-1
            if(nextRoute.indexOf(to.path) >= 0) {
                if(!isLogin) {
                    router.path('/login')
                }
            }
            // 驗證透過後繼續往下執行
            next()
        })

        Vue.createApp({}).use(router).mount('#app')
    </script>
</body>

相關文章