2023前端面试

VUE
vue3.0性能提升主要是通过哪几个方面体现的
  1. 响应式实现优化,vue2使用数据劫持需要递归去做响应式处理,vue3使用proxy代理一步到位

  1. 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 中的组件, 此时会多出两个生命周期的钩子: activateddeactivated

  • 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函数会在数据变化时被触发,但却不能准确的判断是那个属性值被改变,所以在实际情况中用 computedwatch函数来监听属性的变化,并做一些其他的操作

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路由
基本使用
  1. 安装vue-router,命令: npm i vue-router

  1. 引入vue-router之后应用插件: Vue.use(VueRouter)

  1. 编写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
                }
            ]
        },
        
    ]
动态路由

实现方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

华而有识

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值