Day 85 VUE——路由

路由

安装:npm i vue-router -S,
推荐使用 vue add router 添加组件(记得提前把代码提交到 git)

在 main,js 中

import Vue from ‘vue’
import VueRouter from ‘vue-router’

Vue.use(VueRouter)

vue-router的基本使用

// 1.导入
import Vue from 'vue'
import router from 'vue-router'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'

// 2.模块化机制 使用 Router
Vue.use(router)

// 3.创建路由器对象
export default new VueRouter({
  routes:[
    {
      path:'/',
      name:'home',
      component:Home
    },
    {
      path:'/about',
      name:'about',
      component:About
    },
    {
      path:'/user:id',
      name:'user',
      component:()=>import('@/views/User')
    },
    {
      path:'*',
      component:()=>import('@/views/404')
    },
  ]
})
基本使用

 

命名路由

const routes = [
  {
    path: '/',
    name: 'Home',    // 对路由命名
    component: Home
  }
]
index.js
<template>
    <div id="nav">
       // :to="{name:'Home'}"  使用命名路由
      <router-link :to="{name:'Home'}">Home</router-link> | 
      <router-link :to="{name:'About'}">About</router-link> | 
    </div>
    <router-view/>
</template>
App.vue

 

动态路由匹配和路由组件复用

路由 监听、导航守卫

import User from '@/views/User.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
   // 准备重用的路由
  {
    path:'/user',
    name:'User',
    component:User
  }
]
index.js
<template>
  <div id="app">
    <!--  :to="{params:{id:2}}  params 是对路由的重用设置 -->
    <div id="nav">
      <router-link :to="{name:'Home'}">Home</router-link> | 
      <router-link :to="{name:'User',params:{id:1}}">User_1</router-link> | 
      <router-link :to="{name:'User',params:{id:2}}">User_2</router-link>
    </div>
    <router-view/>
  </div>
</template>
App.vue
<template>
    <div>
        我是用户界面{{ $route.params.id }}
    </div>
</template>

<script>
export default {
    // 路由组件会复用的情况

    // 当路由参数变化时,/user/1 切换到 /user/2 时,原来的组件实例会被复用
    // 因为两个路由渲染了同个组件,复用高效
    // created(){
    //         console.log(this.$route.params.id)
    // },
    // 监听
    // 相应路由参数变化
    watch:{
        $route:function(to){
            console.log(to.params.id)
            // 发起 ajax 请求后端接口数据 数据驱动视图
        }
    },
    // 导航守卫
    // beforeRouteUpdate(to,form,next){
    //     console.log(to.params.id)
    //     // 放行,一定要调用 next,不然会柱塞整个路由 
    //     next() 
    // }
}
</script>

<style>

</style>
USER.vue

 

404路由和路由匹配优先级

 404 的路由要放到最下面,不然影响正常使用

export default new VueRouter({
  routes:[
    {
      path:'/user:id',
      name:'user',
      component:()=>import('@/views/User')
    },
    {
      // 404 路由
      path:'*',
      component:()=>import('@/views/404')
    },
  ]
})
404
同一个路径可以匹配多个路由,匹配的优先级按照路由的定义顺序
谁先定义,谁的优先级高
export default new VueRouter({
  routes:[
    // 同一个路径可以匹配多个路由,匹配的优先级按照路由的定义顺序
    // 谁先定义,谁的优先级高
    // {
    //   path:'/about',
    //   name:'about',
    //   component:()=>import('@/views/User')
    // },
    {
      path:'/about',
      name:'about',
      component:About
    },
  ]
})
路由的优先级

 

路由查询参数

history 模式,干净的网页地址,没有 # 
// 3.创建路由器对象
export default new VueRouter({
  mode:'history',   // history 模式,干净的网页地址
  routes:[
    {
      path:'/',
      name:'home',
      component:Home
    },
    {
      path:'/page',
      name:'page',
      component:()=>import('@/views/Page')
    },
  ]
})
index.js
<template>
  <div id="app">
    <div id="nav">
      <router-link :to="{name:'user',params:{id:2}}">User_2</router-link> | 
      <router-link :to="{name:'page',query:{id:2,foo:'title'}}">Page</router-link>
    </div>
    <router-view/>
  </div>
