06 . Vue路由簡介,原理,實現及巢狀路由,動態路由,程式設計式導航

youmen發表於2020-11-19

路由概念

路由的本質就是一種對應關係,比如說我們在url地址中輸入我們要訪問的url地址之後,瀏覽器要去請求這個url地址對應的資源。
那麼url地址和真實的資源之間就有一種對應的關係,就是路由。

路由分為前端路由和後端路由

/*
			1).後端路由是由伺服器端進行實現,並完成資源的分發.
						概念: 根據不同的URL請求,返回不同的內容
						本質: URL請求地址與伺服器資源之間的對應關係
						
			2).前端路由是依靠hash值(錨連結)的變化進行實現 
						概念: 根據不同的事件顯示不同的頁面內容,即事件與事件處理函式之間的對應關係.
						前端路由主要做監聽事件並分發執行事件處理函式
						
						
			後端路由效能相對前端路由來說較低
*/

SPA

Single Page Application

/*
		後端渲染(存在效能問題)
		Ajax前端渲染(前端渲染提高效能,但是不支援瀏覽器的前進後退操作)
		SPA(Single Page Applicationn) 單頁面應用程式: 
				整個網站只有一個頁面,內容的變化通過Ajax區域性更新實現,同時支援瀏覽器位址列的前進和後退操作.
			SPA實現原理之一:  基於URL地址的hash(hash的變化會導致瀏覽器記錄訪問歷史的變化,但是hash的變化不會觸發新的URL請求)
			在實現SPA的過程中,最核心技術點就是前端路由
*/
前端路由

前端路由是基於hash值的變化進行實現的(比如點選頁面中的選單或者按鈕改變URL的hash值,根據hash值的變化來控制元件的切換)
核心實現依靠一個不同的使用者事件,即監聽hash值變化的事件,顯示不同的頁面內容.

本質: 使用者事件與事件處理函式之間的對應關係

實現簡易前端路由

基於URL的hash實現(點選選單的時候改變URL的hash,根據hash的變化控制元件的切換)

模擬路由
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
    <title>Document</title>
    <!-- 匯入 vue 檔案 -->
    <script src="./js/vue_2.5.22.js"></script>
</head>
<body>
<!-- 被 vue 例項控制的 div 區域 -->
<div id="app">
    <!-- 切換元件的超連結 -->
    <a href="#/zhuye">主頁</a>
    <a href="#/keji">科技</a>
    <a href="#/caijing">財經</a>
    <a href="#/yule">娛樂</a>

    <!-- 根據 :is 屬性指定的元件名稱,把對應的元件渲染到 component 標籤所在的位置 -->
    <!-- 可以把 component 標籤當做是【元件的佔位符】 -->
    <component :is="comName"></component>
</div>

<script>
    // #region 定義需要被切換的 4 個元件
    // 主頁元件
    const zhuye = {
        template: '<h1>主頁資訊</h1>'
    }

    // 科技元件
    const keji = {
        template: '<h1>科技資訊</h1>'
    }

    // 財經元件
    const caijing = {
        template: '<h1>財經資訊</h1>'
    }

    // 娛樂元件
    const yule = {
        template: '<h1>娛樂資訊</h1>'
    }
    // #endregion

    // #region vue 例項物件
    const vm = new Vue({
        el: '#app',
        data: {
            comName: 'zhuye'
        },
        // 註冊私有元件
        components: {
            zhuye,
            keji,
            caijing,
            yule
        }
    })
    // #endregion

    // 監聽 window 的 onhashchange 事件,根據獲取到的最新的 hash 值,切換要顯示的元件的名稱
    window.onhashchange = function () {
        // 通過 location.hash 獲取到最新的 hash 值
        console.log(location.hash);
        switch (location.hash.slice(1)) {
            case '/zhuye':
                vm.comName = 'zhuye'
                break
            case '/keji':
                vm.comName = 'keji'
                break
            case '/caijing':
                vm.comName = 'caijing'
                break
            case '/yule':
                vm.comName = 'yule'
                break
        }
    }
</script>
</body>
</html>

核心思路

在頁面中有一個vue例項物件,vue例項物件中有四個元件,分別是tab欄切換需要顯示的元件內容
在頁面中有四個超連結,如下:

<a href="#/zhuye">主頁</a> 
<a href="#/keji">科技</a> 
<a href="#/caijing">財經</a>
<a href="#/yule">娛樂</a>

當我們點選這些超連結的時候,就會改變url地址中的hash值,當hash值被改變時,就會觸發onhashchange事件
在觸發onhashchange事件的時候,我們根據hash值來讓不同的元件進行顯示:

