06 . Vue路由简介,原理,实现及嵌套路由,动态路由,编程式导航

路由概念

路由的本质就是一种对应关系,比如说我们在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>
posted @ 2020-11-19 20:04  常见-youmen  阅读(1079)  评论(2编辑  收藏  举报