</template>
App.vue
<template>
    <div>
        <h3>这是一个 Page 界面</h3>
    </div>
</template>

<script>
export default {
    created(){
        const {id,foo} = this.$route.query
        console.log(id,foo)     // 拿到这些信息就可以与后端进行交互了
    }
}
</script>

<style>

</style>
Page.vue

 

路由重定向和别名

export default new VueRouter({
  mode:'history',   // history 模式,干净的网页地址
  routes:[
    {
      path:'/',
      // 重定向
      // redirect:'home'
      redirect:{name:'home'}
    },
    {
      path:'/home',
      name:'home',
      component:Home,
      // 别名
      alias:'/hhh'
    },
    {
      path:'/about',
      name:'about',
      component:About
    },
  ]
})
index.js

 

路由组件传值

// 3.创建路由器对象
export default new VueRouter({
    {
      path:'/user:id',
      name:'user',
      component:()=>import('@/views/User'),
      // 路由组件传值
      // 方法一
      // props:true
      // 方法二
      props:(route)=>({
        id:route.params.id,
        title:route.query.title,
      })
    },
  ]
})
index.js
<template>
    <div>
        <h2>这个是 User {{ $route.params.id }}</h2>
        <h2>使用 props 传值 {{ id }} --- {{ title }}</h2>
    </div>
</template>

<script>
export default {
    props:['id','title'],
}
</script>

<style>

</style>
User.vue

 

如何使用编程式导航

<template>
    <div>
        <button @click="goHome">界面跳转</button>
        <button @click="goBack">后退</button>
    </div>
</template>

<script>
export default {
    methods:{
        goBack(){
            // 正数 前进    0 刷新界面     负数 后退
            this.$router.go(-1)    
        },
        goHome(){
            // 编程时导航
            // 方法一
            // this.$router.push('/')
            // 方法二
            this.$router.push({
                path:'/'
            })
            // 方法三
            // this.$router.push({
            //     name:'user',
            //     params:{id:2}
            // })
            // 方法四
            // this.$router.push({
            //     path:'/reg',
            //     query:{plan:'123'}
            // })
        }
    }
}
</script>

<style>

</style>
User.vue

 

嵌套路由的使用

// 3.创建路由器对象
export default new VueRouter({
  mode:'history',   // history 模式,干净的网页地址
  routes:[
    {
      path:'/user:id',
      name:'user',
      component:()=>import('@/views/User'),
      // 路由组件传值
      // 方法一
      // props:true
      // 方法二
      props:(route)=>({
        id:route.params.id,
        title:route.query.title,
      }),
      children:[
        {
          path:'App1',
          component:()=>import('@/views/App1')
        },
        {
          path:'App2',
          component:()=>import('@/views/App2')
         },
     ]
    },
  ]
})
index.js
<template>
  <div id="app">
    <div id="nav">
      <!-- 声明式跳转 -->
      <router-link :to="{name:'user',params:{id:1}}">User_1</router-link> | 
      <router-link :to="{name:'user',params:{id:2}}">User_2</router-link> | 
      
      <!-- 路由嵌套 -->
      <router-link to='/user1/App1'>user_1/App1</router-link> | 
      <router-link to='/user2/App2'>user_2/App2</router-link> | 
    </div>
    <router-view/>
  </div>
</template>
App.vue
<template>
    <div>
        <h2>这个是 User {{ $route.params.id }}</h2>

        <!-- 子路由的文件出口 -->
        <router-view></router-view>
    </div>
</template>
User.vue

 

命名视图的使用

