记录--前端性能优化——首页资源压缩63%、白屏时间缩短86%

news2025/7/7 11:26:55

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

 

提升首屏的加载速度,是前端性能优化中最重要的环节,这里笔者梳理出一些 常规且有效 的首屏优化建议

目标: 通过对比优化前后的性能变化,来验证方案的有效性,了解并掌握其原理

1、路由懒加载

SPA 项目,一个路由对应一个页面,如果不做处理,项目打包后,会把所有页面打包成一个文件,当用户打开首页时,会一次性加载所有的资源,造成首页加载很慢,降低用户体验

列一个实际项目的打包详情:

app.js 初始体积: 1175 KB

 app.css 初始体积: 274 KB

 将路由全部改成懒加载

// 通过webpackChunkName设置分割后代码块的名字
const Home = () => import(/* webpackChunkName: "home" */ "@/views/home/index.vue");
const MetricGroup = () => import(/* webpackChunkName: "metricGroup" */ "@/views/metricGroup/index.vue");
…………
const routes = [
    {
       path: "/",
       name: "home",
       component: Home
    },
    {
       path: "/metricGroup",
       name: "metricGroup",
       component: MetricGroup
    },
    …………
 ]

重新打包后,首页资源拆分为 app.js 和 home.js,以及对应的 css 文件

  • app.js:244 KB、 home.js: 35KB

  • app.css:67 KB、home.css: 15KB

 通过路由懒加载,该项目的首页资源压缩约 52%

路由懒加载的原理

懒加载前提的实现:ES6的动态地加载模块——import()

调用 import() 之处,被作为分离的模块起点,意思是,被请求的模块和它引用的所有子模块,会分离到一个单独的 chunk 中
——摘自《webpack——模块方法》的import()小节

要实现懒加载,就得先将进行懒加载的子模块分离出来,打包成一个单独的文件

webpackChunkName 作用是 webpack 在打包的时候,对异步引入的库代码(lodash)进行代码分割时,设置代码块的名字。webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中

2、组件懒加载

除了路由的懒加载外,组件的懒加载在很多场景下也有重要的作用

举个🌰:

home 页面 和 about 页面,都引入了 dialogInfo 弹框组件,该弹框不是一进入页面就加载,而是需要用户手动触发后才展示出来

home 页面示例:

<template>
  <div class="homeView">
    <p>home 页面</p>
    <el-button @click="dialogVisible = !dialogVisible">打开弹框</el-button>
    <dialogInfo v-if="dialogVisible" />
  </div>
</template>
<script>
import dialogInfo from '@/components/dialogInfo';
export default {
  name: 'homeView',
  components: {
    dialogInfo
  }
}
</script>

项目打包后,发现 home.js 和 about.js 均包括了该弹框组件的代码(在 dist 文件中搜索dialogInfo弹框组件)

当用户打开 home 页时,会一次性加载该页面所有的资源,我们期望的是用户触发按钮后,再加载该弹框组件的资源

这种场景下,就很适合用懒加载的方式引入

弹框组件懒加载:

<script>
const dialogInfo = () => import(/* webpackChunkName: "dialogInfo" */ '@/components/dialogInfo');
export default {
  name: 'homeView',
  components: {
    dialogInfo
  }
}
</script>

重新打包后,home.js 和 about.js 中没有了弹框组件的代码,该组件被独立打包成 dialogInfo.js,当用户点击按钮时,才会去加载 dialogInfo.js 和 dialogInfo.css

最终,使用组件路由懒后,该项目的首页资源进一步减少约 11%

组件懒加载的使用场景

有时资源拆分的过细也不好,可能会造成浏览器 http 请求的增多

总结出三种适合组件懒加载的场景:

1)该页面的 JS 文件体积大,导致页面打开慢,可以通过组件懒加载进行资源拆分,利用浏览器并行下载资源,提升下载速度(比如首页)

2)该组件不是一进入页面就展示,需要一定条件下才触发(比如弹框组件)

3)该组件复用性高,很多页面都有引入,利用组件懒加载抽离出该组件,一方面可以很好利用缓存,同时也可以减少页面的 JS 文件大小(比如表格组件、图形组件等)