window.onhashchange = function() {
    // 通過 location.hash 獲取到最新的 hash 值
    console.log(location.hash);
    switch(location.hash.slice(1)){
        case '/zhuye':
        //通過更改資料comName來指定顯示的元件
        //因為 <component :is="comName"></component> ,元件已經繫結了comName
        vm.comName = 'zhuye'
        break
        case '/keji':
        vm.comName = 'keji'
        break
        case '/caijing':
        vm.comName = 'caijing'
        break
        case '/yule':
        vm.comName = 'yule'
        break
    }
}

Vue Router簡介

它是一個Vue.js官方提供的路由管理器。是一個功能更加強大的前端路由器,推薦使用。
Vue Router和Vue.js非常契合,可以一起方便的實現SPA(single page web application,單頁應用程式)應用程式的開發。
Vue Router依賴於Vue,所以需要先引入Vue,再引入Vue Router

Vue Router特性
/*
		支援H5歷史模式或者hash模式
    支援巢狀路由
    支援路由引數
    支援程式設計式路由
    支援命名路由
    支援路由導航守衛
    支援路由過渡動畫特效
    支援路由懶載入
    支援路由滾動行為
*/

Vue Router的使用

步驟
/*
		1. 引入相關的庫檔案
		2. 新增路由連結
		3. 新增路由填充位
		4. 定義路由元件
		5. 配置路由規則並建立路由例項
		6. 把路由掛載到Vue根例項中
		
		補充:
    	路由重定向:可以通過路由重定向為頁面設定預設展示的元件
    	在路由規則中新增一條路由規則即可,如下:
    var myRouter = new VueRouter({
    //routes是路由規則陣列
    routes: [
        //path設定為/表示頁面最初始的地址 / ,redirect表示要被重定向的新地址,設定為一個路由即可
        { path:"/",redirect:"/user"},
        { path: "/user", component: User },
        { path: "/login", component: Login }
    ]
})
*/

A.匯入js檔案

<script src="lib/vue_2.5.22.js"></script>
<script src="lib/vue-router_3.0.2.js"></script>

B.新增路由連結:<router-link>是路由中提供的標籤,預設會被渲染為a標籤,to屬性預設被渲染為href屬性, to屬性的值會被渲染為#開頭的hash地址

<router-link to="/user">User</router-link>
<router-link to="/login">Login</router-link>

C.新增路由填充位(路由佔位符)

<!-- 路由填充位(也叫路由佔位符) -->
<!-- 將來通過路由規則匹配到的元件, 將會被渲染到router-view所在的位置 -->
<router-view></router-view>

D.定義路由元件

var User = { template:"<div>This is User</div>" }
var Login = { template:"<div>This is Login</div>" }

E.配置路由規則並建立路由例項

var myRouter = new VueRouter({
    //routes是路由規則陣列
    routes:[
        //每一個路由規則都是一個物件,物件中至少包含path和component兩個屬性
        //path表示  路由匹配的hash地址,component表示路由規則對應要展示的元件物件
        {path:"/user",component:User},
        {path:"/login",component:Login}
    ]
})

F.將路由掛載到Vue例項中

new Vue({
    el:"#app",
    //通過router屬性掛載路由物件
    router:myRouter
})

Example

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/vue-router_3.0.2.js"></script>
</head>
<body>

<body>
<!-- 被 vm 例項所控制的區域 -->
<div id="app">
    <router-link to="/user">User</router-link>
    <router-link to="/register">Register</router-link>

    <!-- 路由佔位符 -->
    <router-view></router-view>
</div>

<script>
    const User = {
        template: '<h1>User 元件</h1>'
    }

    const Register = {
        template: '<h1>Register 元件</h1>'
    }

    // 建立路由例項物件
    const router = new VueRouter({
        // 所有的路由規則
        routes: [
            {path: '/user', component: User},
            {path: '/register', component: Register}
        ]
    })

    // 建立 vm 例項物件
    const vm = new Vue({
        // 指定控制的區域
        el: '#app',
        data: {},
        // 掛載路由例項物件
        // router: router
        router
    })
</script>
</body>
</html>
路由重定向

路由重定向指的是: 使用者在訪問A的時候,強制使用者跳轉到地址c,從而展示特定的元件頁面;

通過路由規則的redirect屬性,指定一個新的路由地址,可以很方便的設定路由重定向.

    // 建立路由例項物件
    var router = new VueRouter({
        // 所有的路由規則

        routes: [
				// 其中,path表示需要被重定向的原地址, redirect表示將要被重定向到的新地址
            {path: '/', redirect: '/User'},
						{path: '/user', component: '/User'},
            {path: '/register', component: Register}
        ]
    })

