前台项目第二天(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,
  },
]

在根组件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:'',
    }
  },

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

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

对应回调中

    //尝试编程式导航 搜索页跳转的回调
    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()}})
    }

9.路由传参相关面试题

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

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

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

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

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

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

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

----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}
    // }
  },
]

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,()=>{},()=>{});
  }
}

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;

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

  devServer:{
    proxy:{
      '/api':{
        target:'url',
        // pathRewrite:{'^/api':''},//路径重写
      }
    }
  }

//切记配置文件修改之后 项目需要重新启动
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,
}

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

import home from './home';
import search from './search';
//对外暴露Stroe类的一个实例
export default new Vuex.Store({
    //模块式开发方式存储
    modules: {
        home,
        search,
    }
})

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

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

/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)
        }
    }
};

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

import { mapState } from 'vuex';
computed: {
    ...mapState({
      //右侧需要的是一个函数
      categoryList:(state) => {
        // console.log(state);
       return state.home.categoryList;
      }
    })
  }

对应标签使用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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值