vue2项目

这个是因为飞书文档无法满足笔记需求,想到写博客记录笔记,前面的笔记看情况决定是不是补上
部分内容参考博主毛毛虫呜呜的笔记

git地址

https://gitee.com/juneathena/vue

路由传参

路由跳转方式:
声明式导航:router-link,必须要加to:<router-link to="home">Home</router-link>
编程式导航:利用组件实例对象的$router.push/replace方法,跳转之前可以书写一下自己的 业务。

query、params两个属性可以传递参数:
query参数:不属于路径当中的一部分,类似于get请求,地址栏表现为 /search?k1=v1&k2=v2
query参数对应的路由信息 path: "/search"
params参数:属于路径当中的一部分,需要注意,在配置路由的时候,需要占位 ,地址栏表现为 /search/v1/v2
params参数对应的路由信息要修改为path: "/search/:keyword"这里的/:keyword就是一个params参数的占位符

路由传参:
1、字符串形式

this.$router.push("/search/" + this.keyWord + "?k=" + this.keyWord.toUpperCase());

2、模板字符串

this.$router.push(`/search/${
     this.keyWord}?k=${
     this.keyWord.toUpperCase()}`)

3、对象写法

this.$router.push({
   name: "search", params: {
   keyWord: this.keyWord}, query: {
   k: this.keyWord.toUpperCase()}})

路由常问问题

Q:路由传递参数(对象写法)path是否可以结合params参数一起使用?
    A:不可以,路由跳转传参的时候,对象的写法可以是name、path形式,但是需要注意的是,path这种写法不能与params参数一起使用

Q:如何指定params可传可不传?
    A: 1. 在配置路由的时候,在配置后面加一个问号 path: "/search/:keyWord?"

Q:params参数可以传递也可不传递,但是如果传递空串,如何解决?
    A: 使用undefined解决

Q:路由组件能不能传递props数据?
    A: 可以,三种写法:
       1. 布尔值写法:props: true
       2. 对象写法:props: {a:1, b:1}
       3. 函数写法:props:($router)=>{ return {keyword:$router.params.keyword, k:$router.query.k} }

二次封装axios

axios中文文档地址
Axios 是一个基于 promise 的 HTTP 库,vue比较适合Axios。
请求拦截器:可以在发送请求之前处理一些业务。
响应拦截器:可以在数据返回后处理一些事情。

// 对axios进行二次封装
import axios from "axios";

import nprogress from "nprogress";
import "nprogress/nprogress.css"

//1、利用axios对象的方法create去创建一个axios实例
const requests = axios.create({
   
	//配置对象
	
	// 基础路径,发请求的时候,路径中会出现/api
	baseURL: "/api",
	// 设置超时
	timeout: 5000,
});

// 请求拦截器:在发送请求之前,请求拦截器可以检测到,可以在发出请求之前处理一些业务
requests.interceptors.request.use((config) => {
   
	//config:配置对象,主要是对请求头headers配置
    //比如添加token

	// 进度条开始
	nprogress.start();

	return config;
})

// 响应拦截器
requests.interceptors.response.use((res) => {
   

	// 进度条结束
	nprogress.done();
	// 成功回调函数
	return res.data;
}, (error) => {
   
	//响应失败的回调函数
	return Promise.reject(new Error(error));
})

export default requests;  

通过配置代理解决跨域问题(前端)

通过配置代理,让请求都指向指定服务器

module.exports = {
   
  devServer: {
   
    proxy: {
   
      '/api': {
   
        target: '目标服务器',
      },
    }
  }
}

来自群内大佬讲解的代理
我们在发起请求的时候,如果不加请求的地址,浏览器会默认加上我们本机localhost地址,如果这样去发送请求,实际上,浏览器会默认请求,localhost:8080。跨域是受到浏览器同源策略影响,简单理解就是我们像服务端发送请求,其实别人数据给我们了,但是浏览器同源策略阻挡了服务端返回的数据,但是服务器与服务器之间是没有跨域问题的。他是通过创建一个我们本地的服务器,然后用我们本地的服务器去请求服务端服务器的内容,这样一来,我们本地服务器就能拿到服务端返回的内容了。然后我们再去拿到本地服务器的返回的数据,就把跨域问题处理了。在weback的devServe里面怎么处理的呢?他有一个配置项,叫proxy。处理跨域的核心配置就是 target,所以我们需要把需要代理的地址写上去,前提是给一个节点,这个节点就是,我在什么情况下才会去代理,所以我们需要写一个节点(上方代码里面的/api),当我80端口请求的接口中间有api的时候,webpack就知道我们需要代理了,然后80端口就会去请求target这个地址的内容。