巢狀路由

巢狀路由功能
/*
		點選父級路由連結顯示模板內容
		模板內容中又有子級路由連結
		點選子級路由連結顯示子級模板內容
*/
巢狀路由的概念

當我們進行路由的時候顯示的元件中還有新的子級路由連結以及內容。

巢狀路由最關鍵的程式碼在於理解子級路由的概念:
比如我們有一個/login的路由
那麼/login下面還可以新增子級路由,如:
/login/account
/login/phone

參考程式碼如下

var User = { template: "<div>This is User</div>" }
//Login元件中的模板程式碼裡面包含了子級路由連結以及子級路由的佔位符
    var Login = { template: `<div>
        <h1>This is Login</h1>
        <hr>
        <router-link to="/login/account">賬號密碼登入</router-link>
        <router-link to="/login/phone">掃碼登入</router-link>
        <!-- 子路由元件將會在router-view中顯示 -->
        <router-view></router-view>
        </div>` }

    //定義兩個子級路由元件
    var account = { template:"<div>賬號:<input><br>密碼:<input></div>"};
    var phone = { template:"<h1>掃我二維碼</h1>"};
    var myRouter = new VueRouter({
        //routes是路由規則陣列
        routes: [
            { path:"/",redirect:"/user"},
            { path: "/user", component: User },
            { 
                path: "/login", 
                component: Login,
                //通過children屬性為/login新增子路由規則
                children:[
                    { path: "/login/account", component: account },
                    { path: "/login/phone", component: phone },
                ]
            }
        ]
    })

    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {},
        router:myRouter
    });
巢狀路由用法

父路由元件模板

/*
		父級路由連結
		父元件路由填充位
*/

<p>
		<router-link to="/user">User</router-link>
		<router-link to="/register">Register</router-link>
</p>

<div>
		<!-- 控制元件的顯示位置 -->
		<router-view></router-view>
</div>

子級路由模板

