IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 【开发小记】vue项目优化 -> 正文阅读

[JavaScript知识库]【开发小记】vue项目优化

今天从多个方面来记录一下自己项目中考虑过的优化方案

一、代码层面

首先从基本的代码层面来看,举个例子,比如我拿到了一个数组,需要对这个数组的内容做一些处理(比如需要对数组的内容遍历然后做一些处理等等),但是在当数组是空的时候就没有必要走下面的逻辑了。所以可以加一个判断语句,如果数组为空就不再进行后续的逻辑,这也可以减少很多代码的执行,从而提高性能。类似的还有很多,应该说是代码细节层面的一些优化了。

二、网络层面的优化

1、重复请求的取消:第一次请求还没回来之前就进行第二次同样的请求,这时候就应该把第二次请求给取消掉,防止重复请求
这里我们对axios请求进行了封装,采用了拦截器中进行了相应的处理。
在请求拦截器和响应拦截器之前,先实现了三个方法。
因为当请求方式,请求 URL和请求携带参数都一样时,就可以认为是相同的请求。因此在每次发起请求时,可以根据当前请求的请求方式、请求 URL地址和请求携带参数来生成一个唯一的 key;同时为每个请求创建一个专属的 CancelToken,然后将 key 和 Cancel 函数以键值对的形式保存到 Map对象中,使用 Map对象的好处是可以快速判断是否有重复的请求

// 用于根据当前请求的信息生成请求的key
  generateReqKey(config){
    const {method,url,params,data} = config;
    return [method,url,qs.stringify(params),qs.stringify(data)].join('&')
  }
  // 用于把当前请求信息添加到pendingRequest对象中去
  PendingRequest = new Map();
  addPendingRequest(config){
    const requestKey = this.generateReqKey(config);
    config.cancalToken = config.cancalToken || new axios.CancelToken((cancel)=>{
      if(!this.PendingRequest.has(requestKey)){
        this.PendingRequest.set(requestKey,cancel)
      }
    })
  }
  // 检查是否存在重复请求,若存在则需要取消已经发出的请求
  removeRequest(config){
    const requestKey = this.generateReqKey(config);
    if(this.PendingRequest.has(requestKey)){
      const CancelToken = this.PendingRequest.get(requestKey);
      CancelToken(requestKey);
      this.PendingRequest.delete(requestKey);
    }
  }

然后是配置拦截器
因为需要对所有的请求都进行处理,因此考虑使用 axios的拦截器机制来实现取消重复请求的功能。
axios的制作者为开发人员提供了请求拦截器和响应拦截器,各自的作用如下:
(1)请求拦截器:该类拦截器的作用是在请求发送前统一执行某些操作,比如在请求头中添加 token字段;
(2)响应拦截器:该类拦截器的作用是在接收到服务器响应后统一执行某些操作,比如根据不同的状态码来执行相对应的操作。

  interceptors(install) {
    install.interceptors.request.use(config => {
      // 检查是否存在重复请求
      this.removeRequest(config);
      // 把当前请求信息添加到pendingRequest对象中
      this.addPendingRequest(config);
      const token = localStorage.getItem('token');
      if (token) {
        config.headers.authorization = `token ${token}`;
      }

      return config
    }, err => {
      return Promise.reject(err)
    });

    install.interceptors.response.use(res => {
      // 从pendingRequest对象中移除请求
      this.removeRequest(res.config);
      const { data } = res;
      return data
    }, err => {
      // 从pendingRequest对象中移除请求
      this.removeRequest(err.config)
      return Promise.reject(err)
    });
  }

完整的网络请求封装代码如下:

import axios from 'axios';
// 引入qs库奖url中的参数转化为对象
import qs from "qs"

class HttpRequest {
  constructor(options) {
    this.defaults = {
      baseUrl: ''
    }

    this.defaults = { ...this.defaults, ...options }
  }
  // 用于根据当前请求的信息生成请求的key
  generateReqKey(config){
    const {method,url,params,data} = config;
    return [method,url,qs.stringify(params),qs.stringify(data)].join('&')
  }
  // 用于把当前请求信息添加到pendingRequest对象中去
  PendingRequest = new Map();
  addPendingRequest(config){
    const requestKey = this.generateReqKey(config);
    config.cancalToken = config.cancalToken || new axios.CancelToken((cancel)=>{
      if(!this.PendingRequest.has(requestKey)){
        this.PendingRequest.set(requestKey,cancel)
      }
    })
  }
  // 检查是否存在重复请求,若存在则需要取消已经发出的请求
  removeRequest(config){
    const requestKey = this.generateReqKey(config);
    if(this.PendingRequest.has(requestKey)){
      const CancelToken = this.PendingRequest.get(requestKey);
      CancelToken(requestKey);
      this.PendingRequest.delete(requestKey);
    }
  }
  interceptors(install) {
    install.interceptors.request.use(config => {
      // 检查是否存在重复请求
      this.removeRequest(config);
      // 把当前请求信息添加到pendingRequest对象中
      this.addPendingRequest(config);
      const token = localStorage.getItem('token');
      if (token) {
        config.headers.authorization = `token ${token}`;
      }

      return config
    }, err => {
      return Promise.reject(err)
    });

    install.interceptors.response.use(res => {
      // 从pendingRequest对象中移除请求
      this.removeRequest(res.config);
      const { data } = res;
      return data
    }, err => {
      // 从pendingRequest对象中移除请求
      this.removeRequest(err.config)
      return Promise.reject(err)
    });
  }