3、合理使用 Tree shaking

virtualList.png

Tree shaking 的作用:消除无用的 JS 代码,减少代码体积

举个🌰:

// util.js
export function targetType(target) {
  return Object.prototype.toString.call(target).slice(8, -1).toLowerCase();
}
export function deepClone(target) {
  return JSON.parse(JSON.stringify(target));
}

项目中只使用了 targetType 方法,但未使用 deepClone 方法,项目打包后,deepClone 方法不会被打包到项目里

tree-shaking 原理:

依赖于ES6的模块特性,ES6模块依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析,这就是 tree-shaking 的基础

静态分析就是不需要执行代码,就可以从字面量上对代码进行分析。ES6之前的模块化,比如 CommonJS 是动态加载,只有执行后才知道引用的什么模块,就不能通过静态分析去做优化,正是基于这个基础上,才使得 tree-shaking 成为可能

Tree shaking 并不是万能的

并不是说所有无用的代码都可以被消除,还是上面的代码,换个写法 tree-shaking 就失效了

// util.js
export default {
  targetType(target) {
    return Object.prototype.toString.call(target).slice(8, -1).toLowerCase();
  },
  deepClone(target) {
    return JSON.parse(JSON.stringify(target));
  }
};

// 引入并使用
import util from '../util';
util.targetType(null)

同样的,项目中只使用了 targetType 方法,未使用 deepClone 方法,项目打包后,deepClone 方法还是被打包到项目里

在 dist 文件中搜索 deepClone 方法:

究其原因,export default 导出的是一个对象,无法通过静态分析判断出一个对象的哪些变量未被使用,所以 tree-shaking 只对使用 export 导出的变量生效

这也是函数式编程越来越火的原因,因为可以很好利用 tree-shaking 精简项目的体积,也是 vue3 全面拥抱了函数式编程的原因之一

4、骨架屏优化白屏时长

skeleton.gif

使用骨架屏,可以缩短白屏时间,提升用户体验。国内大多数的主流网站都使用了骨架屏,特别是手机端的项目

SPA 单页应用,无论 vue 还是 react,最初的 html 都是空白的,需要通过加载 JS 将内容挂载到根节点上,这套机制的副作用:会造成长时间的白屏

常见的骨架屏插件就是基于这种原理,在项目打包时将骨架屏的内容直接放到 html 文件的根节点中

使用骨架屏插件,打包后的 html 文件(根节点内部为骨架屏):

html.png

同一项目,对比使用骨架屏前后的 FP 白屏时间:

  • 无骨架屏:白屏时间 1063ms
FPoriginal.png
  • 有骨架屏:白屏时间 144ms
FP.png

骨架屏确实是优化白屏的不二选择,白屏时间缩短了 86%

骨架屏插件

这里以 vue-skeleton-webpack-plugin 插件为例,该插件的亮点是可以给不同的页面设置不同的骨架屏,这点确实很酷

1)安装

npm i vue-skeleton-webpack-plugin 

2)vue.config.js 配置

// 骨架屏
const SkeletonWebpackPlugin = require("vue-skeleton-webpack-plugin");
module.exports = {
   configureWebpack: {
      plugins: [
       new SkeletonWebpackPlugin({
        // 实例化插件对象
        webpackConfig: {
          entry: {
            app: path.join(__dirname, './src/skeleton.js') // 引入骨架屏入口文件
          }
        },
        minimize: true, // SPA 下是否需要压缩注入 HTML 的 JS 代码
        quiet: true, // 在服务端渲染时是否需要输出信息到控制台
        router: {
          mode: 'hash', // 路由模式
          routes: [
            // 不同页面可以配置不同骨架屏
            // 对应路径所需要的骨架屏组件id,id的定义在入口文件内
            { path: /^\/home(?:\/)?/i, skeletonId: 'homeSkeleton' },
            { path: /^\/detail(?:\/)?/i, skeletonId: 'detailSkeleton' }
          ]
        }
      })        
      ]
   }
}

3)新建 skeleton.js 入口文件