/*
		子級路由連結
		子級路由填充位
*/
const Register = {
	template: `<div>
    <h1>Register 元件</h1>
    <hr/>
    <router-link to="/register/tab1">Tab1</router-link>
		<router-link to="/register/tab2">Tab2</router-link>
    
    <!-- 子路由填充位置 -->
    <router-view/>
</div>
}

父路由通過children屬性配置子級路由

const router = new VueRouteer({
		routes: [
				{ path: '/user',component: User},
				{
						path: '/register',
						component: Register,
						// 通過children屬性,為/register新增子路由規則
						children: [
                {path: '/',redirect: '/user'},
                {path: '/user', component: User},
                {path: '/register', component: Register}
				]
			}
    ]
})

Example

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/vue-router_3.0.2.js"></script>
</head>
<body>

<body>
<!-- 被 vm 例項所控制的區域 -->
<div id="app">
    <router-link to="/user">User</router-link>
    <router-link to="/register">Register</router-link>

    <!-- 路由佔位符 -->
    <router-view></router-view>
</div>

<script>
    const User = {
        template: '<h1>User 元件</h1>'
    }

    const Register = {
        template: `
            <div>
            <h1>Register 元件</h1>
            <hr/>
            <router-link to="/register/tab1">tab1</router-link>
            <router-link to="/register/tab2">tab2</router-link>

            <router-view/>
            </div>`
    }

    const Tab1 = {
        template: '<h3>tab1 子元件</h3>'
    }

    const Tab2 = {
        template: '<h3>tab2 子元件</h3>'
    }

    // 建立路由例項物件
    const router = new VueRouter({
        // 所有的路由規則
        routes: [
            {path: '/', redirect: '/user'},
            {path: '/user', component: User},

            // children 陣列表示子路由規則
            {
                path: '/register', component: Register, children: [
                    {path: '/register/tab1', component: Tab1},
                    {path: '/register/tab2', component: Tab2}
                ]
            }
        ]
    })

    // 建立 vm 例項物件
    const vm = new Vue({
        // 指定控制的區域
        el: '#app',
        data: {},
        // 掛載路由例項物件
        // router: router
        router
    })
</script>
</body>
</html>

動態路由

動態路由匹配
var User = { template:"<div>使用者:{{$route.params.id}}</div>"}

var myRouter = new VueRouter({
    //routes是路由規則陣列
    routes: [
        //通過/:引數名  的形式傳遞引數 
        { path: "/user/:id", component: User },
    ]
})

注意

// 如果使用$route.params.id來獲取路徑傳參的資料不夠靈活。
     // 1.我們可以通過props來接收引數
var User = { 
    props:["id"],
    template:"<div>使用者:{{id}}</div>"
    }

var myRouter = new VueRouter({
    //routes是路由規則陣列
    routes: [
        //通過/:引數名  的形式傳遞引數 
        //如果props設定為true,route.params將會被設定為元件屬性
        { path: "/user/:id", component: User,props:true },
        

    ]

})

     // 2.還有一種情況,我們可以將props設定為物件,那麼就直接將物件的資料傳遞給
元件進行使用
var User = { 
    props:["username","pwd"],
    template:"<div>使用者:{{username}}---{{pwd}}</div>"
    }

var myRouter = new VueRouter({
    //routes是路由規則陣列
    routes: [
        //通過/:引數名  的形式傳遞引數 
        //如果props設定為物件,則傳遞的是物件中的資料給元件
        { path: "/user/:id", component: User,props:{username:"jack",pwd:123} },
        

    ]

})

     // 3.如果想要獲取傳遞的引數值還想要獲取傳遞的物件資料,那麼props應該設定為
函式形式。
var User = { 
    props:["username","pwd","id"],
    template:"<div>使用者:{{id}} -> {{username}}---{{pwd}}</div>"
    }

var myRouter = new VueRouter({
    //routes是路由規則陣列
    routes: [
        //通過/:引數名  的形式傳遞引數 
        //如果props設定為函式,則通過函式的第一個引數獲取路由物件
        //並可以通過路由物件的params屬性獲取傳遞的引數
        //
        { path: "/user/:id", component: User,props:(route)=>{
            return {username:"jack",pwd:123,id:route.params.id}
            } 
        },
    ]
})

Example

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/vue-router_3.0.2.js"></script>
</head>
<body>

<body>
<!-- 被 vm 例項所控制的區域 -->
<div id="app">
    <router-link to="/user/1">User1</router-link>
    <router-link to="/user/2">User2</router-link>
    <router-link to="/user/3">User3</router-link>
    <router-link to="/register">Register</router-link>

    <!-- 路由佔位符 -->
    <router-view></router-view>
</div>

<script>
    const User = {
        template: '<h1>User 元件 -- 使用者id為: {{ $route.params.id }}</h1>'
    }

    const Register = {
        template: `
            <div>
            <h1>Register 元件</h1>
            <hr/>
            <router-link to="/register/tab1">tab1</router-link>
            <router-link to="/register/tab2">tab2</router-link>

            <router-view/>
            </div>`
    }

    const Tab1 = {
        template: '<h3>tab1 子元件</h3>'
    }

    const Tab2 = {
        template: '<h3>tab2 子元件</h3>'
    }

    // 建立路由例項物件
    const router = new VueRouter({
        // 所有的路由規則
        routes: [
            {path: '/', redirect: '/user'},
            {path: '/user/:id', component: User},

            // children 陣列表示子路由規則
            {
                path: '/register', component: Register, children: [
                    {path: '/register/tab1', component: Tab1},
                    {path: '/register/tab2', component: Tab2}
                ]
            }
        ]
    })

    // 建立 vm 例項物件
    const vm = new Vue({
        // 指定控制的區域
        el: '#app',
        data: {},
        // 掛載路由例項物件
        // router: router
        router
    })
</script>
</body>
</html>
路由元件傳遞引數
/*
		$route與對應路由形式高度耦合,不夠靈活,所以可以使用props將元件和路由解耦
*/

1. props的值為布林型別

const router = new VueRouter({
		routes: [
			// 如果props被設定為true, route.params將會被設定為元件屬性
			[ path: '/user/:id',component: User,props:true ]
		]

		const User = [
			props: ['id'], // 使用props接受路由引數
			template: '<div>使用者ID: {{ id }}</div>'  // 使用路由引數
		]
})

Example1

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/vue-router_3.0.2.js"></script>
</head>
<body>

<body>
<!-- 被 vm 例項所控制的區域 -->
<div id="app">
    <router-link to="/user/1">User1</router-link>
    <router-link to="/user/2">User2</router-link>
    <router-link to="/user/3">User3</router-link>
    <router-link to="/register">Register</router-link>

    <!-- 路由佔位符 -->
    <router-view></router-view>
</div>

<script>
    const User = {
        props: ['id'],
        template: '<h1>User 元件 -- 使用者id為: {{ id }}</h1>'
    }

    const Register = {
        template: `
            <div>
            <h1>Register 元件</h1>
            <hr/>
            <router-link to="/register/tab1">tab1</router-link>
            <router-link to="/register/tab2">tab2</router-link>
            <router-view/>
            </div>`
    }

    const Tab1 = {
        template: '<h3>tab1 子元件</h3>'
    }

    const Tab2 = {
        template: '<h3>tab2 子元件</h3>'
    }

    // 建立路由例項物件
    const router = new VueRouter({
        // 所有的路由規則
        routes: [
            {path: '/', redirect: '/user'},
            {path: '/user/:id', component: User, props: true},

            // children 陣列表示子路由規則
            {
                path: '/register', component: Register, children: [
                    {path: '/register/tab1', component: Tab1},
                    {path: '/register/tab2', component: Tab2}
                ]
            }
        ]
    })

    // 建立 vm 例項物件
    const vm = new Vue({
        // 指定控制的區域
        el: '#app',
        data: {},
        // 掛載路由例項物件
        // router: router
        router
    })
</script>
</body>
</html>

props的值為物件型別

const router = new VueRouter({
		routes: [
			// 如果props被設定為true, route.params將會被設定為元件屬性
			[ path: '/user/:id',component: User,props: {uname:'lisi',age:12} ]
		]

		const User = [
			props: ['uname','age'], // 使用props接受路由引數
			template: '<div>使用者ID: {{ uname + '----' + age }}</div>'  // 使用路由引數
		]
})

props的值為函式型別

const router = new VueRouter({
		routes: [
			// 如果props是一個函式,則這個函式接受route物件為自己的形參
			[ path: '/user/:id',component: User,props:  route => ({uname: 'zs',age: 20, id: route.params.id}) 
			]
})

		const User = [
			props: ['uname','age','id'], // 使用props接受路由引數
			template: '<h1>User 元件 -- 使用者id為: {{ id }} -- 姓名為:{{ uname }} -- 年齡為: {{ age }}</h1>' // 使用路由引數
		]
})

命名路由

命名路由:給路由取別名

const router = new VueRouter({
		routes: [
				{
						path: '/user/:id',
						name: 'user',
						component: User
				}
		]
})

<router-link :to="{ name: 'user',params: {id:123}}">User</router-link>
router.push({name:'user',params: {id:123}})

Example

var myRouter = new VueRouter({
    //routes是路由規則陣列
    routes: [
        //通過name屬性為路由新增一個別名
        { path: "/user/:id", component: User, name:"user"},
    ]
})

// 新增了別名之後,可以使用別名進行跳轉
<router-link to="/user">User</router-link>
<router-link :to="{ name:'user' , params: {id:123} }">User</router-link>

// 還可以程式設計式導航
myRouter.push( { name:'user' , params: {id:123} } )

Example1

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 例項所控制的區域 -->
<div id="app">
    <router-link to="/user/1">User1</router-link>
    <router-link to="/user/2">User2</router-link>
    <router-link :to="{ name: 'user', params: {id: 3} }">User3</router-link>
    <router-link to="/register">Register</router-link>

    <!-- 路由佔位符 -->
    <router-view></router-view>
</div>

<script>
    const User = {
        props: ['id', 'uname', 'age'],
        template: '<h1>User 元件 -- 使用者id為: {{id}} -- 姓名為:{{uname}} -- 年齡為:{{age}}</h1>'
    }

    const Register = {
        template: '<h1>Register 元件</h1>'
    }

    // 建立路由例項物件
    const router = new VueRouter({
        // 所有的路由規則
        routes: [
            {path: '/', redirect: '/user'},
            {
                // 命名路由
                name: 'user',
                path: '/user/:id',
                component: User,
                props: route => ({uname: 'zs', age: 20, id: route.params.id})
            },
            {path: '/register', component: Register}
        ]
    })

    // 建立 vm 例項物件
    const vm = new Vue({
        // 指定控制的區域
        el: '#app',
        data: {},
        // 掛載路由例項物件
        // router: router
        router
    })
</script>
</body>
</html>

程式設計式導航

頁面導航的兩種方式

A.宣告式導航:通過點選連結的方式實現的導航
B.程式設計式導航:呼叫js的api方法實現導航

Vue-Router常見導航方式
/*
		Vue-Router中常見的導航方式:
      this.$router.push("hash地址");
      this.$router.push("/login");
      this.$router.push({ name:'user' , params: {id:123} });
      this.$router.push({ path:"/login" });
      this.$router.push({ path:"/login",query:{username:"jack"} });

      this.$router.go( n );//n為數字,參考history.go
      this.$router.go( -1 );
*/

Example

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 例項所控制的區域 -->
<div id="app">
    <router-link to="/user/1">User1</router-link>
    <router-link to="/user/2">User2</router-link>
    <router-link :to="{ name: 'user', params: {id: 3} }">User3</router-link>
    <router-link to="/register">Register</router-link>

    <!-- 路由佔位符 -->
    <router-view></router-view>
</div>

<script>
    const User = {
        props: ['id', 'uname', 'age'],
        template: `<div>
            <h1>User 元件  -- 使用者id為: {{ id }}  -- 姓名為: {{ uname }} -- 年齡為: {{ age }}</h1>
            <button @click="goRegister">跳轉到註冊頁面</button>
         </div>`,
        methods: {
            goRegister() {
                this.$router.push('/register')
            }
        },
    }

    const Register = {
        template: `<div>
            <h1>Register 元件</h1>
            <button @click="goBack">後退</button>
        </div>`,
        methods: {
            goBack() {
                this.$router.go(-1)
            }
        }
    }

    // 建立路由例項物件
    const router = new VueRouter({
        // 所有的路由規則
        routes: [
            {path: '/', redirect: '/user'},
            {
                // 命名路由
                name: 'user',
                path: '/user/:id',
                component: User,
                props: route => ({uname: 'zs', age: 20, id: route.params.id})
            },
            {path: '/register', component: Register}
        ]
    })

    // 建立 vm 例項物件
    const vm = new Vue({
        // 指定控制的區域
        el: '#app',
        data: {},
        // 掛載路由例項物件
        // router: router
        router
    })
</script>
</body>
</html>
Router.push()方法引數規則
/*
		字串(路徑名稱)
			router.push('/home')
			
		物件
			router.push({path: '/home'})
			
		命名的路由(傳遞引數)
			router.push({name: '/user',params: {userId: 123}})
			
		帶查詢引數,變成 /register?uname=lisi
			router.push({ path: '/register', query: {uname: 'lisi' }})
*/

後臺管理案例

點選左側的"使用者管理","許可權管理","商品管理","訂單管理","系統設定"都會出現對應的元件並展示內容

其中"使用者管理"元件展示的效果如上圖所示,在使用者管理區域中的詳情連結也是可以點選的,點選之後將會顯示使用者詳情資訊。

案例思路

/*
		1).先將素材資料夾中的11.基於vue-router的案例.html複製到我們自己的資料夾中。
        看一下這個檔案中的程式碼編寫了一些什麼內容,
        這個頁面已經把後臺管理頁面的基本佈局實現了
    2).在頁面中引入vue,vue-router
    3).建立Vue例項物件,準備開始編寫程式碼實現功能
    4).希望是通過元件的形式展示頁面的主體內容,而不是寫死頁面結構,所以我們可以定義一個根元件:
*/

實現步驟

/*
		1. 抽離並渲染App根元件
		2. 將左側選單改造為路由連結
		3. 建立左側選單對應的路由元件
		4. 在右側主體區域新增路由佔位符
		5. 新增子路由規則
		6. 通過路由重定向預設渲染使用者元件
		7. 程式設計式導航跳轉到使用者詳情頁
		8. 實現後退功能
*/
//只需要把原本頁面中的html程式碼設定為元件中的模板內容即可
const app = {
    template:`<div>
        <!-- 頭部區域 -->
        <header class="header">傳智後臺管理系統</header>
        <!-- 中間主體區域 -->
        <div class="main">
          <!-- 左側選單欄 -->
          <div class="content left">
            <ul>
              <li>使用者管理</li>
              <li>許可權管理</li>
              <li>商品管理</li>
              <li>訂單管理</li>
              <li>系統設定</li>
            </ul>
          </div>
          <!-- 右側內容區域 -->
          <div class="content right">
            <div class="main-content">新增使用者表單</div>
          </div>
        </div>
        <!-- 尾部區域 -->
        <footer class="footer">版權資訊</footer>
      </div>`
  }

當我們訪問頁面的時候,預設需要展示剛剛建立的app根元件,我們可以
建立一個路由物件來完成這個事情,然後將路由掛載到Vue例項物件中即可

const myRouter = new VueRouter({
    routes:[
        {path:"/",component:app}
    ]
})

const vm = new Vue({
    el:"#app",
    data:{},
    methods:{},
    router:myRouter
})

補充:到此為止,基本的js程式碼都處理完畢了,我們還需要設定一個路由佔位符

<body>
  <div id="app">
    <router-view></router-view>
  </div>
</body>

此時我們開啟頁面應該就可以得到一個VueRouter路由出來的根元件了
我們需要在這個根元件中繼續路由實現其他的功能子元件
先讓我們更改根元件中的模板:更改左側li為子級路由連結,並在右側內容區域新增子級元件佔位符

const app = {
    template:`<div>
        ........
        <div class="main">
          <!-- 左側選單欄 -->
          <div class="content left">
            <ul>
              <!-- 注意:我們把所有li都修改為了路由連結 -->
              <li><router-link to="/users">使用者管理</router-link></li>
              <li><router-link to="/accesses">許可權管理</router-link></li>
              <li><router-link to="/goods">商品管理</router-link></li>
              <li><router-link to="/orders">訂單管理</router-link></li>
              <li><router-link to="/systems">系統設定</router-link></li>
            </ul>
          </div>
          <!-- 右側內容區域 -->
          <div class="content right">
            <div class="main-content">
                <!-- 在 -->
                <router-view></router-view> 
            </div>
          </div>
        </div>
        .......
      </div>`
  }

然後,我們要為子級路由建立並設定需要顯示的子級元件

//建議建立的元件首字母大寫,和其他內容區分
const Users = {template:`<div>
    <h3>使用者管理</h3>
</div>`}
const Access = {template:`<div>
    <h3>許可權管理</h3>
</div>`}
const Goods = {template:`<div>
    <h3>商品管理</h3>
</div>`}
const Orders = {template:`<div>
    <h3>訂單管理</h3>
</div>`}
const Systems = {template:`<div>
    <h3>系統管理</h3>
</div>`}

//新增子元件的路由規則
const myRouter = new VueRouter({
    routes:[
        {path:"/",component:app , children:[
            { path:"/users",component:Users },
            { path:"/accesses",component:Access },
            { path:"/goods",component:Goods },
            { path:"/orders",component:Orders },
            { path:"/systems",component:Systems },
        ]}
    ]
})

const vm = new Vue({
    el:"#app",
    data:{},
    methods:{},
    router:myRouter
})

展示使用者資訊列表:
A.為Users元件新增私有資料,並在模板中迴圈展示私有資料

const Users = {
data(){
    return {
        userList:[
            {id:1,name:"zs",age:18},
            {id:2,name:"ls",age:19},
            {id:3,name:"wang",age:20},
            {id:4,name:"jack",age:21},
        ]
    }
},
template:`<div>

    <h3>使用者管理</h3>
    <table>
        <thead>
            <tr>
                <th>編號</th>
                <th>姓名</th>
                <th>年齡</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <tr :key="item.id" v-for="item in userList">
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.age}}</td>
                <td><a href="javascript:;">詳情</a></td>
            </tr>
        </tbody>
    </table>