// 3.创建路由器对象
export default new VueRouter({
  mode:'history',   // history 模式,干净的网页地址
  routes:[
    {
      path:'/about',
      name:'about',
      // component:About
      // 设置命名视图
      components:{
        default:About,  // 默认的名字
        right:()=>import('@/views/right'),
        left:()=>import('@/views/left'),
      }    
    },
  ]
})
index.js
<template>
  <div id="app">
    <!-- 渲染 Home 的 -->
    <router-view/>
    <router-view name='right' class="right"></router-view>
    <router-view name='left' class="left"></router-view>
  </div>
</template>
App.vue

 

使用全局守卫做登录操作

// 1.导入
import Vue from 'vue'
import router from 'vue-router'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'

// 2.模块化机制 使用 Router
Vue.use(router)

// 3.创建路由器对象
export default new VueRouter({
  mode:'history',   // history 模式,干净的网页地址
  routes:[
    {
      path:'/note',
      name:'note',
      component:()=>import('@/views/Note')
    },
    {
      path:'/login',
      name:'login',
      component:()=>import('../views/Login')
    },
    {
      path:'*',
      component:()=>import('@/views/404')
    },
  ]
})
index.js
<template>
  <div id="app">
    <div id="nav">
      <!-- 声明式跳转 -->
      <router-link :to="{name:'home'}">Home</router-link> |
      <router-link :to="{name:'about'}">About</router-link> | 
      <router-link :to="{name:'note'}">我的笔记</router-link> | 
    </div>
  </div>
</template>
App.vue
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false


// 全局守卫
router.beforeEach((to,from,next)=>{
  // 判断用户是否访问了 note
  if(to.path === '/note'){
    const user = JSON.parse(localStorage.getItem('user'))
    if (user) {
      // 用户已登录
      next()
    }else{
      // 用户没有登录  跳转到登录界面
      next('/login')
    }
  }
  next()
})

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')
main.js
<template>
    <div>
        <h2>登录界面</h2>
        账号:<input type="text" v-model="user">
        密码:<input type="password" v-model="pawd">
        <input type="button" value='登录' @click="login">
    </div>
</template>

<script>
export default {
    data(){
        return{
            user:'',
            pawd:''
        }
    },
    methods:{
        login(){
            // 1.获取账号密码
            // 2.模拟后端交互
            setTimeout(() => {
                let data = {
                    user:this.user
                }
                // 保存用户名到本地
                localStorage.setItem('user',JSON.stringify(data));
                // 跳转到 note
                this.$router.push('/note')
            }, 1000);
        }
    }

}
</script>

<style>

</style>
Login.vue

 

组件内部的守卫的应用

// 1.导入
import Vue from 'vue'
import router from 'vue-router'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'

// 2.模块化机制 使用 Router
Vue.use(router)

// 3.创建路由器对象
export default new VueRouter({
  mode:'history',   // history 模式,干净的网页地址
  routes:[
    {
      path:'/edit',
      name:'edit',
      component:()=>import('../views/Edit')
    },
    {
      path:'*',
      component:()=>import('@/views/404')
    },
  ]
})
index.js
<template>
  <div id="app">
    <div id="nav">
      <router-link :to="{name:'edit'}">编辑</router-link> | 
    </div>
  </div>
</template>
App.vue
<template>
    <div>
        <textarea v-model="edit" id="" cols="30" rows="10"></textarea>
        <button @click='save'>保存</button>
        <ul>
            <li v-for="(item,index) in list" :key="index">
                <h4>{{ item.title }}</h4>
            </li>
        </ul>
    </div>
</template>

<script>
export default {
    data(){
        return{
            edit:'',
            list:[]
        }
    },
    methods:{
        save(){
            this.list.push({
                title:this.edit
            })
            // 清空文本框
            this.edit = '';
        }
    },
    // beforeRouteUpdate(to,from,next){
    //     // 组件重用时 这个方法才起作用
    //     next();
    // },
    beforeRouteLeave(to,from,next){
        if (this.edit) {
            alert('请保存后在离开')
            next(false)
        }else{
            next()
        }
    }
}
</script>

<style>

</style>
Edit.vue

 

路由meta元信息实现权限控制