// skeleton.js
import Vue from "vue";
// 引入对应的骨架屏页面
import homeSkeleton from "./views/homeSkeleton";
import detailSkeleton from "./views/detailSkeleton";

export default new Vue({
    components: {
        homeSkeleton,
        detailSkeleton,
    },
    template: `
    <div>
      <homeSkeleton id="homeSkeleton" style="display:none;" />
      <detailSkeleton id="detailSkeleton" style="display:none;" />
    </div>
  `,
});

5、长列表虚拟滚动

首页中不乏有需要渲染长列表的场景,当渲染条数过多时,所需要的渲染时间会很长,滚动时还会造成页面卡顿,整体体验非常不好

虚拟滚动——指的是只渲染可视区域的列表项,非可见区域的不渲染,在滚动时动态更新可视区域,该方案在优化大量数据渲染时效果是很明显的

虚拟滚动图例:

virtual.png

虚拟滚动基本原理:

计算出 totalHeight 列表总高度,并在触发时滚动事件时根据 scrollTop 值不断更新 startIndex 以及 endIndex ,以此从列表数据 listData 中截取对应元素

虚拟滚动性能对比:

  • 在不使用虚拟滚动的情况下,渲染10万个文本节点:

    longList.png
  • 使用虚拟滚动的情况后:

    virtualList.png

使用虚拟滚动使性能提升了 78%

虚拟滚动插件

虚拟滚动的插件有很多,比如 vue-virtual-scroller、vue-virtual-scroll-list、react-tiny-virtual-list、react-virtualized 等

这里简单介绍 vue-virtual-scroller 的使用

// 安装插件
npm install vue-virtual-scroller

// main.js
import VueVirtualScroller from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

Vue.use(VueVirtualScroller)

// 使用
<template> 
  <RecycleScroller 
    class="scroller" 
    :items="list" 
    :item-size="32" 
    key-field="id" 
    v-slot="{ item }"> 
      <div class="user"> {{ item.name }} </div>
  </RecycleScroller> 
</template>

该插件主要有 RecycleScroller.vue、DynamicScroller.vue 这两个组件,其中 RecycleScroller 需要 item 的高度为静态的,也就是列表每个 item 的高度都是一致的,而 DynamicScroller 可以兼容 item 的高度为动态的情况

6、Web Worker 优化长任务

由于浏览器 GUI 渲染线程与 JS 引擎线程是互斥的关系,当页面中有很多长任务时,会造成页面 UI 阻塞,出现界面卡顿、掉帧等情况

查看页面的长任务:

打开控制台,选择 Performance 工具,点击 Start 按钮,展开 Main 选项,会发现有很多红色的三角,这些就属于长任务(长任务:执行时间超过50ms的任务)

longTask.png

测试实验:

如果直接把下面这段代码直接丢到主线程中,计算过程中页面一直处于卡死状态,无法操作

let sum = 0;
for (let i = 0; i < 200000; i++) {
    for (let i = 0; i < 10000; i++) {
      sum += Math.random()
    }
  }

使用 Web Worker 执行上述代码时,计算过程中页面正常可操作、无卡顿

// worker.js
onmessage = function (e) {
  // onmessage获取传入的初始值
  let sum = e.data;
  for (let i = 0; i < 200000; i++) {
    for (let i = 0; i < 10000; i++) {
      sum += Math.random()
    }
  }
  // 将计算的结果传递出去
  postMessage(sum);
}

Web Worker 具体的使用与案例,详情见 一文彻底了解Web Worker,十万、百万条数据都是弟弟🔥

Web Worker 的通信时长

并不是执行时间超过 50ms 的任务,就可以使用 Web Worker,还要先考虑通信时长的问题

假如一个运算执行时长为 100ms,但是通信时长为 300ms, 用了 Web Worker可能会更慢

比如新建一个 web worker, 浏览器会加载对应的 worker.js 资源,下图中的 Time 是这个资源的通信时长(也叫加载时长)

load.png

当任务的运算时长 - 通信时长 > 50ms,推荐使用Web Worker

7、requestAnimationFrame 制作动画

requestAnimationFrame 是浏览器专门为动画提供的 API,它的刷新频率与显示器的频率保持一致,使用该 api 可以解决用 setTimeout/setInterval 制作动画卡顿的情况

