vue-router的使用
基本vue-cli@2.x创建的vue项目。
1.插件安装
# 安装路由
npm install vue-router --save-dev
# element-ui
npm i element-ui -S
# 安装axios
npm install axios -s
# 提升下载速度,后面加这个 指定下载源
--registry https://registry.npmmirror.com
项目结构图:
2.项目配置
main.js文件配置
通过es6语法
导入npm
下载的插件,然后通过Vue.use(xx插件)
,全局声明使用插件.注意:axios
的注册方式不一样。如果要使用Vue.use
方法,可以下载vue-axious
的插件库。用法差不多。
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
//=======导入路由配置======
import router from './router'
//=====导入element-ui 和其样式======
import ElementUi from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
//=======导入axios========
import axios from 'axios'
Vue.config.productionTip = false
//=======声明使用插件======
Vue.use(ElementUi)
//=====注册axios=====
Vue.prototype.axios=axios
/* eslint-disable no-new */
new Vue({
el: '#app',
//=======把路由加入vue实例中=====
router,
components: { App },
template: '<App/>',
render: h => h(App)
})
路由配置:
在src目录下,新建一个router
目录,里面再创建一个index.js
的路由配置文件.此路由已经在main.js
导入了.所有的compoent
都来自下面配置的组件。
配置说明:
mode:
- 默认取值
hash
,就是每次访问路径时,路径上都会带有#
- histroy:路径不带
#
号
- 默认取值
routes
:用于定义path的访问,每个数组里面都是{}
path
:访问的路径定义 如:'/index'
component
:路径访问对应的组件定义name
:当前路径的名称定义,可以实现通过名称访问redirect:
重定向到已经定义的path上prop
:当前路径开启prop属性,路径对应的组件里面可以定义prop:[xx],来接受参数
/main/:name
:就是给路径定义一个占位符,在路径跳转时,传入参数,然后通过$route.params.name
获取其参数。高级点可以通过正则表达式来匹配。
router/index.js
:
import Vue from 'vue'
import Router from 'vue-router'
//所有的组件导入
import HelloWorld from '@/components/HelloWorld'
import Main from '../components/Main'
import Login from '../components/Login'
import Menu from '../components/Menu'
import User from '../components/User'
import Role from '../components/Role'
import NotFound from '../components/NotFound'
Vue.use(Router)
export default new Router({
mode:'history', //不带#号
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},{
/* :参数名就是提供一个占位符,路径跳转的时候可以获取
如果直接是 /main的路径,则不会配置。
*/
path:'/main/:username',
name:'Main',
component:Main,
//表示开启props使路由组件可以通过prop:['xxxx']接受 $route.params参数
props:true
},{
path:'/login',
name:'Login',
component:Login
},{
path:'/menu',
name:'Menu',
component:Menu,
//=====嵌套子路由======
children:[
{
path:'/user',
name:'User',
component:User
},
{
path:'/role',
name:'Role',
component:Role
}
]
},{
//==========定义404页面========
path:'*',
component:NotFound
},{
//重定向
path:'/home/:username',
redirect:'/main/:username'
}
]
})
3.路由标签
router-link
:
<router-link to="path"></router-link>
请注意,我们没有使用常规的 a
标签,而是使用一个自定义组件 router-link
来创建链接。这使得 Vue Router 可以在不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码。其属性有多个选项表示跳转的状态。
router-view
:
<router-view></router-view>
访问路径后,将路径对应的默认组件进行显示。一般在其父组件进行定义。可以指定组件显示。
Main.vue
中:
<router-link to="/login">登录</router-link>
<router-link to="/menu">管理</router-link>
Menu.vue
中:
<ul class="nav">
<li><router-link to="/user">用户管理</router-link></li>
<li><router-link to="/role">角色管理</router-link></li>
<li><router-link to="/home/jack">回到首页</router-link></li>
</ul>
App.vue
中
组件如果没有嵌套,所有组件通过路由访问,在此进行显示
<template>
<div id="app">
<router-view/>
</div>
</template>
4.路径跳转
分为带参数和不带参数
用户和密码通过element-ui进行校验后,通过配置路由的的相关对象进行跳转
跳转的方式:
声明式 | 编程式 |
---|---|
<router-link :to="..."> | router.push(...) |
所谓声明式,就是像a标签一样进行点击跳转,而编程式,则在js里面操作路由对象进行跳转。
-
路径直接跳:
router.push('/users/eduardo')
-
带有路径对象跳:
// 带有路径的对象 router.push({ path: '/users/eduardo' })
-
带有路径的名称和参数跳:
//path为 /user/eduardo //name是路由配置时定义的,可以匹配到路由路径 router.push({ name: 'user', params: { username: 'eduardo' } })
-
带有路由和查询参数对象
$route.query.play
// 带查询参数/register?plan=private router.push({ path: '/register', query: { plan: 'private' } })
- 如果提供了
path
+params
会被忽略,上述例子中的query
并不属于这种情况。取而代之的是,你需要提供路由的name
+params
或手写完整的带有参数的path:/main/jack
.- 注意路径参数的传递,必须保证路径的配置文件里面已经开启了 形如:
/main/:name
中:name
,表示传递参数赋值/user/jakc
和{path:'/user',params:{username:'jakc'}}
的路径一样,只是表现形式不同而已
案例:登录验证后,通过路由跳转
Login.vue文件内容:
<template>
<div>
<el-form ref="form" :model="form" class="login-box" :rules="rules">
<h3>欢迎登录</h3>
<el-form-item label="账号" prop="name">
<el-input
type="text"
placeholder="请输入用户名"
v-model="form.name"
></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
type="password"
placeholder="请输入密码"
v-model="form.password"
></el-input>
</el-form-item>
<el-form>
<el-button type="primary" @click="submitForm('form')">登录</el-button>
</el-form>
</el-form>
</div>
</template>
<script>
export default {
name: "Login",
data() {
return {
form: {
name: "",
password: "",
},
rules: {
name: [
{ required: true, message: "请输入用户名", trigger: "blur" },
{ min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" },
],
password: [
{ required: true, message: "请输入密码", trigger: "blur" },
{
min: 6,
max: 10,
message: "长度在 6 到 10 个字符",
trigger: "blur",
},
],
},
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
//登录成功,保存登录信息
sessionStorage.setItem("loginInfo",this.form.name);
//=====================带信息跳转=============
//path==> /main/jakc?q=查询饕餮
this.$router.push({name:'Main',params:{username:this.form.name},query:{q:"查询饕餮"}});
} else {
this.$message.error('输入有误');
return false;
}
});
}
},
};
</script>
<style scoped>
.login-box {
width: 400px;
margin: 30px auto;
border: 1px solid #dcdfe6;
padding: 20px;
border-radius: 6px;
box-shadow: 0 0 30px #dcdfe6;
}
.login-box h3 {
text-align: center;
}
</style>
效果:
5.参数获取
路径的配置中有
{
path:"/main/:username",
component:xxx,
name:xxx,
prop:true //开启,第二种才能使用
}
第一种:
<template>
<p><span>1:{{$route.params.username}}</span>
</template>
第二种:
<template>
<span>2:{{username}}</span>
</template>
<script>
export default {
//路径配置必须开启,接受来自$route.params.xxx的参数
props:['username'],
</script>
案例:登录后主页展示数据
Main.vue
:
<template>
<div>
<i class="el-icon-user"></i>
<p>
<!-- =======数据获取===================-->
<span>1:{{$route.params.username}}</span>
<span>2:{{username}}</span>
<span>3:query参数:{{$route.query.q}}</span>
</p>
<router-link to="/login">登录</router-link>
<router-link to="/menu">管理</router-link>
<el-table
:data="tableData"
center
style="width: 50%;margin:20px auto">
<el-table-column
prop="date"
label="日期"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
//==========路径配置必须开启,接受来自$route.params.xxx的参数========
props:['username'],
data() {
return {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
}
},
//使用路由的钩子函数获取异步数据 -=== 后面axios讲了====
beforeRouteEnter (to, from, next) {
/*由于路由进入之前,此组件为实例化,
通过回调函数获取实例,从而调用methods里面的方法*/
console.log("进入path:"+to.fullPath);
next(vm=>vm.getData());
},
methods:{
//定义函数通过axios获取参数
getData(){
this.axios.get("./static/data.json").then((res)=>{
// console.log(res);
this.tableData=res.data.info;
}).catch(err=>{
console.log("请求失败的信息:");
console.log(err);
});
}
}
}
</script>
<style lang="">
</style>
效果:
6. 重定向与404
index.js中:
routes:[
{
//====定义404页面====
path:'*',
component:NotFound
},{
//重定向
path:'/home/:username',
redirect:'/main/:username'
}
]
Menu.vue
中:
<li><router-link to="/home/jack">回到首页</router-link></li>
NotFoud.vue中:
<template lang="">
<div>
<img src="@/assets/404.jpeg"/>
</div>
</template>
<script>
export default {
name:'NotFound'
}
</script>
<style lang="">
</style>
7.路由嵌套
配置的路由访问中,通过children
再次配置路由访问。即在当前路径a中如果访问配置的子路由b,则b路由组件可以直接显示到当前路由a的组件中。
index.js
文件:a
{
path:'/menu',
name:'Menu',
component:Menu,
//嵌套子路由
children:[
{
path:'/user',
name:'User',
component:User
},
{
path:'/role',
name:'Role',
component:Role
}
]
Menu.vue:
<template lang="">
<div>
<ul class="nav">
<li><router-link to="/user">用户管理</router-link></li>
<li><router-link to="/role">角色管理</router-link></li>
<li><router-link to="/home/jack">回到首页</router-link></li>
</ul>
<router-view></router-view>
</div>
</template>
User.vue
<template>
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
label="日期"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
<el-table-column
label="姓名"
width="180">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<p>姓名: {{ scope.row.name }}</p>
<p>住址: {{ scope.row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.name }}</el-tag>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
size="mini"
@click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
data() {
return {
tableData: [{
date: '2016-05-02',
name: '悟空',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '圣将',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '唐僧藏',
address: '上海市普陀区金沙江路 1516 弄'
}]
}
},
methods: {
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
console.log(index, row);
}
}
}
</script>
Role.vue:
<template>
<el-table
:data="tableData"
border
style="width: 100%">
<el-table-column
prop="index"
label="序号"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="power"
label="战力值">
</el-table-column>
</el-table>
</template>
<script>
export default {
data() {
return {
tableData: [{
index: '1',
name: '悟空',
power: '100'
}, {
index: '2',
name: '王小虎',
power: '20'
}, {
index: '3',
name: '圣将',
power: '90'
}, {
index: '4',
name: '唐僧藏',
power: '80'
}]
}
}
}
</script>
效果:
menu.vue页面:
点击用户管理:当前menu.vue
保存不变,显示user.vue
内容
点击角色户管理:当前Menu.vue
保存不变,显示Role.vue
内容
8.路由钩子函数
所谓钩子函数,访问某个路径,在这个路径关联的组件里面,自动执行所触发的函数。
-
Main.vue
export default{ data(){ return {} }, //进入当前路径 执行 beforeRouteEnter (to, from, next) { console.log("进入path:"+to.fullPath); next();//可继续去往下一个路由 }, //离开当前路径 执行 beforeRouteLeave(to,from,next){ console.log("离开path"+to.fullePath); next(); //可继续去往下一个路由 } }
-
main.js
文件:beforeEach
是全局钩子函数,所有的路径访问都会触发执行此函数。相当于javaweb的/
的拦截器。可做登录验证。// (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' //导入路由配置 import router from './router' //import ............. Vue.config.productionTip = false //===========导航全局首位,相当于过滤器,如验证是否登录========= router.beforeEach((to,from,next)=>{ //获取登录状态 let isLogin=sessionStorage.getItem("loginInfo"); if(to.path=='/logout'){ //清除登录状态 sessionStorage.clear(); //去往登录页 next({path:'/login'}) //如果不加 to.fullPath!='/login',则会不断循环next路由 }else if(isLogin==null && to.path!='/login'){ //去往登录页 next({path:'/login'}) } //下一个路由 next(); }); new Vue({ el: '#app', router, components: { App }, template: '<App/>', render: h => h(App) })
-
参数说明:
to
:路由将要跳转的路径信息from
:路径跳转前的路径信息next
:路由的控制参数:next()
跳入下一个页面next('/path')
改变路由的跳转方向,使其跳到另一个路由next(false)
返回原来的页面next((vm)=>{})
仅在beforeRouteEnter
中可用,vm 是组件实例化
9.钩子函数+axios
通过路径访问前,异步加载axios获取数据。如从登录Login.vue
组件到Main.vue
组件
data.json文件内容:
{
"info":[
{
"date":"2020/3/11",
"name":"jack",
"address":"饭都花园"
},
{
"date":"2022/4/11",
"name":"jack",
"address":"西湖公园"
},
{
"date":"2021/3/4",
"name":"jerry",
"address":"天门山游玩"
}
]
}
Main.vue
文件:
<script>
export default{
//使用路由的钩子函数获取异步数据
beforeRouteEnter (to, from, next) {
/*由于路由进入之前,此组件未实例化,
通过回调函数获取实例,从而调用methods里面的方法*/
console.log("进入path:"+to.fullPath);
next(vm=>vm.getData());
},
methods:{
//定义函数通过axios获取参数
getData(){
this.axios.get("./static/data.json").then((res)=>{
// console.log(res);
this.tableData=res.data.info;
}).catch(err=>{
console.log("请求失败的信息:");
console.log(err);
});
}
}
}
</script>