渲染组件时,会通过
Vue.extend
方法构建子组件的构造函数,并进行实例化。最终手动调用$mount()
进行挂载。更新组件时会进行patchVnode
流程,核心就是diff
算法
使用mapGetters辅助函数, 利用对象展开运算符将getter混入computed 对象中
import {mapGetters} from 'vuex'
export default{
computed:{
...mapGetters(['total','discountTotal'])
}
}
我们可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。
推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:
mutation
是同步更新, $watch
严格模式下会报错 action
是异步操作,可以获取数据后调用 mutation
提交最终数据参考:前端vue面试题详细解答
不会立即同步执行重新渲染。Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化, Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
如果同一个watcher被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环tick中,Vue 刷新队列并执行实际(已去重的)工作。
首屏时间(First Contentful Paint
),指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容
首屏加载可以说是用户体验中最重要的环节
关于计算首屏时间
利用performance.timing
提供的数据:
通过DOMContentLoad
或者performance
来计算出首屏时间
// 方案一:
document.addEventListener('DOMContentLoaded', (event) => {
console.log('first contentful painting');
});
// 方案二:
performance.getEntriesByName("first-contentful-paint")[0].startTime
// performance.getEntriesByName("first-contentful-paint")[0]
// 会返回一个 PerformancePaintTiming的实例,结构如下:
{
name: "first-contentful-paint",
entryType: "paint",
startTime: 507.80000002123415,
duration: 0,
};
在页面渲染的过程,导致加载速度慢的因素可能如下:
常见的几种SPA首屏优化方式
1. 减小入口文件体积
常用的手段是路由懒加载,把不同路由对应的组件分割成不同的代码块,待路由被请求的时候会单独打包路由,使得入口文件变小,加载速度大大增加
在vue-router
配置路由的时候,采用动态加载路由的形式
routes:[
path: 'Blogs',
name: 'ShowBlogs',
component: () => import('./components/ShowBlogs.vue')
]
以函数的形式加载路由,这样就可以把各自的路由文件分别打包,只有在解析给定的路由时,才会加载路由组件
2. 静态资源本地缓存
后端返回资源问题:
HTTP
缓存,设置Cache-Control
,Last-Modified
,Etag
等响应头Service Worker
离线缓存前端合理利用localStorage
3. UI框架按需加载
在日常使用UI
框架,例如element-UI
、或者antd
,我们经常性直接引用整个UI
库
import ElementUI from 'element-ui'
Vue.use(ElementUI)
但实际上我用到的组件只有按钮,分页,表格,输入与警告 所以我们要按需引用
import { Button, Input, Pagination, Table, TableColumn, MessageBox } from 'element-ui';
Vue.use(Button)
Vue.use(Input)
Vue.use(Pagination)
4. 组件重复打包
假设A.js
文件是一个常用的库,现在有多个路由使用了A.js
文件,这就造成了重复下载
解决方案:在webpack
的config
文件中,修改CommonsChunkPlugin
的配置
minChunks: 3
minChunks
为3表示会把使用3次及以上的包抽离出来,放进公共依赖文件,避免了重复加载组件
5. 图片资源的压缩
图片资源虽然不在编码过程中,但它却是对页面性能影响最大的因素
对于所有的图片资源,我们可以进行适当的压缩
对页面上使用到的icon
,可以使用在线字体图标,或者雪碧图,将众多小图标合并到同一张图上,用以减轻http
请求压力。
6. 开启GZip压缩
拆完包之后,我们再用gzip
做一下压缩 安装compression-webpack-plugin
cnmp i compression-webpack-plugin -D
在vue.congig.js
中引入并修改webpack
配置
const CompressionPlugin = require('compression-webpack-plugin')
configureWebpack: (config) => {
if (process.env.NODE_ENV === 'production') {
// 为生产环境修改配置...
config.mode = 'production'
return {
plugins: [new CompressionPlugin({
test: /\.js$|\.html$|\.css/, //匹配文件名
threshold: 10240, //对超过10k的数据进行压缩
deleteOriginalAssets: false //是否删除原文件
})]
}
}
在服务器我们也要做相应的配置 如果发送请求的浏览器支持gzip
,就发送给它gzip
格式的文件 我的服务器是用express
框架搭建的 只要安装一下compression
就能使用
const compression = require('compression')
app.use(compression()) // 在其他中间件使用之前调用
7. 使用SSR
SSR(Server side ),也就是服务端渲染,组件或页面通过服务器生成html字符串,再发送到浏览器
从头搭建一个服务端渲染是很复杂的,vue
应用建议使用Nuxt.js
实现服务端渲染
减少首屏渲染时间的方法有很多,总的来讲可以分成两大部分 :资源加载优化
和 页面渲染优化
下图是更为全面的首屏优化的方案
大家可以根据自己项目的情况选择各种方式进行首屏渲染的优化
计算属性 computed:
(1)支持缓存,只有依赖数据发生变化时,才会重新进行计算函数;
(2)计算属性内不支持异步操作;
(3)计算属性的函数中都有一个 get(默认具有,获取计算属性)和 set(手动添加,设置计算属性)方法;
(4)计算属性是自动监听依赖值的变化,从而动态返回内容。
侦听属性 watch:
(1)不支持缓存,只要数据发生变化,就会执行侦听函数;
(2)侦听属性内支持异步操作;
(3)侦听属性的值可以是一个对象,接收 handler 回调,deep,immediate 三个属性;
(3)监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些其他事情。
回答范例
vue-loader
是用于处理单文件组件(SFC
,Single-File Component
)的webpack loader
vue-loader
,我们就可以在项目中编写SFC
格式的Vue
组件,我们可以把代码分割为
、
和
,代码会异常清晰。结合其他loader
我们还可以用Pug
编写
,用SASS
编写
,用TS
编写
。我们的
还可以单独作用当前组件webpack
打包时,会以loader
的方式调用vue-loader
vue-loader
被执行时,它会对SFC
中的每个语言块用单独的loader
链处理。最后将这些单独的块装配成最终的组件模块原理
vue-loader
会调用@vue/compiler-sfc
模块解析SFC
源码为一个描述符(Descriptor
),然后为每个语言块生成import
代码,返回的代码类似下面
// source.vue被vue-loader处理之后返回的代码
// import the block
import render from 'source.vue?vue&type=template'
// import the