下面的案例演示了两者制作进度条的对比(运行按钮可点击)

可以看到使用定时器制作的动画,卡顿还是比较明显的

setTimeout/setInterval、requestAnimationFrame 三者的区别:

1)引擎层面

setTimeout/setInterval 属于 JS引擎,requestAnimationFrame 属于 GUI引擎

JS引擎与GUI引擎是互斥的,也就是说 GUI 引擎在渲染时会阻塞 JS 引擎的计算

2)时间是否准确

requestAnimationFrame 刷新频率是固定且准确的,但 setTimeout/setInterval 是宏任务,根据事件轮询机制,其他任务会阻塞或延迟js任务的执行,会出现定时器不准的情况

3)性能层面

当页面被隐藏或最小化时,setTimeout/setInterval 定时器仍会在后台执行动画任务,而使用 requestAnimationFrame 当页面处于未激活的状态下,屏幕刷新任务会被系统暂停

8、JS 的6种加载方式

1)正常模式

<script src="index.js"></script>

这种情况下 JS 会阻塞 dom 渲染,浏览器必须等待 index.js 加载和执行完成后才能去做其它事情

2)async 模式

<script async src="index.js"></script>

async 模式下,它的加载是异步的,JS 不会阻塞 DOM 的渲染,async 加载是无顺序的,当它加载结束,JS 会立即执行

使用场景:若该 JS 资源与 DOM 元素没有依赖关系,也不会产生其他资源所需要的数据时,可以使用async 模式,比如埋点统计

3)defer 模式

<script defer src="index.js"></script>

defer 模式下,JS 的加载也是异步的,defer 资源会在 DOMContentLoaded 执行之前,并且 defer 是有顺序的加载

如果有多个设置了 defer 的 script 标签存在,则会按照引入的前后顺序执行,即便是后面的 script 资源先返回

所以 defer 可以用来控制 JS 文件的执行顺序,比如 element-ui.js 和 vue.js,因为 element-ui.js 依赖于 vue,所以必须先引入 vue.js,再引入 element-ui.js

<script defer src="vue.js"></script>
<script defer src="element-ui.js"></script>

defer 使用场景:一般情况下都可以使用 defer,特别是需要控制资源加载顺序时

4)module 模式

<script type="module">import { a } from './a.js'</script>

在主流的现代浏览器中,script 标签的属性可以加上 type="module",浏览器会对其内部的 import 引用发起 HTTP 请求,获取模块内容。这时 script 的行为会像是 defer 一样,在后台下载,并且等待 DOM 解析

Vite 就是利用浏览器支持原生的 es module 模块,开发时跳过打包的过程,提升编译效率

5) preload

<link rel="preload" as="script" href="index.js">

link 标签的 preload 属性:用于提前加载一些需要的依赖,这些资源会优先加载(如下图红框)

preload.png

vue2 项目打包生成的 index.html 文件,会自动给首页所需要的资源,全部添加 preload,实现关键资源的提前加载

htmlPreload.png

preload 特点:

1)preload 加载的资源是在浏览器渲染机制之前进行处理的,并且不会阻塞 onload 事件;

2)preload 加载的 JS 脚本其加载和执行的过程是分离的,即 preload 会预加载相应的脚本代码,待到需要时自行调用;

6)prefetch

<link rel="prefetch" as="script" href="index.js">

prefetch 是利用浏览器的空闲时间,加载页面将来可能用到的资源的一种机制;通常可以用于加载其他页面(非首页)所需要的资源,以便加快后续页面的打开速度

prefetch.png

prefetch 特点:

1)pretch 加载的资源可以获取非当前页面所需要的资源,并且将其放入缓存至少5分钟(无论资源是否可以缓存)

2)当页面跳转时,未完成的 prefetch 请求不会被中断

加载方式总结

async、defer 是 script 标签的专属属性,对于网页中的其他资源,可以通过 link 的 preload、prefetch 属性来预加载

如今现代框架已经将 preload、prefetch 添加到打包流程中了,通过灵活的配置,去使用这些预加载功能,同时我们也可以审时度势地向 script 标签添加 async、defer 属性去处理资源,这样可以显著提升性能