  request(options) {
    options = { ...this.defaults, ...options }
    const instance = axios.create(options);
    this.interceptors(instance);
    return instance
  }
}

2、限制失败请求重试的次数,避免无效请求过多,导致大量的资源消耗
**3、善用缓存,减小网络请求的次数。**比如在我们的项目中,个人空间展示页,如果判断是自己访问自己的空间,那么就不用再去请求数据了,直接从vuex中或者localstorage中去取就可以了。

三、业务层面的优化

1、防抖节流
防抖节流是优化高频率执行代码的一种手段,比如浏览器的resize、scroll、keypress、mousemove等事件在触发的时候,会不断的调用绑定的回调函数,极大的浪费资源,甚至降低前端的性能。
为了优化体验,我们可以采取防抖和节流的手段来减少调用的频率。
节流:n秒内只运行一次,若n秒内重复触发,则只有一次生效。
防抖:n秒后执行该事件,若在n秒内重复触发,则重新计时。

代码实现如下:
节流函数

// 节流函数
function throttled(fn,delay) {
  let timer = null;
  let startTime = Date.now();
  return function(){
    let curTime = Date.now();
    let remaining = delay-(curTime-startTime);
    let context = this;
    let args = arguments;
    clearTimeout(timer);
    if(remaining<=0){
      fn.apply(context,args);
      startTime = Date.now();
    }else{
      timer = setTimeout(fn,remaining);
    }
  }
}

防抖函数

// 防抖
function debounce(fn,wait,immediate){
  let timeout;
  return function(){
    let context = this;
    let args = arguments;
    if(timeout) clearTimeout(timeout);
    if(immediate){
      let callNow = !timeout; //第一次回立即执行,以后只有事件执行之后才会继续触发
      timeout = setTimeout(function(){
        timeout = null;
      },wait)
      if(callNow){
        fn.apply(context,args)
      }
    }else{
      timeout = setTimeout(function(){
        fn.apply(context,args);
      },wait);
    }
  }
}

二者的应用场景举例:
防抖是连续的事件,只需要触发一次回调:
(1)搜索框搜索输入,只需要用户最后一次输入完再发送请求
(2)手机号、邮箱验证输入检测
(3)窗口大小resize,只需要窗口调整完成后,计算窗口大小,防止重复渲染
节流是每间隔一段时间执行一次回调:
(1)滚动加载,加载更多或者滚动到底部监听
(2)搜索框,搜索联想功能

2.事件解绑
组件销毁之前解绑事件,避免内存占用过多

3.长列表优化
我们的项目中采用了分页的思想来分批请求数据。其余的还可以采用懒加载、虚拟滚动等。

4.首屏时间优化
可以采用预渲染技术,比如ssr等。
可以用lighthouse去测检测一下性能
在这里插入图片描述

5.路由懒加载

// 引入路由组件
import Welcome from '@/pages/Welcome'
import Home from '@/pages/Home'; //引入组件会打包在文件中,如果都用import的话会导致所有组件打包在一个文件中,导致文件很大
// 按需加载,访问路径的时候才会加载;不访问不加载
const Search = ()=> import('@/pages/Search');
const Community = ()=> import('@/pages/Community');
const MyRoom = ()=> import('@/pages/MyRoom');

** 6.组件懒加载**
用到了再加载,缩短加载时间

四、打包方面

(1)减少打包的体积:压缩代码、资源的体积
(2)缩短打包时长:cache-loader、thread-loader
cache-loader: 允许缓存以下 loaders 到(默认)磁盘或数据库。在一些性能开销较大的 loader 之前添加 cache-loader,以便将结果缓存到磁盘里。保存和读取这些缓存文件会有一些时间开销,所以请只对性能开销较大的 loader 使用此 loader。

thread-loader:
使用时,需将此 loader 放置在其他 loader 之前。放置在此 loader 之后的 loader 会在一个独立的 worker 池中运行。
在 worker 池中运行的 loader 是受到限制的。例如:
这些 loader 不能生成新的文件。
这些 loader 不能使用自定义的 loader API(也就是说,不能通过插件来自定义)。
这些 loader 无法获取 webpack 的配置。
每个 worker 都是一个独立的 node.js 进程,其开销大约为 600ms 左右。同时会限制跨进程的数据交换。
请仅在耗时的操作中使用此 loader!
(3)使用CDN:请求资源更快

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 01:54:55  更:2022-09-15 01:56:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年6日历 -2024/6/1 21:41:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码