webpack/devServer中文文档
个人理解:

proxy: {
   
  // 一旦代理服务器devServer服务器接收到 /api/xxx 的请求,就会把请求转发到远端服务器服务器(3000)
  // 浏览器和服务器之间有跨域,但是服务器和服务器之间没有跨域
  '/api': {
   
    target: 'http://localhost:3000',
    // 重写的路径是发送到远端服务的路径
    // 发送请求时,请求路径重写:将 /api/todo--> /test/todo(/api重写成/test)
    // http://localhost:3000/api/todo -> http://localhost:3000/test/todo
    pathRewrite: {
   
      '^/api': '/test'
    }
  }
}

loadsh插件防抖和节流

在快速划过三级导航或者搜索框输入搜索文字的时候,如果事件处理函数调用的频率无限制,会造成浏览器卡顿。因此会采用节流(throttle)防抖(debounce)

节流:在规定的时间间隔范围内不会重复触发函数的回调,只有大于这个时间间隔才会触发回调,把频繁变为少量触发
防抖:前面的所有触发都被取消,最后一次执行在规定时间之后才会触发,也就是说如果连续快速触发,只会执行一次
该项目采用第三方库实现节流:

// 按需引入throttle
import {
    throttle } from 'lodash/throttle.js'

 methods: {
   
    //采用键值对形式创建函数
    changeIndex: throttle(function (index){
   
      this.currentIndex = index
    },100),
  }

编程式导航

需要实现的部分的截图:(功能:点击菜单跳转链接,url带上参数)
在这里插入图片描述
实现路由跳转有两种方式:
声明式导航:router-link
编程式导航:push|replace

对于导航式路由,我们有多少个a标签就会循环出多少个router-link标签,这样当我们频繁操作时浏览器会出现卡顿现象。
对于编程式路由,我们是通过触发点击事件实现路由跳转。同理有多少个a标签就会有多少个触发函数。虽然不会出现卡顿,但是也会影响性能。
最好的解决方案就是:编程时导航+事件委派。事件委派就是把子节点的触发时间都委派给父节点,这样就可以只调用一次回调函数goSearch

利用事件委派也存在一些问题:
(1)把全部的子节点【h3、dt、dl、em】的事件都委派给了父亲节点,如何确定点击的一定是a标签?
(2)如何确定区分是一级还是二、三级的标签(一、二、三级分类产品的名字、id需要在url中传递)

解决方案:
(1)给三个a标签添加自定义属性:data-categoryName,只有这三个a标签拥有,其他子节点没有.
(2)添加自定义属性:data-category1Id:data-category2Id:data-category3Id来获取三个不同级别的a标签内的id来实现跳转。
(*)可以使用event来获取当前点击事件,通过event.target属性获取当前点击节点,再通过dataset属性获取节点的属性信息。

        <!--3级联动-->
        <div class="sort">
          <div class="all-sort-list2" @click="goSearch">
            <!--1级分类-->
            <div class="item" v-for="(c1, index) in categoryList" :key="c1.categoryId" :class="{ cur: currentIndex == index }">
              <h3 @mouseenter="changeIndex(index)">
                <a :data-categoryName="c1.categoryName" :data-category1Id="c1.categoryId">{
  { c1.categoryName }}</a>
              </h3>
              <!--2、3级分类-->
              <div class="item-list clearfix" :style="{
       display:currentIndex == index?'block':'none' }">
                <div class="subitem" v-for="c2 in c1.categoryChild" :key="c2.categoryId">
                  <dl class="fore">
                    <dt>
                      <a :data-categoryName="c2.categoryName" :data-category2Id="c2.categoryId">{
  { c2.categoryName }}</a>
                    </dt>
                    <dd>
                      <em v-for="c3 in c2.categoryChild" :key="c3.categoryId">
                        <a :data-categoryName="c3.categoryName" :data-category3Id="c3.categoryId">{
  { c3.categoryName }}</a>
                      </em>
                    </dd>
                  </dl>
                </div>
              </div>
            </div>
          </div>