9、图片的优化

平常大部分性能优化工作都集中在 JS 方面,但图片也是页面上非常重要的部分

特别是对于移动端来说,完全没有必要去加载原图,浪费带宽。如何去压缩图片,让图片更快的展示出来,有很多优化工作可以做

淘宝首页的图片资源都很小:

taobao.png

图片的动态裁剪

很多云服务,比如阿里云或七牛云,都提供了图片的动态裁剪功能,效果很棒,确实是钱没有白花

只需在图片的url地址上动态添加参数,就可以得到你所需要的尺寸大小,比如:http://7xkv1q.com1.z0.glb.clouddn.com/grape.jpg?imageView2/1/w/200/h/200

图片瘦身前后对比:

  • 原图:1.8M
imgOriginal.png
  • 裁剪后:12.8KB
imgAfter.png

经过动态裁剪后的图片,加载速度会有非常明显的提升

图片的懒加载

对于一些图片量比较大的首页,用户打开页面后,只需要呈现出在屏幕可视区域内的图片,当用户滑动页面时,再去加载出现在屏幕内的图片,以优化图片的加载效果

lazyImg.gif

图片懒加载实现原理:

由于浏览器会自动对页面中的 img 标签的 src 属性发送请求并下载图片,可以通过 html5 自定义属性 data-xxx 先暂存 src 的值,然后在图片出现在屏幕可视区域的时候,再将 data-xxx 的值重新赋值到 img 的 src 属性即可

<img src="" alt="" data-src="./images/1.jpg">
<img src="" alt="" data-src="./images/2.jpg">

这里以 vue-lazyload 插件为例

// 安装 
npm install vue-lazyload 
    
// main.js 注册
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
// 配置项
Vue.use(VueLazyload, {
  preLoad: 1.3,
  error: 'dist/error.png', // 图片加载失败时的占位图
  loading: 'dist/loading.gif', // 图片加载中时的占位图
  attempt: 1
})

// 通过 v-lazy 指令使用
<ul>  
    <li v-for="img in list">
        <img v-lazy="img.src" :key="img.src" >
    </li>
</ul>

使用字体图标

字体图标是页面使用小图标的不二选择,最常用的就是 iconfont

iconfont.png

字体图标的优点:

1)轻量级:一个图标字体要比一系列的图像要小。一旦字体加载了,图标就会马上渲染出来,减少了 http 请求

2)灵活性:可以随意的改变颜色、产生阴影、透明效果、旋转等

3)兼容性:几乎支持所有的浏览器,请放心使用

图片转 base64 格式

将小图片转换为 base64 编码字符串,并写入 HTML 或者 CSS 中,减少 http 请求

转 base64 格式的优缺点:

1)它处理的往往是非常小的图片,因为 Base64 编码后,图片大小会膨胀为原文件的 4/3,如果对大图也使用 Base64 编码,后者的体积会明显增加,即便减少了 http 请求,也无法弥补这庞大的体积带来的性能开销,得不偿失

2)在传输非常小的图片的时候,Base64 带来的文件体积膨胀、以及浏览器解析 Base64 的时间开销,与它节省掉的 http 请求开销相比,可以忽略不计,这时候才能真正体现出它在性能方面的优势

项目可以使用 url-loader 将图片转 base64:

// 安装
npm install url-loader --save-dev
    
// 配置
module.exports = {
  module: {
    rules: [{
        test: /.(png|jpg|gif)$/i,
        use: [{
            loader: 'url-loader',
            options: {
              // 小于 10kb 的图片转化为 base64
              limit: 1024 * 10
            }
        }]
     }]
  }
};

优化总结

本文主要介绍的是 代码层面 的性能优化,经过上面的一系列优化,首页打开速度有了明显的提升,虽然都是一些常规方案,但其中可以深挖的知识点并不少

下一篇文章: 前端内存优化知多少?内存泄露只是冰山一角,聊一聊前端内存方面的优化,小伙们一起来看看其中又有哪些知识点

本文转载于:

https://juejin.cn/post/7188894691356573754

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/405469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