</div>`}
```

當使用者列表展示完畢之後,我們可以點選列表中的詳情來顯示使用者詳情資訊,首先我們需要建立一個元件,用來展示詳情資訊

const UserInfo = {
    props:["id"],
    template:`<div>
      <h5>使用者詳情</h5>
      <p>檢視 {{id}} 號使用者資訊</p>
      <button @click="goBack">返回使用者詳情頁</button>
    </div> `,
    methods:{
      goBack(){
        //當使用者點選按鈕,後退一頁
        this.$router.go(-1);
      }
    }
  }

然後我們需要設定這個元件的路由規則

const myRouter = new VueRouter({
    routes:[
        {path:"/",component:app , children:[
            { path:"/users",component:Users },
            //新增一個/userinfo的路由規則
            { path:"/userinfo/:id",component:UserInfo,props:true},
            { path:"/accesses",component:Access },
            { path:"/goods",component:Goods },
            { path:"/orders",component:Orders },
            { path:"/systems",component:Systems },
        ]}
    ]
})

const vm = new Vue({
    el:"#app",
    data:{},
    methods:{},
    router:myRouter
})

再接著給使用者列表中的詳情a連線新增事件

const Users = {
    data(){
        return {
            userList:[
                {id:1,name:"zs",age:18},
                {id:2,name:"ls",age:19},
                {id:3,name:"wang",age:20},
                {id:4,name:"jack",age:21},
            ]
        }
    },
    template:`<div>
        <h3>使用者管理</h3>
        <table>
            <thead>
                <tr>
                    <th>編號</th>
                    <th>姓名</th>
                    <th>年齡</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <tr :key="item.id" v-for="item in userList">
                    <td>{{item.id}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.age}}</td>
                    <td><a href="javascript:;" @click="goDetail(item.id)">詳情</a></td>
                </tr>
            </tbody>
        </table>
    </div>`,
    methods:{
        goDetail(id){
            this.$router.push("/userinfo/"+id);
        }
    }
}