// 3.创建路由器对象
export default new VueRouter({
  mode:'history',   // history 模式,干净的网页地址
  routes:[
    {
      path:'/page',
      name:'page',
      component:()=>import('@/views/Page'),
      meta:{
        // 加入到黑名单
        requireAuth:true
      }
    },
    {
      path:'/edit',
      name:'edit',
      component:()=>import('../views/Edit'),
      meta:{
        // 加入到黑名单
        requireAuth:true
      }
    },
    {
      path:'*',
      component:()=>import('@/views/404')
    },
  ]
})
index.js
<template>
    <div>
        <h2>登录界面</h2>
        账号:<input type="text" v-model="user">
        密码:<input type="password" v-model="pawd">
        <input type="button" value='登录' @click="login">
    </div>
</template>

<script>
export default {
    data(){
        return{
            user:'',
            pawd:''
        }
    },
    methods:{
        login(){
            // 1.获取账号密码
            // 2.模拟后端交互
            setTimeout(() => {
                let data = {
                    user:this.user
                }
                // 保存用户名到本地
                localStorage.setItem('user',JSON.stringify(data));
                // 跳转到 note
                this.$router.push({
                    path:this.$route.query.redirect
                })
            }, 1000);
        }
    }

}
</script>

<style>

</style>
Login.vue
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

// 全局守卫
router.beforeEach((to,from,next)=>{
  if(to.matched.some(record=>record.meta.requireAuth)){
    // 需要权限  在黑名单中
    if (!localStorage.getItem('user')) {
      next({
        path:'/login',
        query:{
          redirect:to.fullPath
        }
      })
    }else{
      next();
    }
  }
  // 在白名单中
  next();
})


new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')
main.js

 

路由组件内在什么时机获取数据

module.exports = {
    devServer:{
        before:(app,serve)=>{
            app.get('/api/post',(req,res)=>{
                res.json({
                    title:'vue-router 的数据获取',
                    body:'在导航完成之后获取数据'
                })
            })
        }
    }
}
vue.config.js 在根目录创建用于模拟数据
// 1.导入
import Vue from 'vue'
import router from 'vue-router'
import VueRouter from 'vue-router'

// 2.模块化机制 使用 Router
Vue.use(router)

// 3.创建路由器对象
export default new VueRouter({
  mode:'history',   // history 模式,干净的网页地址
  routes:[
   {
      path:'/post',
      name:'post',
      component:()=>import('../views/Post')
    },
    {
      path:'*',
      component:()=>import('@/views/404')
    },
  ]
})
index.js
<template>
  <div id="app">
    <div id="nav">
      <!-- 声明式跳转 -->
      <router-link :to="{name:'home'}">Home</router-link> |
      <router-link :to="{name:'about'}">About</router-link> | 
      <router-link :to="{name:'note'}">我的笔记</router-link> | 
      <router-link :to="{name:'edit'}">编辑</router-link> | 
      <router-link :to="{name:'post'}">Post</router-link> | 
    </div>
  </div>
</template>
App.vue
<template>
    <div class="post">
        <div v-if="loading" class="loading">Loading...</div>
        <div v-if="error" class="error">{{ error }}</div>
        <div v-if="post">
            <h2>标题:{{ post.title }}</h2>
            <h2>内容:{{ post.body }}</h2>
        </div>
    </div>
</template>

<script>
export default {
    data(){
        return{
            post:null,
            error:null,
            loading:false
        }
    },
    // 导航完成之后获取数据
    created(){
        console.log(this.$https)
        this.getPostData()
    },
    watch:{
        $route:"getPostData"
    },
    methods:{
        async getPostData(){
            try {
                this.loading = true
                const {data} = await this.$https.get('/api/post')
                this.loading = false
                this.post = data;
            } catch (error) {
                console.log(error);
                this.error = error.toString()
            }
        }
    }
}
</script>

<style>

</style>
Post.vue

 

 

posted @ 2020-08-19 13:05  亦双弓  阅读(109)  评论(0编辑  收藏  举报