除夕最绚丽3D烟花代码(html+音效)

今天就是除夕了&#xff0c;新年怎么能少得了烟花呢&#xff1f;虽然绝大部分地区禁止燃放烟花&#xff0c;但该欣赏的烟花还是要欣赏滴~~ 最近整理文件&#xff0c;找到了一份烟花代码&#xff0c;3D特效&#xff0c;今天分享给大家&#xff0c;希望大家喜欢。 话不多说&#…

uni.getLocation和wx.getLocation方法调用无效,也不返回失败,解决方案!!!

线上已解决问题的代码 记录时间 2022.12.10 //获得地理定位信息uni.getLocation({type: wgs84,success: function(resp) {console.log(11111);//保存纬度数据let latitude resp.latitude;//保存经度度数据let longitude resp.longitude;console.log(经度 latitude);console…

【Vue项目搭建】修改【若依框架】的侧边栏、导航栏、面包屑样式、修改全局页面样式

掌握分寸感&#xff0c;找目标一致的人协同你&#xff0c;有效地调配资源&#xff0c;就可以提高效率。 写在前面的话&#xff1a;博主最近想要搭建自己的前端若依项目&#xff0c;因此此系列博客会做一些记录。我的项目gitee地址&#xff1a; https://gitee.com/xuruicong/rac…

less和sass的区别[简洁易懂]

一、基础知识 1.sass&#xff0c;less都是CSS的预处理器&#xff0c;其基本思想就是用编程的思路编写CSS代码。增加了变量&#xff0c;嵌套&#xff0c;函数&#xff0c;语句&#xff0c;继承等概念。有助于模块化开发&#xff0c;例如写一个换肤的效果&#xff0c;以前我们需要…

前端200道面试题及答案(更新中)

目录 html相关 1&#xff09;说一下对cookie和Storage(localStorage和sessionStorage) 的认识和区别&#xff1f; 2&#xff09;link和import的区别 3&#xff09;浏览器如何实现不同标签页的通信&#xff1f; 4&#xff09;iframe的优缺点 5&#xff09;canvas 6&#x…

Sublime Text 4 (Build 4143) 注册方法STEP BY STEP

To 初学Python的Pythonista: Sublime Text相对于PyCharm和Visual Studio Code&#xff0c;确实有不足之处&#xff0c;但提供了众多功能丰富的插件&#xff0c;且最大优点就是相对于Pycharm和VSCODE&#xff0c;它体积小&#xff0c;启动速度快。对于Python的初学者来说&#…

JavaScript基础总结---重点

目录JavaScript简介什么是JavaScript浏览器执行JS过程JS的组成JS的引入方式函数与作用域arguments的使用全局变量与局部变量预解析对象创建对象的三种方式1.利用字面量创建对象2.利用 new Object 创建对象3.利用构造函数创建对象遍历对象属性变量、属性、函数、方法总结new关键…

节点流和处理流详解

CSDN话题挑战赛第2期 参赛话题&#xff1a;学习笔记 1. 基本介绍 节点流可以从一个特定的数据源读写数据&#xff0c;如FileReader&#xff0c;FileWriter处理流&#xff08;也叫包装流&#xff09;是“连接”在已存在的流&#xff08;节点流或处理流&#xff09;之上&#x…

web服务器项目常见面试题目(C++)

项目介绍 1、为什么要做这样一个项目&#xff1f; 在学习CPP语言的时候&#xff0c;发现需要做一个项目来巩固一下&#xff0c;网上有推荐这个项目&#xff0c;然后就自己尝试做了一下。这个项目综合性比较强&#xff0c;从中既能学习Linux环境下的一些系统调用&#xff0c;也…

Vue3创建项目(一)新手教程

✅作者简介&#xff1a; 我是痴心阿文&#xff0c;你们的学友哥。 整理一下Vue3创建项目&#xff0c;新手教程&#xff0c;看完需要预计花费10分钟。 1.环境准备 Vue依赖NodeJs的环境&#xff0c;需要先安装Nodejs。 2.NodeJs安装 打开NodeJs下载页选择自己系统对应的版本下载。…