完整程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>基於vue-router的案例</title>
    <style type="text/css">
        html,
        body,
        #app {
            margin: 0;
            padding: 0px;
            height: 100%;
        }

        .header {
            height: 50px;
            background-color: #545c64;
            line-height: 50px;
            text-align: center;
            font-size: 24px;
            color: #fff;
        }

        .footer {
            height: 40px;
            line-height: 40px;
            background-color: #888;
            position: absolute;
            bottom: 0;
            width: 100%;
            text-align: center;
            color: #fff;
        }

        .main {
            display: flex;
            position: absolute;
            top: 50px;
            bottom: 40px;
            width: 100%;
        }

        .content {
            flex: 1;
            text-align: center;
            height: 100%;
        }

        .left {
            flex: 0 0 20%;
            background-color: #545c64;
        }

        .left a {
            color: white;
            text-decoration: none;
        }

        .right {
            margin: 5px;
        }

        .btns {
            width: 100%;
            height: 35px;
            line-height: 35px;
            background-color: #f5f5f5;
            text-align: left;
            padding-left: 10px;
            box-sizing: border-box;
        }

        button {
            height: 30px;
            background-color: #ecf5ff;
            border: 1px solid lightskyblue;
            font-size: 12px;
            padding: 0 20px;
        }

        .main-content {
            margin-top: 10px;
        }

        ul {
            margin: 0;
            padding: 0;
            list-style: none;
        }

        ul li {
            height: 45px;
            line-height: 45px;
            background-color: #a0a0a0;
            color: #fff;
            cursor: pointer;
            border-bottom: 1px solid #fff;
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        td,
        th {
            border: 1px solid #eee;
            line-height: 35px;
            font-size: 12px;
        }

        th {
            background-color: #ddd;
        }
    </style>
    <script src="js/vue_2.5.22.js"></script>
    <script src="js/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 要被vue例項所控制的區域 -->
<div id="app">
    <!-- 路由佔位符 -->
    <router-view></router-view>
</div>


<script>
    // 定義APP根元件
    const App = {
        template: `
            <div>
                <header class="header">後臺管理系統</header>
                <div class="main">
                    <div class="content left">
                        <ul>
                            <li><router-link to="/users">使用者管理</router-link></li>
                            <li><router-link to="/rights">許可權管理</router-link></li>
                            <li><router-link to="/goods">商品管理</router-link></li>
                            <li><router-link to="/orders">訂單管理</router-link></li>
                            <li><router-link to="/settings">系統設定</router-link></li>
                        </ul>
                    </div>
                    <div class="content right"><div class="main-content">
                        <router-view />
                    </div></div>
                </div>
                <footer class="footer">版權資訊</footer>
            </div>
            `
    }


    const Users = {
        data() {
            return {
                userlist: [
                    {id:1,name:'youmen1',age:10},
                    {id:2,name:'youmen2',age:20},
                    {id:3,name:'youmen3',age:30},
                    {id:4,name:'youmen4',age:40}
                ]
            }
        },
        methods: {
            goDetail(id){
                console.log(id)
                this.$router.push('/userinfo/' + id)
            }
        },
        template: `<div>
        <h3>使用者管理區域</h3>
        <table>
            <thead>
                <tr><th>編號</th><th>姓名</th><th>年齡</th><th>操作</th></tr>
            </thead>
            <tbody>
                <tr v-for="item in userlist" :key="item.id">
                    <td>{{ item.id }}</td>
                    <td>{{ item.name }}</td>
                    <td>{{ item.age }}</td>
                    <td>
                        <a href="javascript:;" @click="goDetail(item.id)">詳情</a>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>`}

    const UserInfo = {
        props: ['id'],
        template: `<div>
          <h5>使用者詳情頁 --- 使用者Id為:{{id}}</h5>
          <button @click="goback()">後退</button>
        </div>`,
        methods: {
            goback() {
                // 實現後退功能
                this.$router.go(-1)
            }
        }
    }

    const Rights = { template: `<div>
        <h3>許可權管理區域</h3>
    </div>`}

    const Goods = { template: `<div>
        <h3>商品管理區域</h3>
    </div>`}

    const Orders = { template: `<div>
        <h3>訂單管理區域</h3>
    </div>`}

    const Settings = { template: `<div>
        <h3>系統設定區域</h3>
    </div>`}

    // 建立路由物件
    const router = new VueRouter({
        routes: [
            {
                path: '/',
                component: App,
                redirect: '/users',
                children: [
                    { path: '/users', component: Users },
                    { path: '/userinfo/:id', component: UserInfo, props: true },
                    { path: '/rights', component: Rights },
                    { path: '/goods', component: Goods },
                    { path: '/orders', component: Orders },
                    { path: '/settings', component: Settings }
                ]
            }
        ]
    })

    const vm = new Vue({
        el: '#app',
        router
    })
</script>


</body>
</html>

相關文章