v-router重写push、replace方法

问题描述:当页面再次进入同一个路由地址时,控制台报错
在这里插入图片描述
解决方法:修改vue-router的配置文件,也就是router/index.js文件

//重写VueRouter.prototype身上的push方法了
VueRouter.prototype.push = function(location, resolve, reject) {
  //第一个形参:路由跳转的配置对象(query|params)
  //第二个参数:undefined|箭头函数(成功的回调)
  //第三个参数:undefined|箭头函数(失败的回调)
  if (resolve && reject) {
    //push方法传递第二个参数|第三个参数(箭头函数)
    //originPush:利用call修改上下文,变为(路由组件.$router)这个对象,第二参数:配置对象、第三、第四个参数:成功和失败回调函数
    originPush.call(this, location, resolve, reject);
  } else {
    //push方法没有产地第二个参数|第三个参数
    originPush.call(
      this,
      location,
      () => {},
      () => {}
    );
  }
};
//重写VueRouter.prototype身上的replace方法了
VueRouter.prototype.replace = function(location, resolve, reject) {
  if (resolve && reject) {
    originReplace.call(this, location, resolve, reject);
  } else {
    originReplace.call(
      this,
      location,
      () => {},
      () => {}
    );
  }
};

三级联动路由跳转的优化

三级联动路由如下图所示:
在这里插入图片描述
点击’电子书‘后跳转的页面如下:
在这里插入图片描述
问题分析:
1、由于三级分类都是<a>标签,所以要实现路由跳转,最简单的方式就是将a标签换成
<router-link to="/search">,但是由于服务器的数据返回,循环语句的执行,可能在一瞬间,要加载几千个router-link,router-link是组件,组件需要创建,所以很耗费内存,最终会出现卡顿现象。
2、所以采用编程式导航来实现,编程式导航需要绑定事件,如果将事件绑定在每个<a>标签上,虽然不会出现卡顿现象了,但是当数据返回时,每次循环会就会导致有几千个回调函数,所以可以利用事件委派解决这个问题。
3、最好的解决方案是编程式导航结合事件委派。但是利用事件委派存在两个问题需要解决:

    3.1、全部的子节点的事件都委派给了父节点,但是我们需要的是点击一定是a标签,如何区别a标签和其它标签?
        在a标签上定义自定义事件data-categoryName,后面用dataset就能获取自定义属性及属性值;
    3.2如何获取参数【1、2、3级分类的产品的名字、id】?
        在1,2,3级分类上定义自定义属性data-category1Id、data-category2Id、data-category3Id,就能区分了

