前端学习八(Vue Router)
Vue Router官网:https://router.vuejs.org/zh/guide/#html
一、引用库
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
二、定义 (路由) 组件(可以从其他文件 import 进来)
Login组件如下
const Login = { template: ` <div class="box"> <el-card class="box-card"> <h3>用户登录</h3> <el-form :model="form" label-width="80px"> <el-form-item label="账号"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="密码"> <el-input v-model="form.password" type="password"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="login">点击登录</el-button> </el-form-item> </el-form> </el-card> </div>`, data() { return { form: { username: "", password: "" } } }, methods: { async login() { const r = await http.post("/user/login/", this.form) if (r.status === 200) { const token = r.data.token; window.sessionStorage.setItem("token", token) // 编程式跳转路由 this.$router.push('/home') // this.$router.push({ path: '/login' }) } else { alert("登录失败") } } } }
Home组件如下
const Home = { template: ` <div class="box2"> <el-button type="primary" @click="getProjects">获取项目</el-button> <el-table :data="tableData" stripe style="width: 100%"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="name" label="项目" width="180"> </el-table-column> <el-table-column prop="create_time" label="创建时间" min-width="200px"> </el-table-column> </el-table> </div>` , data() { return { tableData: "" } }, methods: { async getProjects() { const r = await http.get("/projects/") console.log(r); if (r.status === 200) { this.tableData = r.data.results } else { alert("获取项目失败") } }, } }
三、定义路由以及创建路由实例
// 2. 定义路由 // 每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器, // 或者,只是一个组件配置对象。 const routes = [ { path: "/login", component: Login }, { path: "/home", component: Home } ] // 3. 创建 router 实例 const router = new VueRouter({ routes: routes // 如果定义的路由名和key相同,则可以如下简写 // routes })
子路由
const routes = [ { path: "/", component: Home, // 子路由,内容会渲染在父路由的router-view中 children: [ { path: "/index", component: index }, { path: "/project", component: project }, { path: "/api", component: api } ] }, { path: "/login", component: Login } ]
别名和重定向
const routes = [ // 重定向 { path: "/", redirect: "/login" }, // 别名name { name: "rgs", path: "/register", component: Register }, { path: "/login", component: Login }, { path: "/home", component: Home } ]
别名被使用的两种方式
// 编程式跳转路由,使用别名 this.$router.push({ name: 'rgs' })
<!-- 使用router-link标签跳转路由(注意,这里是属性绑定,所以要用绑定的形式) --> <router-link :to="{name:'rgs'}" >注册</router-link>
四、注入路由到vue实例
// 4. 注入路由到vue实例 const app = new Vue({ el: "#app", router: router })
五、使用
<div id='app'> <!-- 路由出口,路由匹配到的组件将渲染在这里 --> <router-view></router-view> </div>
六、编程式导航和声明式导航
// 编程式跳转路由 this.$router.push('/home')
<!-- 声明式导航 --> <router-link to="/login">登录页面</router-link>
七、上面学习内容练习的实例
实例1
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <script src="https://unpkg.com/element-ui/lib/index.js"></script> </head> <body> <div id='app'> <!-- 路由出口,路由匹配到的组件将渲染在这里 --> <router-view></router-view> </div> <script> const http = axios.create({ baseURL: 'http://api.keyou.site:8000', timeout: 1000 }); http.interceptors.request.use(function (config) { const token = window.sessionStorage.getItem("token") if (token) { config.headers.Authorization = 'JWT ' + token } return config; }, function (error) { return Promise.reject(error); }); // 1. 定义 (路由) 组件,可以从其他文件 import 进来 const Login = { template: ` <div class="box"> <el-card class="box-card"> <h3>用户登录</h3> <el-form :model="form" label-width="80px"> <el-form-item label="账号"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="密码"> <el-input v-model="form.password" type="password"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="login">点击登录</el-button> </el-form-item> </el-form> </el-card> </div>`, data() { return { form: { username: "musen123", password: "123456" } } }, methods: { async login() { const r = await http.post("/user/login/", this.form) if (r.status === 200) { const token = r.data.token; window.sessionStorage.setItem("token", token) // 编程式跳转路由 this.$router.push('/home') // this.$router.push({ path: '/login' }) } else { alert("登录失败") } } } } const Home = { template: ` <div class="box2"> <el-button type="primary" @click="getProjects">获取项目</el-button> <el-table :data="tableData" stripe style="width: 100%"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="name" label="项目" width="180"> </el-table-column> <el-table-column prop="create_time" label="创建时间" min-width="200px"> </el-table-column> </el-table> </div>` , data() { return { tableData: "" } }, methods: { async getProjects() { const r = await http.get("/projects/") console.log(r); if (r.status === 200) { this.tableData = r.data.results } else { alert("获取项目失败") } }, } } // 2. 定义路由 // 每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器, // 或者,只是一个组件配置对象。我们晚点再讨论嵌套路由。 const routes = [ { path: "/login", component: Login }, { path: "/home", component: Home } ] // 3. 创建 router 实例 const router = new VueRouter({ routes: routes // 如果定义的路由名和key相同,则可以如下简写 // routes }) // 4. 注入路由到vue实例 const app = new Vue({ el: "#app", router: router }) </script> </body> </html>
实例2
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <script src="https://unpkg.com/element-ui/lib/index.js"></script> </head> <body> <div id='app'> <el-menu class="el-menu-demo" mode="horizontal" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b"> <el-menu-item index="11"> <!-- 声明式导航 --> <router-link to="/login">登录页面</router-link> </el-menu-item> <el-menu-item index="12"> <router-link to="/home">个人中心</router-link> </el-menu-item> <el-menu-item index="13"> <!-- 使用router-link标签跳转路由(注意,这里是属性绑定,所以要用绑定的形式) --> <router-link :to="{name:'rgs'}" >注册</router-link> </el-menu-item> <el-submenu index="2"> <template slot="title">我的工作台</template> <el-menu-item index="2-1">选项1</el-menu-item> <el-menu-item index="2-2">选项2</el-menu-item> <el-menu-item index="2-3">选项3</el-menu-item> </el-submenu> <el-menu-item index="3" disabled>消息中心</el-menu-item> <el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item> </el-menu> <!-- 路由出口,路由匹配到的组件将渲染在这里 --> <router-view></router-view> </div> <script> const http = axios.create({ baseURL: 'http://api.keyou.site:8000', timeout: 1000 }); http.interceptors.request.use(function (config) { const token = window.sessionStorage.getItem("token") if (token) { config.headers.Authorization = 'JWT ' + token } return config; }, function (error) { return Promise.reject(error); }); // 1. 定义 (路由) 组件 const Login = { template: ` <div class="box"> <el-card class="box-card"> <h3>用户登录</h3> <el-form :model="form" label-width="80px"> <el-form-item label="账号"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="密码"> <el-input v-model="form.password" type="password"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="login">点击登录</el-button> </el-form-item> </el-form> </el-card> </div>`, data() { return { form: { username: "musen123", password: "123456" } } }, methods: { async login() { const r = await http.post("/user/login/", this.form) if (r.status === 200) { const token = r.data.token; window.sessionStorage.setItem("token", token) // 编程式跳转路由 this.$router.push('/home') // this.$router.push({ path: '/login' }) } else { alert("登录失败") } } } } const Home = { template: ` <div class="box2"> <el-button type="primary" @click="registerBtn">注册</el-button> <el-button type="primary" @click="getProjects">获取项目</el-button> <el-table :data="tableData" stripe style="width: 100%"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="name" label="项目" width="180"> </el-table-column> <el-table-column prop="create_time" label="创建时间" min-width="200px"> </el-table-column> </el-table> </div>` , data() { return { tableData: "" } }, methods: { async getProjects() { const r = await http.get("/projects/") console.log(r); if (r.status === 200) { this.tableData = r.data.results } else { alert("获取项目失败") } }, async registerBtn() { // 编程式跳转路由,使用别名 this.$router.push({ name: 'rgs' }) }, } } const Register = { template: `<p1>注册页面</p1>` } const routes = [ // 重定向 { path: "/", redirect: "/login" }, // 别名name { name: "rgs", path: "/register", component: Register }, { path: "/login", component: Login }, { path: "/home", component: Home } ] const router = new VueRouter({ routes }) var vm = new Vue({ el: "#app", router: router }) </script> </body> </html>
实例3
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <script src="https://unpkg.com/element-ui/lib/index.js"></script> </head> <body> <div id='app'> <router-view></router-view> </div> <script> const http = axios.create({ baseURL: 'http://api.keyou.site:8000', timeout: 1000 }); http.interceptors.request.use(function (config) { const token = window.sessionStorage.getItem("token") if (token) { config.headers.Authorization = 'JWT ' + token } return config; }, function (error) { return Promise.reject(error); }); // 1. 定义 (路由) 组件 const Login = { template: ` <div class="box"> <el-card class="box-card"> <h3>用户登录</h3> <el-form :model="form" label-width="80px"> <el-form-item label="账号"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="密码"> <el-input v-model="form.password" type="password"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="login">点击登录</el-button> </el-form-item> </el-form> </el-card> </div>`, data() { return { form: { username: "musen123", password: "123456" } } }, methods: { async login() { const r = await http.post("/user/login/", this.form) if (r.status === 200) { const token = r.data.token; window.sessionStorage.setItem("token", token) // 编程式跳转路由 this.$router.push('/') // this.$router.push({ path: '/login' }) } else { alert("登录失败") } } } } const Home = { template: ` <div> <el-menu class="el-menu-demo" mode="horizontal" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b"> <el-menu-item index="1"> <router-link to="/index">index页面</router-link> </el-menu-item> <el-menu-item index="2"> <router-link to="/project">项目页面</router-link> </el-menu-item> <el-menu-item index="2"> <router-link to="/api">api页面</router-link> </el-menu-item> </el-menu> <router-view></router-view> </div>` } const index = { template: `<h1>index页面</h1>` } const project = { template: `<h1>项目页面</h1>` } const api = { template: `<h1>api页面</h1>` } const routes = [ { path: "/", component: Home, // 子路由,内容会渲染在父路由的router-view中 children: [ { path: "/index", component: index }, { path: "/project", component: project }, { path: "/api", component: api } ] }, { path: "/login", component: Login } ] const router = new VueRouter({ routes// (缩写) 相当于 routes: routes }) var vm = new Vue({ el: "#app", router: router }) </script> </body> </html>
八、路由参数传递
1、路径参数
// 编程式导航和传参 this.$router.push( { name: 'usr', params: { id: 999, key: 100 } } )
<button type="button"> <!-- 声明式导航 --> <router-link to="/user/99/00">声明式导航1</router-link> </button> <button type="button"> <!-- 声明式导航,别名和传参 --> <router-link :to="{name:'usr',params:{id:111,key:222}}">声明式导航2</router-link> </button>
const User = { // 动态路径匹配,我没定义$route,应该是vue对象自带的 template: ` <div> <h1>User页面</h1> <h3>参数值为:{{$route.params.id}}</h3> <h3>参数值为:{{$route.params.key}}</h3> </div>` }
练习文件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <script src="https://unpkg.com/element-ui/lib/index.js"></script> </head> <body> <div id="app"> <button type="button"> <!-- 声明式导航 --> <!-- <router-link to="/user/99/00">按钮</router-link> --> <!-- 声明式导航,别名和传参 --> <router-link :to="{name:'usr',params:{id:111,key:222}}">声明式导航</router-link> </button> <button type="button" @click='usrBtn'>编程式导航</button> <router-view></router-view> </div> <script type="text/javascript"> const Home = { template: "<h1>Home页面</h1>" } const User = { // 动态路径匹配,我没定义$route,应该是vue对象自带的 template: ` <div> <h1>User页面</h1> <h3>参数值为:{{$route.params.id}}</h3> <h3>参数值为:{{$route.params.key}}</h3> </div>` } const routes = [{ path: "/", component: Home, }, { path: "/user/:id/:key", component: User, name: "usr" }] const router = new VueRouter({ routes: routes }) var vm = new Vue({ el: "#app", data: {}, router: router, methods: { usrBtn() { console.log(this.$route); // 编程式导航和传参 this.$router.push( { name: 'usr', params: { id: 999, key: 100 } } ) console.log(this.$route); } } }) </script> </body> </html>
2、查询参数
// 编程式导航和传参 this.$router.push( { name: 'usr', query: { name: 111, age: 222 } } )
<button type="button"> <!-- 声明式导航,别名和传参 --> <router-link :to="{name:'usr',query:{name:777,age:888}}">声明式导航</router-link> </button>
const User = { // 动态路径匹配,我没定义$route,应该是vue对象自带的 template: ` <div> <h1>User页面</h1> <h3>参数值为:{{$route.query.name}}</h3> <h3>参数值为:{{$route.query.age}}</h3> </div>` }
练习文件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <script src="https://unpkg.com/element-ui/lib/index.js"></script> </head> <body> <div id="app"> <button type="button"> <!-- 声明式导航,别名和传参 --> <router-link :to="{name:'usr',query:{name:777,age:888}}">声明式导航</router-link> </button> <button type="button" @click='usrBtn'>编程式导航</button> <router-view></router-view> </div> <script type="text/javascript"> const Home = { template: "<h1>Home页面</h1>" } const User = { // 动态路径匹配,我没定义$route,应该是vue对象自带的 template: ` <div> <h1>User页面</h1> <h3>参数值为:{{$route.query.name}}</h3> <h3>参数值为:{{$route.query.age}}</h3> </div>` } const routes = [{ path: "/", component: Home, }, { path: "/user", component: User, name: "usr" }] const router = new VueRouter({ routes: routes }) var vm = new Vue({ el: "#app", data: {}, router: router, methods: { usrBtn() { console.log('==',this.$route); // 编程式导航和传参 this.$router.push( { name: 'usr', query: { name: 111, age: 222 } } ) console.log("++",this.$route); } } }) </script> </body> </html>
九、导航守卫
应用场景,把没有权限访问的路径重定向回开始路径
to 前往路径
from 开始路径
next 执行跳转动作,默认参数是to路径
// 定义路由导航守卫 router.beforeEach((to, from, next) => { if (to.path === '/login' || window.sessionStorage.getItem('token')) { // 这里还可以鉴别token是否有效 next() } else { next('/login') } })
练习文件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <script src="https://unpkg.com/element-ui/lib/index.js"></script> </head> <body> <div id='app'> <!-- 路由出口,路由匹配到的组件将渲染在这里 --> <router-view></router-view> </div> <script> const http = axios.create({ baseURL: 'http://api.keyou.site:8000', timeout: 1000 }); http.interceptors.request.use(function (config) { const token = window.sessionStorage.getItem("token") if (token) { config.headers.Authorization = 'JWT ' + token } return config; }, function (error) { return Promise.reject(error); }); const Login = { template: ` <div class="box"> <el-card class="box-card"> <h3>用户登录</h3> <el-form :model="form" label-width="80px"> <el-form-item label="账号"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="密码"> <el-input v-model="form.password" type="password"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="login">点击登录</el-button> </el-form-item> </el-form> </el-card> </div>`, data() { return { form: { username: "musen123", password: "123456" } } }, methods: { async login() { const r = await http.post("/user/login/", this.form) if (r.status === 200) { const token = r.data.token; window.sessionStorage.setItem("token", token) // 编程式跳转路由 this.$router.push('/home') // this.$router.push({ path: '/login' }) } else { alert("登录失败") } } } } const Home = { template: ` <div class="box2"> <el-button type="primary" @click="getProjects">获取项目</el-button> <el-table :data="tableData" stripe style="width: 100%"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="name" label="项目" width="180"> </el-table-column> <el-table-column prop="create_time" label="创建时间" min-width="200px"> </el-table-column> </el-table> </div>` , data() { return { tableData: "" } }, methods: { async getProjects() { const r = await http.get("/projects/") console.log(r); if (r.status === 200) { this.tableData = r.data.results } else { alert("获取项目失败") } }, } } const routes = [ { path: "/login", component: Login }, { path: "/home", component: Home } ] const router = new VueRouter({ routes: routes }) // 定义路由导航守卫 router.beforeEach((to, from, next) => { if (to.path === '/login' || window.sessionStorage.getItem('token')) { // 这里还可以鉴别token是否有效 next() } else { next('/login') } }) const app = new Vue({ el: "#app", router: router }) </script> </body> </html>
一个只会点点点的测试,有疑问可以在测试群(群号:330405140)问我

浙公网安备 33010602011771号