抓取ajax动态网页java(【干货】Vue项目性能优化(一)——Vue框架)
优采云 发布时间: 2022-01-23 17:15抓取ajax动态网页java(【干货】Vue项目性能优化(一)——Vue框架)
前言
Vue框架通过数据双向绑定和虚拟DOM技术帮助我们处理前端开发中最脏最累的DOM操作部分。我们不再需要思考如何操作 DOM 以及如何最有效地操作 DOM;但是Vue项目还是存在项目首屏优化、Webpack编译配置优化等问题,所以我们还是需要关注Vue项目的性能优化,让项目具有更高效的性能和更好的用户体验。这篇文章是作者通过实际项目的优化实践总结出来的。希望读者在看完这篇文章后会有一些启发,从而帮助他们优化自己的项目。
辛苦整理了好久,希望手动点赞鼓励~
github地址为:/fengshi123/...,总结了作者所有的博客,欢迎关注和star~
一、代码级优化
1.1、v-if和v-show区分使用场景
v-if 是真正的条件渲染,因为它确保条件块内的事件侦听器和子组件在切换期间被正确销毁和重新创建;也懒惰:如果条件在初始渲染时为假,则什么都不做 - 条件块在条件第一次变为真之前不会开始渲染。
v-show 更简单,无论初始条件如何,元素总是被渲染,并且简单地根据 CSS 显示属性进行切换。
因此,v-if适用于运行时很少改变条件,不需要频繁切换条件的场景;v-show 适用于需要非常频繁切换条件的场景。
1.2、计算和观察区分使用场景
计算:它是一个计算属性,它依赖于其他属性值,计算值被缓存。只有当它所依赖的属性值发生变化时,才会在下次获取计算值时重新计算计算值;
watch:更多的是“观察”的作用,类似于一些数据的监控回调,每次被监控的数据发生变化,都会执行回调以进行后续操作;
应用场景:
1.3、v-for遍历必须给item添加key,避免同时使用v-if
(1)v-for遍历必须给item添加key
在遍历和渲染列表数据时,需要为每个item设置一个唯一的key值,这样Vue.js的内部机制才能准确的找到列表数据。当状态更新时,将新状态值与旧状态值进行比较,以更快地定位差异。
(2)v-for遍历避免同时使用v-if
v-for 的优先级高于 v-if。如果每次都需要遍历整个数组,会影响速度,尤其是需要渲染一小部分的时候,必要时应该换成计算属性。
推荐:
{{ user.name }}
computed: {
activeUsers: function () {
return this.users.filter(function (user) {
return user.isActive
})
}
}
复制代码
不建议:
{{ user.name }}
复制代码
1.4、长列表性能优化
Vue会通过Object.defineProperty劫持数据,实现视图对数据变化的响应。但是,有时我们的组件是纯粹的数据展示,不会有任何变化。我们不需要 Vue 来劫持我们的数据。在数据展示的情况下,这样可以显着减少组件初始化时间,那么如何防止Vue劫持我们的数据呢?对象可以通过 Object.freeze 方法冻结。一旦对象被冻结,就不能再对其进行修改。
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};
复制代码
1.5、事件销毁
当 Vue 组件被销毁时,它会自动清理它与其他实例的连接,解除其所有指令和事件*敏*感*词*器的绑定,但仅限于组件本身的事件。js中如果使用addEventListene等方法,不会自动销毁。我们需要在组件被销毁时手动移除这些事件的*敏*感*词*器,以避免内存泄漏,例如:
created() {
addEventListener('click', this.click, false)
},
beforeDestroy() {
removeEventListener('click', this.click, false)
}
复制代码
1.6、图片资源的延迟加载
对于图片过多的页面,为了加快页面加载速度,很多时候我们需要先加载没有出现在页面可视区域的图片,滚动到可视区域后再加载。这样一来,页面加载性能会大大提升,用户体验也会得到提升。我们在项目中使用了 Vue 的 vue-lazyload 插件:
(1)安装插件
npm install vue-lazyload --save-dev
复制代码
(2)入口文件man.js中引入并使用
import VueLazyload from 'vue-lazyload'
复制代码
然后直接在vue中使用
Vue.use(VueLazyload)
复制代码
或添加自定义选项
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'dist/error.png',
loading: 'dist/loading.gif',
attempt: 1
})
复制代码
(3)在vue文件中直接将img标签的src属性改为v-lazy,从而将图片显示方式改为延迟加载显示:
<img v-lazy="/static/img/1.png">
复制代码
以上是vue-lazyload插件的简单使用。如果想查看更多插件的参数选项,可以查看vue-lazyload的github地址。
1.7、路由延迟加载
Vue是单页应用,可能导入的路由很多。这样用webpcak打包的文件就很大了。进入首页时,加载的资源过多,页面会出现白屏,不利于用户体验。如果我们可以将不同路由对应的组件分成不同的代码块,然后在路由被访问时加载相应的组件,效率会更高。这将大大提高首屏显示的速度,但其他页面的速度可能会变慢。
路由延迟加载:
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
复制代码
1.8、按需引入第三方插件
我们经常需要在项目中引入第三方插件。如果直接引入整个插件,会导致项目体积过大。我们可以使用 babel-plugin-component ,然后只引入需要的组件来减少项目体积。的目标。下面是在项目中引入element-ui组件库的例子:
(1)首先,安装 babel-plugin-component:
npm install babel-plugin-component -D
复制代码
(2)然后,修改.babelrc为:
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
复制代码
(3)在main.js中引入一些组件:
import Vue from 'vue';
import { Button, Select } from 'element-ui';
Vue.use(Button)
Vue.use(Select)
复制代码
1.9、优化无限列表性能
如果你的应用程序有很长或无限的滚动列表,你需要使用窗口技术来优化性能,只需要渲染一小块区域的内容,减少重新渲染组件和创建 dom 节点的时间。你可以参考下面的开源项目 vue-virtual-scroll-list 和 vue-virtual-scroller 来优化这个无限列表的场景。
1.10、服务端渲染SSR或预渲染
服务端渲染是指Vue从客户端的标签开始渲染整个html片段完成服务端的工作,服务端形成的html片段直接返回给客户端。这个过程称为服务器端渲染。
(1)服务端渲染的优点:
(2)服务端渲染的缺点:
如果你的项目的SEO和首屏渲染是评价项目的关键指标,那么你的项目需要服务端渲染来帮助你达到最佳的初始加载性能和SEO。Vue SSR的具体实现方法可以参考作者的另一篇文章文章《Vue SSR踏上坑路》。如果您的 Vue 项目只需要改进几个营销页面(例如 /、/about、/contact 等)的 SEO,那么您可能希望在构建时预渲染并简单地为特定路由生成静态 HTML 文件。优点是设置预渲染更容易,并且您可以将前端用作完全静态的站点。具体来说,您可以使用 prerender-spa-plugin 轻松添加预渲染。
二、Webpack 级别的优化
2.1、Webpack 压缩图片
在vue项目中,除了可以在webpack.base.conf.js中的url-loader中设置limit size来处理图片,并将小于limit的图片转换为base64格式,其余不操作。所以对于一些大的图片资源,在请求资源的时候,加载会很慢,我们可以使用image-webpack-loader来压缩图片:
(1)首先,安装image-webpack-loader:
npm install image-webpack-loader --save-dev
复制代码
(2)然后,在 webpack.base.conf.js 中配置:
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use:[
{
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
}
}
]
}
复制代码
2.2、减少从 ES6 到 ES5 的冗余代码
Babel 插件在将 ES6 代码转换为 ES5 代码时会注入一些辅助函数,例如下面的 ES6 代码:
class HelloWebpack extends Component{...}
复制代码
将此代码转换为有效的 ES5 代码需要以下两个辅助函数:
babel-runtime/helpers/createClass // 用于实现 class 语法
babel-runtime/helpers/inherits // 用于实现 extends 语法
复制代码
默认情况下,Babel 会将这些依赖的辅助函数代码嵌入到每个输出文件中。如果多个源代码文件依赖这些辅助函数,这些辅助函数的代码会出现多次,导致代码冗余。为了不重复这些helper函数的代码,可以在依赖的时候通过require('babel-runtime/helpers/createClass')来导入,这样它们就只出现一次。babel-plugin-transform-runtime插件就是用来实现这个功能的,将相关的辅助功能替换成import语句,从而减小babel编译的代码的文件大小。
(1)首先,安装 babel-plugin-transform-runtime:
npm install babel-plugin-transform-runtime --save-dev
复制代码
(2)然后,修改.babelrc配置文件为:
"plugins": [
"transform-runtime"
]
复制代码
如果想看更多关于插件的详细信息,可以查看 babel-plugin-transform-runtime 的详细介绍。
2.3、提取公共代码
如果项目没有提取每个页面的第三方库和公共模块,项目会出现以下问题:
因此,我们需要将多个页面的公共代码提取到单独的文件中来优化上述问题。Webpack 有一个内置插件 CommonsChunkPlugin 专门用于提取多个 Chunk 中的公共部分。我们项目中CommonsChunkPlugin的配置如下:
// 所有在 package.json 里面依赖的包,都会被打包进 vendor.js 这个文件中。
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module, count) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
);
}
}),
// 抽取出代码模块的映射关系
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
})
复制代码
如果想看插件的更多细节,可以查看CommonsChunkPlugin的详细介绍。
2.4、模板预编译
在 JavaScript 中使用 in-DOM 模板或字符串模板时,模板会在运行时编译为渲染函数。通常这已经足够快了,但最好避免对性能敏感的应用程序。
预编译模板最简单的方法是使用单文件组件——相关的构建设置会自动处理预编译,因此构建的代码已经收录编译后的渲染函数而不是原创模板字符串。
如果你使用 webpack 并且喜欢将 JavaScript 和模板文件分开,你可以使用 vue-template-loader,它还会在构建过程中将模板文件转换为 JavaScript 渲染函数。
2.5、提取组件的CSS
使用单文件组件时,组件内部的 CSS 是通过 JavaScript 以样式标签的形式动态注入的。这有一些小的运行时开销,如果您使用服务器端渲染,这可能会导致“无样式内容 (fouc) 闪烁”。将所有组件的 CSS 提取到同一个文件中可以避免这个问题,并且还可以更好地压缩和缓存 CSS。