• 前台项目第二天(7-10)


    路由元信息的使用场景(组件显示与隐藏)

    通过ui页面分析
    Footer组件 在Home Search显示Footer组件 而在登录 注册页面是隐藏的
    6 Footer组件显示与隐藏 v-if(操作dom节点 耗性能) 或v-show(样式控制) 需要的是布尔值 true和false
    ----可通过判断路由是哪个 是否显示与隐藏(不推荐 如果组件过多 此方法冗余)
    ----推荐 router插件提供的 meta配置项 也就是路由元信息

    const routes = [{
    //显示的为true 隐藏的为false
    meta:{show:true}
    },
     {
        path:'/search/:keyword',
        name:'search',
        component:Search,
        meta:{show:true},
         props:true,
      },
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在根组件App.vue中 所使用的Footer非路由组件 通过v-show=“$route.meta.show” 判断是否显示与隐藏

    8.路由传参

    8.1 路由的跳转 有几种方式
    ----声明式导航 router-link (务必有to属性) 往哪跳
    ----编程式导航 用的是组件实例的$router.push|replace方法 除了跳转 还可以收集数据 发请求 功能全
    8.2 路由传参 有几种方式
    ----params参数 属于路径当中的一部分 注意 在配置路由时 需要先占位
    ----query参数 不属于路径当中的一部分 类似于ajax中的queryString /home?k=v&k=v 不用占位
    ----(传参)使用场景 在home页 把收集到的 搜索关键字 跳转到搜索页并带给它 告诉是哪个关键字
    /components/Header/index.vue
    收集表单数据 搜索关键字 数据双向绑定 v-model
    自身数据存储

     data() {
        return {
          keyword:'',
        }
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    对应的input 数据绑定 v-model=‘keyword’

     <input type="text" id="autocomplete" class="input-error input-xxlarge" v-model="keyword"/>
    
    • 1

    对应回调中

        //尝试编程式导航 搜索页跳转的回调
        goSearch(){
          //路由传参 几种形式
          //第一种 字符串形式 params参数 路径的一部分 注意 配置路由时先占位 比如是abc此时 url中会出现关键字
          //query参数 是以?开头 k=v的形式 
          this.$router.push('/search/' + this.keyword + "?k=" +this.keyword.toUpperCase());
          //第二种 模板字符串
          this.$router.push(`/search/${this.keyword}?k=${this.keyword.toUpperCase()}`)
          //第三种 对象写法(较常用) 需在 router/index.js中 对应的配置项中 添加name属性 name:'search' 对象中使用name关键字 而不是path
          this.$router.push({name:'search',params:{abc:this.keyword},query:{k:this.keyword.toUpperCase()}})
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    9.路由传参相关面试题

    9.路由传参相关面试题
    ----9.1路由传参(对象写法) path是否可以结合params参数一起使用? 答:不能 如下编写 不能跳转并报错

    this.$router.push({path:'search',params:{abc:this.keyword},query:{k:this.keyword.toUpperCase()}})
    
    • 1

    **----9.2如何指定params参数可传可不传? 现在 路由已占位叫abc 如下编写 没有传params参数 路径会有问题
    //只有query参数 当前页的路径名也会丢失 如何指定可传 在占位后加一个? 理解为正则表达式的 0或1
    **

    this.$router.push({name:'search',query:{k:this.keyword }})
    
    • 1

    ----9.3params参数可以传递也可以不传递 但是 如果传递是空串 如何解决?
    问题1.路径依然是丢失当前字符

    **可解决 使用||undefined **

    this.$router.push({name:'search',params:{abc:''||undefined},query:{k:this.keyword.toUpperCase()})
    
    • 1

    ----9.4路由组件能不能传递props数据? 答 可以 (三种写法) 较少用 因为props通常在组件间通信使用
    第一种 布尔值写法 router/index.js props:true, 注意只有 带有params参数 的组件
    另外在 /Search/index.vue中 接收 props:[‘abc’],

    const routes = [{
    //显示的为true 隐藏的为false
    meta:{show:true} //路由元 控制footer组件是否显示
    },
     {
        path:'/search/:abc?',
        name:'search',
        component:Search,
        meta:{show:true},
        //----9.4路由组件能不能传递props数据?  可以
        // 第一种 布尔值写法 注意只有 params参数
        props:true,
        // 第二种 对象写法 可以额外的给路由组件传递props数据 当然 需要相应组件接收 以上都不常用
        // props:{a:1,b:2}
        // 函数写法  可以把params query参数 通过props传递给路由组件
        // props:($route)=>{
        //   return {abc:$route.params.abc,k:$route.query.k}
        // }
      },
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    9.5.编程式导航路由跳转到当前路由(参数不变) 多次执行会抛出NavigationDuplicated的警告?
    –声明式导航没有这类问题 因为 vue-router底层已处理
    –1.1.编程式导航会有这个问题 因为从3.5.3版本 vue-router 引入了 promise 有成功和失败回调
    –1.2.通过给push方法传递相应的成功 失败的回调函数 可以捕获到当前错误
    //重写 VueRouter.prototype 的 push|replace 方法可解决
    /router/index.js

    //先把VueRouter原型对象的push 先保存一份
    let originPush = VueRouter.prototype.push;
    //重写 VueRouter.prototype 的 push|replace 方法 
    //第一个参数 告诉原型对象的push方法 往哪跳转(传递哪些参数)
    VueRouter.prototype.push = function(location,resolve,reject){
      if(resolve && reject){
        //call || apply区别
        //相同点 都可以调用函数一次 并且可以篡改函数的上下文一次
        //不同点 call与apply传递参数不同 call传递参数用逗号隔开 而apply方法 传递数组
        originPush.call(this,location,resolve,reject);
      }else{
        originPush.call(this,location,()=>{},()=>{});
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.Home组件模块拆分
    ----先把静态页面完成
    ----拆分出静态组件
    ----获取服务器的数据动态展示
    3.三级联动组件完成
    ----由于三级联动 在Home Search Detail 都有使用 注册为全局组件 方便使用
    ----/pages/Home/TypeNav/index.vue 编写静态组件
    ----入口文件 main.js中 注册为全局组件
    ----先引入 import TypeNav from ‘@/pages/Home/TypeNav’
    ----再注册 Vue.component(TypeNav.name,TypeNav)
    ----/Home/index.vue 标签形式使用
    4.在/Home/下完成其余静态组件
    Html + CSS + 图片资源
    5.POSTMAN测试接口
    POSTMAN测试接口工具的使用
    ----返回的是code=200 代表成功 反之失败
    ----整个项目 接口前缀都有/api字样
    6.axios 二次封装 其他方式 XMLHttpRequest | fetch | JQ axios src/api/index.js
    ----6.1 二次封装原因?
    ------请求拦截器 响应拦截器
    ------请求拦截器:可在发请求之前处理一些业务
    ------响应拦截器:当服务器返回数据以后 可以处理一些业务
    ----6.2在项目中经常出现api文件夹(请求相关)
    ----6.3 src/api/index.js

    //引入axios库
    import axios from "axios";
     //request接收axios实例 进行配置
     const requests = axios.create({
        //配置对象 基本路径 发请求时 路径当中会出现api
        baseURL:"/api",
        timeout:5000,
     });
     //请求拦截器:在发请求之前 拦截器可以监测到 发出去之前做一些业务
     requests.interceptors.request.use((config)=>{
        //config:配置对象参数 里面有一个属性很重要,headers请求头  
        return config;
     });
     //响应拦截器:服务器相应数据返回后 拦截器可以监测到 可以做一些业务
     requests.interceptors.response.use((res)=>{
        return res.data;
     },(error)=>{
        return Promise.reject(new Error('faile'))
     })
    //对外暴露
    export default requests;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    ----场景一 项目很小 接口就几个 完全可以在组件的生命周期函数中发请求
    ----项目复杂 接口多 有的接口在不同组件都有使用 后期接口一旦变化 使用过这个接口的都需改 所以统一管理较方便
    7.接口统一管理
    /api/+index.js 此文件引入封装好的axios 调用requests 可以发起各个接口请求
    ----7.1跨域问题
    ----协议 域名 端口号 不同 配置代理跨域方案
    ----/src/vue.config.js中配置

      devServer:{
        proxy:{
          '/api':{
            target:'url',
            // pathRewrite:{'^/api':''},//路径重写
          }
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    //切记配置文件修改之后 项目需要重新启动
    8.请求进度条 nprogress插件的使用
    ----8.1 项目安装nprogress插件
    cnpm i --save nprogress
    /api/index.js 引入模块和对应的样式
    import nprogress from ‘nprogress’;
    9.vuex状态管理库
    ----9.1 它是什么 作用?
    ----首先 它是官方提供的一个插件 状态管理库 集中式管理项目中组件共用的数据
    ----场景 项目复杂 组件多 数据维护繁琐
    ----几大核心
    state
    mutations
    actions
    getters
    modules
    ----既然是为解决管理各个组件的数据的插件 模块化优势支持
    ----既然是插件了 首先项目中安装
    cnpm i --save vuex@3.6.2
    ----9.2vuex基本使用
    /src/+store/+index.js
    ----引入 import Vue from “vue”
    -----import Vuex from “vuex”;
    //先use一次 Vuex的Store方法 是一个构造函数可以去初始化仓库
    Vue.use(Vuex)
    //state:仓库存储数据的地方
    const state = {};
    //mutations:修改state的唯一手段
    const mutations = {};
    //actions:处理actions 可以书写业务逻辑 处理异步
    const actions = {};
    //getters:理解计算属性 简化仓库数据 让组件获取仓库的数据更加方便
    const getter = {};
    //对外暴露Stroe类的一个实例
    //此种方式是都放在一个仓库(不推荐)
    export default new Vuex.Store({
    state,
    mutations,
    actions,
    getters,
    })
    ----9.3vuex实现模块化开发方式
    ----把一个仓库 拆分成若干小仓库 对应若干组件 这样仓库存储的是 对应组件的数据 新建对应的模块文件 例如
    store/+home/+index.js

    const state = {};
    const mutations = {};
    const actions = {};
    const getters = {};
    export default{
        state,
        mutations,
        actions,
        getters,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在/store/index.js //分别引入小仓库

    import home from './home';
    import search from './search';
    //对外暴露Stroe类的一个实例
    export default new Vuex.Store({
        //模块式开发方式存储
        modules: {
            home,
            search,
        }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    10.完成TypeNav三级联动展示数据业务
    ----全局组件TypeNav放在components文件中
    ----10.1对应组件派发actions 通知vuex调用api发请求
    /TypeNav/index.vue 派发actions

     //挂载生命周期函数 
      mounted() {
        //通知Vuex发请求 获取数据 存储于仓库中
        this.$store.dispatch('categoryList');
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    /store/home/index.js 处理actions 进行三连环 拿到数据 修改state 存数据

    //home模块的小仓库
    //引入封装好的请求文件
    import { reqCategoryList } from "@/api";
    
    //state:仓库存储数据的地方
    const state = {
        //state中默认数据初始值类型是根据服务器返回的类型决定的 
        categoryList:[],
    };
    //mutations:修改state的唯一手段
    const mutations = {
        CATEGORYLIST(state,categoryList){
            state.categoryList = categoryList;
        }
    };
    //actions:处理actions 可以书写业务逻辑 处理异步
    const actions = {
        //通过API里面的接口函数调用 向服务器发请求 获取服务器数据
        async categoryList({commit}){
            let result = await reqCategoryList();
            // console.log(result);// Promise
            if(result.code == 200){
                commit('CATEGORYLIST',result.data)
            }
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    commit提交mutations存数据 此时注意 提交 两个参数 第一个参数 提交的名字 第二个 提交的数据
    ----接下来就是组件拿到仓库的数据 展示即可
    ----使用mapState辅助函数 映射为组件身上的一个属性 (如果不是简写形式 务必要有 return)
    /TypeNav/index.vue 展示 引入辅助函数mapstate

    import { mapState } from 'vuex';
    computed: {
        ...mapState({
          //右侧需要的是一个函数
          categoryList:(state) => {
            // console.log(state);
           return state.home.categoryList;
          }
        })
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    对应标签使用v-for指令 渲染数据

     <div class="item" v-for="(c1,index) in categoryList" :key="c1.categoryId">
                <h3>
                  <a href="">{{c1.categoryName}}a>
                h3>
                <div class="item-list clearfix">
                  <div class="subitem" v-for="(c2,index) in c1.categoryChild" :key="c2.categoryId">
                    <dl class="fore">
                      <dt>
                        <a href="">{{c2.categoryName}}a>
                      dt>
                      <dd>
                        <em v-for="(c3,index) in c2.categoryChild" :key="c3.categoryId">
                          <a href="">{{c3.categoryName}}a>
                        em>
                      dd>
                    dl>
                  div>
                div>
              div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    AWS DAS认证考点整理(Kinesis篇)
    【APUE】文件系统 — 进程环境
    基于springboot实现问卷调查系统项目【项目源码+论文说明】计算机毕业设计
    python接口自动化测试 | yaml数据驱动参数化,看完这一篇就够了
    Map和Set【OJ练习题】
    基于51单片机推箱子小游戏Proteus仿真
    Mac 远程桌面软件
    全国职业技能大赛云计算--高职组赛题卷①(私有云)
    JUC学习笔记——共享模型之不可变
    分布式存储系统之Ceph基础
  • 原文地址:https://blog.csdn.net/weixin_44423378/article/details/125612555