【JAVA】书店管理系统(附带前后端源码及资源)

【JAVA_Web】书店管理系统&#xff08;附带前后端源码及资源&#xff09; 一、项目的目的和意义 1.1目的 在“互联网”的大趋势下&#xff0c;线上销售以其简单、便捷、高效的特点受到人们的青睐。网上书店不受时间或者空间的限制&#xff0c;只要在网络覆盖的地方人们就可以…

vue3 动态加载组件、动态引入组件

1.问题 在做一个用vite构建的vue3项目时&#xff0c;动态拉取导入.vue页面&#xff0c;然后控制台一直有以下提示&#xff0c;页面也无法渲染出来。 2.分析 根据上面的报错提示&#xff0c;让我们安装并使用&#xff1a;rollup/plugin-dynamic-import-vars 这个插件&#xff0…

JS遍历对象的七种方法

我根据阮老师的《ES6标准入门》学习并总结了七种遍历对象的方法&#xff0c;我会将分别介绍这七种方法并进行详细的区分&#xff0c;并将从属性可枚举性问题与遍历方法两个大方面讲述全文&#xff0c;其中可枚举性是掌握遍历对象之前的的铺垫&#xff0c;请读者耐心学习&#x…

【解决vscode终端输出中文乱码问题图文教程】

全网最全解决vscode运行C/C终端输出乱码问题图文教程解决vscode终端输出中文乱码问题&#xff0c;强推**方法二**&#xff0c;少走几年弯路乱码原因方法一&#xff08;永久性&#xff09;方法二&#xff08;永久性&#xff09;强力推荐&#xff01;&#xff01;&#xff01;&am…

Vue3中样式渗透:deep()为什么无效

今天学习 /deep/ 样式穿透&#xff0c;因为vue3中已经使用:deep()取代了/deep/ &#xff0c;所以直接用:deep()练习。 :deep()的使用场景&#xff1a; 如果给当前组件的style 节点添加了scoped 属性&#xff0c;则当前组件的样式对其子组件是不生效的。如果想让某些样式对子组…

DVWA(全级别通关教程详解)

文章目录Brute ForceLowMediumCommand InjectionLowMediumHighCSRFLowMediumHighFile InclusionLowMediumHighFile UploadLowMediumHighSQL Injection &#xff08;手工&#xff09;LowMediumHighSQL Injection(工具)LowMediumHighSQL Injection (Blind)Low布尔盲注时间盲注XSS…

若依RuoYi框架log图标与文字怎么改?

文章目录1.若依修改主界面图标2.若依修改主界面文字3.若依修改页面上方图标4.若依修改页面上方文字5.若依登录页面文字修改6.免费图片转换网站1.若依修改主界面图标 图片路径: /src/assets/logo/logo.png直接将想要替换的png格式图片将其替换即可&#xff0c;图片大小建议为60*…

Vue的生命周期的详解

Vue的生命周期 Vue的生命周期是每个使用Vue框架的前端人员都需要掌握的知识&#xff0c;以此作为记录。 Vue的生命周期就是vue实例从创建到销毁的全过程&#xff0c;也就是new Vue() 开始就是vue生命周期的开始。Vue 实例有⼀个完整的⽣命周期&#xff0c;也就是从开始创建、初…

vue中input标签上传本地文件或图片后获取完整路径,如E:\medicineOfCH\stageImage\xxx.jpg

前言&#xff1a; 好久没有写vue了。今天遇到一个需求&#xff1a;使用input框来上传图片类型&#xff0c;并且在选择之后立刻回显出来。使用< input type“file”/>在选定图片后再< img src“xxx”/>。今天在实现这个需求的时候主要是出现了三个问题&#xff1a;…

分享 6 个 Vue3 开发必备的 VSCode 插件

今天分享 6 个 Vue3 开发必备的 VSCode 插件&#xff0c;可以直接用过 VSCode 的插件中心直接安装使用。 如果有觉得有帮助&#xff0c;还请点赞&#x1f44d;支持一下~ 1. Volar &#x1f525; 下载数 153 万 相信使用 VSCode 开发 Vue2 的同学一定对 Vetur 插件不会陌生&…