• Vue 嵌套路由 路由导航守卫 页面滚动处理 axios axios拦截器 全局配置 all方法


    vue-day07

    1-路由

    1.1-嵌套路由

    • 定义路由规则

      /router/index.js

      const routes=[
          // 嵌套路由
          // 父路由
          {
              path:'/login',
              component:Login,
              meta:{
                  title:'登录页面'
              },
              // 子路由
              children:[
                  {
                      path:'/login/user',
                      component:User,
                      meta:{
                          title:'普通用户登录页面'
                      }
                  },
                  {
                      path:'/login/enterprise',
                      component:Enterprise,
                      meta:{
                          title:'企业用户登录页面'
                      }
                  }
              ]
          }
      ]
      
    • 添加二级路由出口(在一级路由组件中添加)

      pages/Login.vue

      <template>
        <div>
          <h1>登录页面</h1>
          <router-link class="nav-btn" to="/login/user">普通用户</router-link>
          <router-link class="nav-btn" to="/login/enterprise">企业用户</router-link>
          <hr>
          <!-- 二级路由出口(二级路由占位符) -->
          <router-view></router-view>
        </div>
      </template>
      
      <script>
      export default {
        created() {
          // 通过操作真实dom, 实现更新页面标题
          document.title = this.$route.meta.title;
        }
      };
      </script>
      <style>
      </style>
      

    1.2-路由导航守卫

    1.2.1-全局守卫

    • 全局前置守卫

      • 执行时机: 页面跳转之前, 被触发
      • 特点: 具备拦截页面跳转的功能
      // 添加全局前置守卫
      router.beforeEach((to,from,next)=>{
          // 动态设置页面标题
          document.title=to.meta.title;    
          // console.log(to,from);
          // to: 即将前往的页面路由对象
          // from: 即将离开的页面路由对象
          // next: 方法, 可以实现页面跳转, 默认必须调用一次next
          // 放行本次路由跳转
          next();
      });
      
    • 全局解析守卫(2.5.0版本之后新增)

      • 执行时机: 页面跳转之前, 全局前置钩子beforeEach执行之后, 被触发
      • 特点: 不具备拦截页面跳转的功能
      router.beforeResolve ((to,from,next)=>{
          // console.log(to,from);
          // to: 即将前往的页面路由对象
          // from: 即将离开的页面路由对象
          // next: 方法, 可以实现页面跳转, 默认必须调用一次next
          // 放行本次路由跳转
          next();
      });
      
    • 全局后置钩子

      • 执行时机: 页面跳转完成之后, 被触发
      • 特点: 不具备拦截页面跳转的功能
      // 全局后置钩子
      router.afterEach((to, from) => {
        // 动态设置页面标题
        document.title = to.meta.title;
        // to:即将前往的页面路由对象
        // from: 即将离开的页面路由对象
        console.log('afterEach');
      });
      

    1.2.2-路由独享守卫

    • 特点: 具备拦截页面跳转的功能
    • 执行时机: 在页面跳转之前, 全局前置守卫beforeEach执行之后, 自动触发
    • 生效范围: 只对当前路由对象对应的页面跳转起作用
    const routes = [
        {
            path: '/',
            component: Home,
            meta: {
              title: '网站首页'
            },
            // 路由独享守卫: 全局前置守卫执行之后, 被触发
            beforeEnter(to,from,next){
                // to: 即将前往的页面路由对象
                // from: 即将离开的页面路由对象
                // next: 方法, 可以实现页面跳转, 默认必须调用一次next
                // console.log('beforeEnter');
                // 默认情况下, next方法必须调用
                next();
            }
          }
    ]
    

    1.2.3-组件内的守卫

    1.2.3.1-特点
    • 具备拦截页面跳转的功能, 所以如果显示声明了组件内的导航守卫钩子, 一定要手动调用next方法, 否则页面无法正常显示
    1.2.3.2-钩子函数
    • beforeRouteEnter
      • 执行时机: 路由组件被渲染之前
      • 注意: 不能使用this关键字获取组件实例对象
    • beforeRouteUpdate
      • 执行时机: 动态路由对应的组件, 由于动态参数发生改变被重复渲染的时候, 自动触发
    • beforeRouteLeave
      • 执行时机: 导航离开该组件的对应路由时调用
    export default{
          beforeRouteEnter (to, from, next) {
            // 在渲染该组件的对应路由被 confirm 前调用
            // 不!能!获取组件实例 `this`
            // 因为当守卫执行前,组件实例还没被创建
              next(vm=>{
                  // 通过vm获取组件实例对象
                  console.log(vm);
              })
          },
          beforeRouteUpdate (to, from, next) {
            // 在当前路由改变,但是该组件被复用时调用
            // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
            // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
            // 可以访问组件实例 `this`
              next();
          },
          beforeRouteLeave (to, from, next) {
            // 导航离开该组件的对应路由时调用
            // 可以访问组件实例 `this`
            next();
          }
    }
    

    1.3-页面滚动处理

    // 4-创建路由实例
    const router = new Router({
      // 路由规则数组
      routes,
      // 指定路由模式
      mode: 'hash',
      // 自定义路由导航链接高亮类名
      linkActiveClass: 'active',
      // 控制组件页面滚动条的位置   
      scrollBehavior(){
          return {x:0,y:100}
      }
    });
    

    1.4-404路由

    const routes=[
         // 404路由
      {
        path:'*',
        component:NotFound,
        meta: {
          title: '404页面'
        }
      }
    ]
    

    1.5-使用嵌套路由改造后台管理系统

    • 路由文件

      router/index.js

      // 1-导入路由模块
      import Vue from 'vue'
      import VueRouter from 'vue-router';
      
      // 2-注册插件
      Vue.use(VueRouter);
      
      // 3-创建路由规则
      // 导入页面组件
      import Main from '../pages/Main';
      import Goods from '../pages/Goods';
      import Order from '../pages/Order';
      import User from '../pages/User';
      import Layout from '../pages/Layout';
      
      
      const routes = [{
        path: '/',
        component: Layout,
        children: [{
            path: '/main',
            component: Main,
            meta: {
              title: '管理中心'
            }
          },
          {
            path: '/goods',
            component: Goods,
            meta: {
              title: '商品管理'
            }
          },
          {
            path: '/user',
            component: User,
            meta: {
              title: '会员管理'
            }
          },
          {
            path: '/order',
            component: Order,
            meta: {
              title: '订单中心'
            }
          }
        ]
      }];
      
      // 4-创建路由对象
      const router = new VueRouter({
        routes,
        mode: 'hash',
        linkActiveClass: 'active'
      });
      
      // 5-导出路由实例对象
      export default router;
      
      
    • 根组件

      App.vue

      <template>
        <div>
          <!-- 一级:路由出口 -->
          <router-view></router-view>
        </div>
      </template>
      
      <script>
      export default {
      };
      </script>
      
      <style>
      
      </style>
      
    • 布局组件

      Layout.vue

      <template>
        <div class="container">
          <div class="left">
            <ul class="navbar">
              <!-- 启用路由严格匹配模式 -->
              <router-link tag="li" to="/main">管理中心</router-link> 
              <router-link tag="li" to="/goods">商品管理</router-link> 
              <router-link tag="li" to="/user">会员管理</router-link> 
              <router-link tag="li" to="/order">订单管理</router-link> 
            </ul>
          </div>
          <div class="right">
            <!-- 头部 -->
            <Header></Header>
            <div class="content">
              <!-- 二级路由占位符 -->
              <router-view></router-view>
            </div>
            <!-- 底部 -->
            <Footer />
          </div>
        </div>
      </template>
      
      <script>
      // 1-导入页组件
      // 导入功能组件
      import Header from "../components/Header";
      import Footer from "../components/Footer";
      
      export default {
        // 2-注册组件
        components: {
          Header,
          Footer
        },
        data() {
          return {
            // 页面组件名称
            page: "Order"
          };
        },
        methods: {
          // 切换页面
          changePage(page) {
            this.page = page;
          }
        }
      };
      </script>
      
      <style>
      *{
        padding: 0;
        margin: 0;
        box-sizing: border-box;
      }
      .container {
        background-color: #ddd;
        /* vh:相对单位; 100vh=屏幕的高度  1vh==1/100屏幕高度; viewport height */
        height: 100vh;
        display: flex;
      }
      /* 左侧导航栏 */
      .container .left {
         226px;
        background: #00152a;
      }
      .left .navbar li {
        list-style: none;
        line-height: 50px;
        color: #fff;
        text-align: center;
        cursor: pointer;
      }
      .left .navbar li:hover {
        background: #0077b8;
      }
      .left .navbar li.active {
        background: #0077b8;
      }
      
      .container .right {
        flex: 1;
        display: flex;
        flex-direction: column;
      }
      .right .header {
        height: 60px;
        line-height: 60px;
        text-align: center;
        background: #fff;
      }
      .right .content {
        margin: 10px;
        background: #fff;
        height: 300px;
        text-align: center;
        flex: 1;
      }
      .right .footer {
        line-height: 60px;
        text-align: center;
        background: #fff;
      }
      </style>
      

    2-axios

    2.0-原生js发送ajax请求的步骤

    • 创建一个XMLHttpRequest对象

      const xhr=new XMLHttpRequest();
      
    • 设置请求行

      xhr.open('请求方式GET/POST','数据接口地址');
      
    • 发送请求

      xhr.send();
      
    • 监听服务器的响应

      xhr.onreadystatechange=function(){
          if(xhr.readyState===4&&xhr.status==200){
          	console.log('请求被响应',xhr.responseText);   	
          	console.log('请求被响应',xhr.responseXML,);   	
          }
      }
      

    2.1-axios的介绍

    • axios是基于ES6中promise的一个第三方的http类库

    2.1.1-安装

    npm i axios -S
    

    2.2-axios发送数据请求

    2.2.1-get请求

    import axios from 'axios';
    axios({
        // 指定数据接口
        url:'',
        // 指定数数据提交方式为GET
        method:'GET',
        // get请求的参数
        params:{
            
        }
    }).then(res=>{
        console.log(res);
    })
    
    // 专门用来发送get请求的方法
    axios.get('接口地址',{
        // get请求的参数
        params:{
            
        }
    }).then(res=>{
        // 成功处理函数
    })
    

    2.2.1-post请求

    import axios from 'axios';
    axios({
        // 指定数据接口
        url:'',
        // 指定数数据提交方式为GET
        method:'POST',
        // POST请求的参数
        data:{
            
        }
    }).then(res=>{
        console.log(res);
    })
    
    // 专门用来发送post请求的方法
    axios.post('接口地址',{
        // 直接书写请求体: 需要提交给数据接口的参数
        name:'',
        age:''
    }).then(res=>{
        // 成功处理函数
    })
    

    2.3-拦截器

    2.3.1-请求拦截器

    // 请求拦截器
    // req: 系统自动注入, 包含了和请求相关的一些数据对象
    axios.interceptors.request.use(function(req){
        // console.log(req,'interceptors.request');
        // console.log(req.headers);
        // 添加自定义请求头
        req.headers.token='12345678';
        // 一定要有返回值
        return req;    
    });
    

    2.3.2-响应拦截器

    //  响应拦截器
    // response: 系统自动注入的参数, 包含和响应相关的数据对象
    axios.interceptors.response.use(function(response){
        // console.log(response,'interceptors.response');
        // response.data是服务端返回的真实数据
        return response.data;
    });
    

    2.4-axios的全局配置

    1. 全局配置基础域名(baseURL)

      axios.defaults.baseURL='http://localhost:3000/api';
      
    2. 配置请求头

      // 配置请求头
      axios.defaults.headers.auth='abc';
      

    2.5-axios.all()方法

    • 作用: 批量执行数据请求
    • 返回值: 数组
    • 参数: 数组
    export default {
         methods:{
            //  获取分类列表
            async getCates(){
             const res=await axios({
                url:'/getcate',
                method:'GET',
                params:{
                  name:'张三',
                  age:20
                }
              });
              return res.data;
            },
            // 获取轮播图数据
            async getBanners(){
              const res=await axios.get('/getbanner',{
                // get请求参数
                params:{
                  name:'lisi',
                  age:20
                }
              });
              return res.data;
            }
          },
      created(){
        // this.getCates();
        // this.getBanners();
        axios.all([this.getCates(),this.getBanners()]).then(res=>{
          // 数组的解构赋值
          const [cates,banners]=res;
          // 更新数据
          if(cates.code===200){
              this.cates=cates.list;
          }
          if(banners.code===200){
              this.banners=banners.list;
          }
        })
      
      },
    }
    

    2.6-axios.create()方法

    • 作用: 创建一个axios实例对象

      import axios from 'axios';
      const http=axios.create({
          // 配置基础域名
          baseURL:'http://localhost:3000/api',
          // 请求头: 系统, 自定义
          headers:{
              token:'123456789'
          }
      });
      
      // 请求拦截器
      // req: 系统自动注入, 包含了和请求相关的一些数据对象
      http.interceptors.request.use(function(req){
          // console.log(req,'interceptors.request');
          // console.log(req.headers);
          // 添加自定义请求头
          req.headers.token='12345678';
          // 一定要有返回值
          return req;    
      });
      
      //  响应拦截器
      // response: 系统自动注入的参数, 包含和响应相关的数据对象
      http.interceptors.response.use(function(response){
          // console.log(response,'interceptors.response');
          // response.data是服务端返回的真实数据
          return response.data;
      });
      export default http; 
      

    3-测试数据接口服务器的搭建

    1. 下载数据接口源代码shop-api-数据接口服务器.zip

    2. 解压

    3. 安装依赖: 进入数据接口项目根目录, 执行如下命令行

      npm i 
      
    4. 导入数据库备份文件

    5. 修改项目配置文件(主要修改数据库配置信息), 打开/config/global.js, 做如下修改

      exports.dbConfig = {
          host: 'localhost', //数据库地址
          user: 'root',//数据库用户名
          password: 'root',//数据库用户密码
          port: 3306,
          database: 'shop_db' // 数据库名字
      }
      
    6. 启动数据接口服务器

      npm run start
      // 或者(如果没有安装nodemon工具,使用如下命令启动)
      node ./bin/www
      
    7. 通过浏览器访问http://localhost:3000, 如果能正常响应, 说明数据接口服务器启动成功

    axios案例模板所需依赖项

    • bootstrap: 第三方的css演示库, 主要提供了一些css类选择器, 可以快速对页面进行美化
    • swiper: 一个第三方的轮播图插件
    npm i swiper@3.4.2 bootstrap@3.3.7 -S
    

    4-token

    • token: 服务端返回的一个随机字符串, 包含了一些登录用户的信息, 后端程序可对其进行解密操作
    • 作用: 登录凭证, 请求需要登录认证的数据接口的时候, 需要将其发送给数据接口进行登录认证

    5-参考文档

  • 相关阅读:
    App唤起微信小程序和回调
    微信小程序 — 自定义picker选择器弹窗内容+textarea穿透bug
    微信小程序的场景值scene
    微信小程序textarea层级过高(盖住其他元素)
    微信小程序如何修改本地缓存key中的单个数据
    微信小程序---查看更多的显示与隐藏
    微信小程序文字超过行后隐藏并且显示省略号
    Flutter 页面下拉刷新和上拉加载
    json转换成dart类 JSON to Dart
    Flutter 保持页面状态
  • 原文地址:https://www.cnblogs.com/bnzw/p/14032575.html
Copyright © 2020-2023  润新知