VUE
vue3.0性能提升主要是通过哪几个方面体现的
响应式实现优化,vue2使用数据劫持需要递归去做响应式处理,vue3使用proxy代理一步到位
diff算法优化,vue2全量对比,vue3使用了静态标记、静态提升、函数缓存等去优化
mvvm
Model-View-ViewModel,
MVVM采用双向数据绑定,ViewModel把Model和View关联起来。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。
vue单向数据流的理解
指数据一般从父组件传到子组件,子组件没有权利直接修改
父组件传来的数据,即子组件从props中直接获取的数据,只能请求父组件修改数据再传给子组件,父组件属性值的更新会下行流动到子组件中。
可以用data承接props中数据
vue的两种路由模式及区别
vue有两种路由模式:hash、history,vue默认是hash模式
1.hash路由地址上由#号,history模式么有
2.在做回车刷新的时候,hash模式会加载对应页面,history会报错
比如这个 URL:http://www.abc.com/#/hello, hash 的值为 #/hello,如果改变hash值,做回车刷新会加载到对应的页面
它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
3.hash模式支持低版本浏览器,history不支持
4.hash不会重新加载页面,单页面应用必备
5.history有历史记录,h5新增pushState和replaceState去修改历史记录,不会立刻发送请求
6.history需要后台配置
hash: url中有“#”号;
hash值(“#”后的值)不会被包含在http请求中,改变hash值不会引起页面的重新加载.
hash改变会触发hashChange事件,会被浏览器记录下来,可以使用浏览器的前进和后退
hash兼容到IE8以上
会创建hashHistory对象,在访问不同的路由的时候,会发⽣两件事:
HashHistory.push()将新的路由添加到浏览器访问的历史的栈顶
HasHistory.replace()替换到当前栈
history: url不带参数;
history 兼容 IE10 以上
history 模式需要后端配合将所有访问都指向 index.html,否则用户刷新页面,会导致 404
在HTML4中常用的方法:
history.forward():在历史记录中前进一步
history.back():在历史记录中后退一步
history.go(n):在历史记录中跳转n步骤,n=0为刷新本页,n=-1为后退一页。
HTML5中新增了
history.pushState(data[,title][,url]):向历史记录中追加一条记录
history.replaceState(data[,title][,url]):替换当前页在历史记录中的信息
history.state:是一个属性,可以得到当前页的state信息。
window.onpopstate:是一个事件,在点击浏览器后退按钮或js调用forward()、back()、go()时触发。监听函数中可传入一个event对象,event.state即为通过pushState()或replaceState()方法传入的data参数
keep-alive的使用
在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验。
基础知识
<keep-alive>包含动态组件,可以使被包含的组件保留状态,避免重新渲染,实现组件缓存。
<!-- 非活跃的组件将会被缓存! -->
<KeepAlive>
<component/>
</KeepAlive>
被 keep-alive 包含的组件不会被再次初始化,也就意味着不会重走生命周期函数.
当希望缓存的组件能够再次进行渲染, Vue 为我们解决了这个问题,被包含在 keep-alive 中的组件, 此时会多出两个生命周期的钩子: activated 与 deactivated:
activated 在首次挂载,以及每次从缓存中被重新插入的时候调用
deactivated 在从 DOM 上移除、进入缓存 以及组件卸载时调用
// 在index组件页面的activated钩子
activated() {
// isUseCache为false时才重新刷新获取数据
// 因为对index使用keep-alive来缓存组件,所以默认是会使用缓存数据的
if(!this.$route.meta.isUseCache){
this.list = []; // 清空原有数据
this.onLoad(); // 获取数据的函数
}
}
第一次进入:beforeRouterEnter ->created->mounted->activated->deactivated
后续进入时:beforeRouterEnter ->activated->deactivated
// 只缓存组件name为a或者b的组件
<keep-alive include="a,b">
<component />
</keep-alive>
// 组件name为c的组件不缓存(可以保留它的状态或避免重新渲染)
<keep-alive exclude="c">
<component />
</keep-alive>
// 如果同时使用include,exclude,那么exclude优先于include, 下面的例子只缓存a组件
<keep-alive include="a,b" exclude="b">
<component />
</keep-alive>
// 如果缓存的组件超过了max设定的值5,那么将删除第一个缓存的组件
<keep-alive exclude="c" max="5">
<component />
</keep-alive>
<!-- 正则表达式 (需使用 `v-bind`) -->
<KeepAlive :include="/a|b/">
<component />
</KeepAlive>
<!-- 数组 (需使用 `v-bind`) -->
<KeepAlive :include="['a', 'b']">
<component />
</KeepAlive>
配合route使用
// routes 配置
export default [
{
path: '/',
name: 'home',
component: Home,
meta: {
keepAlive: true // 需要被缓存
}
}, {
path: '/profile',
name: 'profile',
component: Profile,
meta: {
keepAlive: false // 不需要被缓存
}
}
]
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
<!-- 这里是会被缓存的视图组件,比如 Home! -->
</router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive">
<!-- 这里是不会被缓存的视图组件,比如 Profile! -->
</router-view>
应用场景
1.tabs切换时保留切换前的操作;
2.前进刷新、后退缓存用户浏览数据和浏览位置;
生命周期
beforeCreate : 数据和方法都不可以被使用
created:可以请求使用和修改数据,但不会更新视图 ,
在created钩子中可以对data数据进行操作,可以进行数据请求将返回的数据赋给data
beforeMount:完成模板的编译,虚拟dom创建完成,即将渲染
mounted:把编译的模板挂载到页面,可以异步请求,也可以访问dom,在这里请求数据会出现闪屏的问题
(模板挂载之前请求未完成)在create请求能够解决问题,
在mounted钩子对挂载的dom进行操作
beforeUpdate:组件即将更新,准备渲染,可以改数据
updated:组件 DOM 已经更新
虽然updated函数会在数据变化时被触发,但却不能准确的判断是那个属性值被改变,所以在实际情况中用 computed或watch函数来监听属性的变化,并做一些其他的操作
activated:keep-alive 组件激活时调用。
deactivated:keep-alive 组件停用时调用。
beforeDestroy:实例销毁之前调用
destroyed:Vue 实例销毁后调用
加载渲染过程:
父beforeCreate->父created-.>父beforeMount->子beforeCreate->子created-.>子beforeMount->子mounted->父mounted
子组件更新过程:
父beforeUpdate->子beforeUpdate->子updated->父updated
销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
v-if 和 v-show 触发的生命周期
https://blog.csdn.net/SpringRolls/article/details/117187075
$nextTick
vue中的nextTick主要用于处理数据动态变化后,DOM还未及时更新的问题
适用场景
第一种:有时需要根据数据动态的为页面某些dom元素添加事件.
这就要求在dom元素渲染完毕时去设置,但是created与mounted函数执行时一般dom并没有渲染完毕,所以就会出现获取不到,添加不了事件的问题,这回就要用到nextTick处理
第二种:在使用某个第三方插件时 ,希望在vue生成的某些dom动态发生变化时重新应用该插件.
这时候就需要在 $nextTick 的回调函数中执行重新应用插件的方法,例如:应用滚动插件better-scroll时
第三种:数据改变后获取焦点
<div id="app">
<div id="div" v-if="showDiv">这是一段文本</div>
<button @click="getText">获取div内容</button>
</div>
<script>
var app = new Vue({
el : "#app",
data:{
showDiv : false
},
methods:{
getText:function(){
this.showDiv = true;
this.$nextTick(function(){
var text = document.getElementById('div').innnerHTML;
console.log(text);
});
}
}
})
</script>
computed与watch区别
1.computed是一个计算属性,watch是监听data中的数据变化
2.computed支持缓存,依赖的属性值发生变化时,计算属性才会重新计算,watch不支持
3.computed不支持异步,watch可以异步
4.computed是第一次加载就监听,watch不是
5.computed需要return,watch不用
6.computed适用于一个数据被好几个数据影响的场景,wacth适用于一个数据影响好几个
computed:计算属性;computed 的值有缓存;依赖其它属性值,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 监听数据的变化;更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
运用场景:
1)当我们需要依赖于其它数据时进行数值计算,应该使用 computed。
因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
2)当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch。
使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得 到最终结果前,设置中间状态。这些都是计算属性无法做到的。
性能优化
1.代码优化 不要把所有数据都放data中
尽可能拆分组件,提高复用性、维护性 keep-alive缓存组件 key值要保证唯一性 合理使用路由懒加载,异步组件
关于异步组件:https://www.cnblogs.com/LIXI-/p/16672518.html
2.加载优化 第三方ui框架按需引入 内容懒加载 图片懒加载
3.用户体验 骨架屏
4.打包优化 cdn形式加载第三方文件
抽离公共文件
5.缓存和压缩
常见的SPA首屏优化方式有哪些
1.路由懒加载
2.异步组件
3.静态资源放在cdn上(图片、文件等)
4.尽量较少dom数量和层级
5.图片不放在本地,用服务器存储,后端返回网址方式访问
6.骨架屏|loading
7.减少请求次数,加快服务器请求响应速度
8.第三方ui框架按需引入
vue路由
基本使用
安装vue-router,命令: npm i vue-router
引入vue-router之后应用插件: Vue.use(VueRouter)
编写router配置项
//该文件专门创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../components/About'
import Home from '../components/Home'
//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
多级路由
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'message',
component:Message
},
{
path:'news',
component:News
}
]
},
]
动态路由
实现方式