节点中有一个属性dataset属性可以获取当前节点的自定义属性与属性值

goSearch函数代码:

    goSearch(event) {
   
      let element = event.target;
      /**
       * html中会把大写转为小写
       * categoryname:a标签
       * category1id:一级类目id
       * category2id:二级类目id
       * category3id:三级类目id
       */
      //节点中有一个属性dataset(火狐、谷歌支持),可以获取节点的自定义属性与属性值
      let {
   categoryname,category1id,category2id,category3id} = element.dataset;
      if (categoryname) {
   
        // 整理路由跳转的参数
        let location = {
   name:'search'};
        let query = {
   categoryName:categoryname};
        // 一、二、三级
        if (category1id) {
   
          query.category1Id = category1id;
        } else if (category2id){
   
          query.category2Id = category2id;
        } else {
   
          query.category3Id = category3id;
        }
        // 完整参数
        location.query = query;
        // 路由跳转
        this.$router.push(location);
      }
    },
  },

Vue路由组件销毁优化

Vue在路由切换的时候会销毁旧路由。
我们在三级列表全局组件TypeNav中的mounted进行了请求一次商品分类列表数据。
由于Vue在路由切换的时候会销毁旧路由,当我们再次使用三级列表全局组件时还会发一次请求。
如下图所示:当我们在包含三级列表全局组件的不同组件之间进行切换时,都会进行一次信息请求。

在这里插入图片描述
每次请求的内容都是一样的,处于性能的考虑,想要只请求一次。所以我们把这次请求放在App.vue的mounted中。(根组件App.vue的mounted只会执行一次
注意:虽然main.js也是只执行一次,但是不可以放在main.js中,main.js不是组件。只有组件的身上才会有$store属性。

合并参数

合并路由中的参数:如果跳转路由的时候带有params参数,需要一起传递过去
TypeNav.vue的goSearch方法:

        // 如果跳转路由的时候带有params参数,需要一起传递过去
        if (this.$route.params) {
   
          // 给location添加一个params参数
          location.params = this.$route.params;
          location.query = query;
          // 跳转
          this.$router.push(location);
          console.log(location)
        }

Header.vue的goSearch方法:

    goSearch() {
   
      let location = {
    name: "search", params: {
    keyword: this.keyWord || undefined },};
      if (this.$route.query) {
   
        location.query = this.$route.query;
      }
      this.$router.push(location);
    },

mock.js模拟数据

服务器返回的数据只有商品分类,对于轮播图(ListContainer)组件和推荐商品(Floor)组件数据服务器没有提供。前端mock的数据不会和服务器进行任何通信
mock.js生成随机数组,拦截ajax请求。

使用步骤:
1、在src目录下创建一个mock文件夹
2、准备需要的json数据
3、把mock需要的图片放到public文件中
4、开始mock虚拟数据,通过mock.js模块
5、mockServe.js文件在入口文件引入(至少需要执行一次,才能模拟数据)
mock文件夹
mockServe.js

// 引入mockjs模块
import Mock from 'mockjs';
// 引入准备好的json数据
import banner from './banner.json';
import floor from './floor.json';

// mock数据:第一个参数请求地址,第二个参数请求数据
Mock.mock("/mock/banner", {
   code:200, date:banner});
Mock.mock("mock/floor", {
   code:200, data:floor});

需要在入口文件main.js中引入mockServe.js

import "@/mock/mockServe"

webpack默认对外暴露的:图片、JSON数据;

通过Vuex来实现数据存储与管理(复习,上面用过)

我们会把公共的数据放在store中,然后使用时再去store中取。
以我们的首页轮播图数据为例。
1、在轮播图组件ListContainer.vue组件加载完毕后发起轮播图数据请求。

  mounted() {
   
    // 派发action,通过Vuex像Ajax发起请求
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值