三级联动TypeNav的代码如下:
template内

 <!-- 将点击事件goSearch放在父元素上 -->
                <div class="all-sort-list2" @click="goSearch">
                    <div class="item" v-for="(c1,index) in categoryList" :key = "c1.categoryId">
                        <h3>
                            <!-- 为了区别a标签和其它标签,在a标签上定义自定义事件data-categoryName,后面用dataset就能获取;1,2,3级区分同理 -->
                            <a :data-categoryName="c1.categoryName" :data-category1Id="c1.categoryId" >{{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 :data-categoryName="c2.categoryName" :data-category2Id="c2.categoryId" >{{c2.categoryName}}</a>
                                        <!-- 声明式导航 --!>
                                        <!-- <router-link to="/search">{{c2.categoryName}}</router-link> -->
                                    </dt>
                                    <dd>
                                        <em v-for="(c3,index) in c2.categoryChild" :key="c3.categoryId">
                                            <a :data-categoryName="c3.categoryName" :data-category2Id="c3.categoryId" >{{c3.categoryName}}</a>
                                        </em>
                                    </dd>
                                </dl>
                            </div>
                        </div>
                    </div>
                </div>

script内

 methods:{
      goSearch(event){
          //利用编程式导航和事件委派
          //事件委派会出现一些问题:1.全部的子节点的事件都委派给了父节点,但是我们需要的是点击一定是a标签
          let element = event.target;
          //dataset可以获取自定义属性与属性值(解构赋值)
          let {categoryname,category1id,category2id,category3id} = element.dataset;
          console.log(element.dataset)
        //   如果标签身上有categoryname那一定是a标签
          if(categoryname){
            //   alert(123);
              //整理路由跳转的参数
              let location = {name:"search"};
              let query = { categoryName:categoryname }
              // 2.如何获取参数【1、2、3级分类的产品的名字、id】
              if(category1id){
                  query.category1Id = category1id
              }else if(category2id){
                  query.category2Id = category2id
              }else{
                  query.category3Id = category3id
              }
              location.query = query;
              this.$router.push(location);
            //   alert(123)
          }
      },

跨域问题

/api/request.js
1、对axios进行二次封装

//对axios进行二次封装
import axios from "axios";
//引入进度条
import nprogress from "nprogress";
//引入进度条的样式
import "nprogress/nprogress.css"
console.log(nprogress);
//利用axios对象的方法create,创建一个axios实例
const requests = axios.create({
    baseURL:"/api",
    //请求超时时间为5s
    timeout:5000,
});

//请求拦截器:再发请求之前,请求拦截器可以监测到,可以在请求发出之前走一些事情
requests.interceptors.request.use((config)=>{
    //config:配置对象,对象里面有个属性很重要,headers请求头
    //进度条开始动
    nprogress.start();
    return config;
})
//响应拦截器
requests.interceptors.response.use((res)=>{
    //成功的回调函数:服务器响应数据回来以后,响应拦截器可以检测到,做一些事情
    //进度条结束
    nprogress.done();
    return res.data;     
},(error)=>{
    //响应失败的回调函数
    return Promise.reject(new Error('faile'));
})

//对外暴露
export default requests;

2、对接口进行统一管理
/api/index.js

//当前这个模块:对API进行统一管理
import requests from "./request";

//三级联动接口
// /api/product/getBaseCategoryList    get   无参数
export const reqCategoryList = ()=>{
    //发请求  axios发请求,返回结果是promise对象
    //会出现跨域问题:协议、域名、端口号不同就会出现跨域问题
    //http://39.98.123.211
    //http://localhost:8080
    //解决方法:JSONP、CROS、代理(在config.js配置文件修改)
    return requests({url:'/product/getBaseCategoryList',method:"get"})
}

解决跨域问题方法一:代理跨域
在服务器和浏览器中间设置一个代理服务器,解决跨域问题
vue.config.js

module.exports = {
    //关闭eslint校验工具
     lintOnSave:false,
     //代理跨域
     devServer:{
        proxy: {
            "/api": {
              target: "http://39.98.123.211",
              //路径不需要重写,因为所有的接口都有/api
            //   pathRewrite: {"^/api" : ""}
            },
          },
     },
     
} 

轮播图解决浏览器异步数据及swiper问题

问题分析:
swiper插件完成轮播图需要两件事:首先将DOM结构渲染完成,然后再创建一个swiper实例。
但是我们从浏览器获取数据是异步的(获取数据也在mounted中),所以不能保证创建swiper实例时(在mounted生命周期函数内创建这个实例)就将DOM结构完成了,要解决这个问题,有以下三种方法:

  • 1、update
    当有其他数据时,其它数据进行更新,但轮播图的数据不更新时,都会再创建一次swiper实例然后再创建轮播图,所以这个方法不是特别好。

  • 2、延时器
    延时1秒,轮播图的功能才可以实现,此方法可行但也不是很完美。

  • 3、watch+nextTick
    如果只有watch,只能保证bannerList数据已经存入到仓库里了,但是不能确定v-for执行完毕,v-for执行完了才能保证DOM结构完成,所以需要结合nextTick来完成。
    nextTick

Logo

前往低代码交流专区

更多推荐