企业级别面试题

133 阅读27分钟

vue和react的区别

共同点

  • 数据驱动视图
  • 组件化
  • 虚拟dom加diff算法

不同点:

  • 核心思想不同
  • 组件写法差异
  • 响应式原理不同

vue的模型是?MVVM和MVC区别

MVC是Model-View- Controller的简写。即模型-视图-控制器。M和V指的意思和MVVM中的M和V意思一样。C即Controller指的是页面业务逻辑。使用MVC的目的就是将M和V的代码分离。MVC是单向通信。也就是View跟Model,必须通过Controller来承上启下。MVC和MVVM的区别并不是VM完全取代了C,只是在MVC的基础上增加了一层VM,只不过是弱化了C的概念,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用,使开发更高效,结构更清晰,增加代码的复用性。

vue是单页还是多页,单页和多页的区别

单页面(Sing Page Application——SPA):顾名思义,只有一个页面。一般是一个主页和多个路由页面组成。

优点:

公共资源不重新加载,局部加载,服务器压力小 切换速度快,用户体验好 前后端分离 缺点:

不利于SEO(可以优化:比如路由懒加载等) 初次加载时耗时多 开发难度较大(相对多页面)

多页面Multi Page Application——MPA):有多个HTML页面,跳转的时候是从一个html页面跳到另一个页面。

优点:

  • 利于SEO。
  • 更容易扩展。
  • 更易数据分析。

缺点:

  • 开发成本高。
  • 服务器压力大。
  • 用户体验相对较差。

uniapp跳转方式

  • uni.navigateTo: 【保留】当前页面,跳转到应用内的某个页面;
  • uni.redirectTo: 【关闭】当前页面,跳转到应用内的某个页面;
  • uni.reLaunch: 【关闭所有】页面,打开到应用内的某个页面。
  • uni.switchTab: 跳转到tabBar页面,并关闭其他所有非tabBar页面。
  • uni.navigateBack: 返回上一个页面,酷似vuerouter.to(-1),
  • uni.preloadPage: 预加载页面,是一种性能优化技术。被预载的页面,在打开时速度更快。

项目中封装过那些组件

比如搜索栏,表格,分页,模态框,表单,然后可以挑选一个你熟悉的组件,介绍一下当时是怎么封装的

说一下axios,用过那些配置,请求成功或者失败会进行哪些操作

请求之前可以判断token是否在vuex中,存在则统一给请求头加上,还可以添加loading,响应时加入状态码的判断,比如状态码200说明接口成功,返回数据,否则抛出错误,当然我们可以和后台人员协商好统一的错误状态码,分别判断,例如登陆过期提示,错误提示

vuex你理解多少

State:存储在store里的数据 读取状态:

直接读取:this.$store.state.XXX

Getter:属性读取和方法读取(类似计算属性) 修改状态:

Mutation:同步

Action:异步

Module

按钮鉴权

首先用户登录时,我们可以用过API接口获取所有菜单和按钮的权限,我们可以把所有按钮信息,保存在sessionStorage中。

const AuthorityData = {
    menus : ['home', 'dashboard'],
    buttons: ['share', 'edit'],
}
// 将按钮权限信息保存起来,防止刷新页面时丢失
sessionStorage.setItem( "permission_button", JSON.stringify(AuthorityData.buttons));

拿vue项目举个栗子,我们可以通过v-if来实现权限的控制,还是比较简单有效的

<el-button v-if="permission_button.includes('edit')">修改</el-button>

<script>
  export default {
      data() {
          return  {
              permission_button: JSON.parse(sessionStorage.getItem("permission_button"))
            }
      }
  }
</script>

我们可以定义一个全局的自定义指令,这样代码就大大的减少了,偷懒才是最舒服的。还是拿vue举例毕竟我只会这个。

import Vue from 'vue';
Vue.directive('btnlimit', {
    // 当被绑定的元素插入到 DOM 中时……
    inserted: (el, binding) => {
        // el 当前绑定的元素 binding.value指令的绑定值
        let permissionList = sessionStorage.getItem('permission_button');
        // 判断一下是否包含这个元素,如果不包含的话,那就让他爸爸元素把子元素扔进垃圾堆
        if (!permissionList.includes(binding.value)) {
            el.parentNode.removeChild(el)
        }
    }
})
// 大家可以把自己定义的指令写在一个directive.js文件中,在main.js总入口引入下就可以了,简单而不失优雅


好了,定义过了全局自定义指令了,我们就可以在所有的vue组件中肆无忌惮的运用它了,不需要单独引用了

<el-button v-btnlimit="'edit'">修改</el-button>

大屏自适应

  // 设计稿的宽度,这里我假设是1920px
        var desginWidth = 1920;
        var desginHeight = 920;
        document.getElementById('scaleContainer').style.width =  `${desginWidth}px`;
        document.getElementById('scaleContainer').style.height =  `${desginHeight}px`;

        function setScale() {
            // 这个是真实浏览器的宽度;手机上,电脑上,改变浏览器宽度都可以,就是最后浏览器展示内容的宽度
            var trueWidth = window.innerWidth;
            var trueHeight = window.innerHeight;
            // 计算设计搞和真实展示宽度的,比例
            var wScale = trueWidth / desginWidth;
            var hScale = trueHeight / desginHeight;
            var scale = Math.min(wScale, hScale);
            document.getElementById('scaleContainer').style.transform = `scale(${scale}) translate(-50%, -50%)`;
        }

        window.addEventListener('resize', setScale);
        setScale();
  1. 视口单位中的“视口”,PC端指的是浏览器的可视区域。
  • vw:1vw 等于视口宽度的 1%。若电脑屏幕分辨率为 1920px,则分成了100份 vw, 每个 vw 的 px 值 为 19.2px;
  • vh:1vh等于视口高度的1%。若电脑屏幕分辨率为 1080px,则分成了100份 vh, 每个 vh 的 px 值 为 10.8px;
  1. 这样我们就可以通过设计稿上面的 px 值得到 vw, vh 的值。如果设计稿上的一个 div 高为 360px, 宽为 120px, 则我们可以在 样式中写为如下
div{
  width: 360/19.2vw;    // 计算得出具体值,保留两位小数
  height: 120/10.8vh;  // 计算得出具体值,保留两位小数
}

vue3和vue2的区别

1、vue3完全支持typescript,提高项目的可维护性
2、Fragment:模板更简单。   vue3用到了一个虚拟的父级,可以多个根节点dom   vue2只能有一个父级节点
3、vue2用 new Vue(); vue3用createApp();   多个实例时,vue2中的vue实例共享一个Vue构造函数,无法做到完全隔离   createApp方法返回一个提供上下文的应用实例,应用实例挂载的整个组件共享同一个上下文
4、vue2 的双向数据绑定是利用ES5  Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现的。   vue3 中使用了 es6 的 ProxyAPI 对数据代理。
5、Vue2与Vue3 最大的区别 —   Vue2使用选项类型API(Options API)对比Vue3合成型API(Composition API)

南京 麦堤微林

知道3维开发吗,有了解什么技术吗

这个不太好回答,如果你说知道,肯定问你技术,对于你们来说,暂时说不了解,可以顺便问一句,公司有人带这个技术吗

前一个公司做的最多的是什么项目(商场,OA...)

一般来说你的公司如果不做电商业务,几乎很少去屑电商项目,大部分的公司都是做后台和小程序还有大屏项目

vue3中状态管理工具使用的是什么和区别

pinia和vuex的区别 (1)pinia它没有mutation,他只有state,getters,action【同步、异步】使用他来修改state数据 (2)pinia他默认也是存入内存中,如果需要使用本地存储,在配置上比vuex麻烦一点

(3)pinia语法上比vuex更容易理解和使用,灵活。 (4)pinia没有modules配置,没一个独立的仓库都是definStore生成出来的

(5)pinia state是一个对象返回一个对象和组件的data是一样的语法

防抖和节流

防抖是触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。适用于可以多次触发但触发只生效最后一次的场景。

function debounce(fn,delay){
    let timer = null //借助闭包
    return function() {
        if(timer){
            clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
        }
        timer = setTimeout(fn,delay)
    }
}

节流是高频事件触发,但在n秒内只会执行一次,如果n秒内触发多次函数,只有一次生效,节流会稀释函数的执行频率。

function throttle(fn,delay){
    let valid = true
    return function() {
       if(!valid){
           //休息时间 暂不工作
           return false 
       }
       // 工作时间,执行函数并且在间隔期内把状态位设为无效
        valid = false
        setTimeout(() => {
            fn()
            valid = true;
        }, delay)
    }
}

应用场景 防抖:

search搜索联想,用户在不断输入值时,用防抖来节约请求资源 window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次 节流:

鼠标不断点击触发,mousedown(单位时间内只触发一次) 监听滚动事件,比如是否滑到底部自动加载更多

具体说明项目中你的职责,具体使用到什么技术

这个时候可以说自己项目具体是做什么用的,然后自己负责的模块,并且用到了那些技术实现这个模块

对Jquery有什么了解吗

1)轻量级、代码简洁 2)强大的选择器,出色的DOM操作封装 3)有可靠的事件处理机制 4)浏览器兼容性好 5)支持链式操作 6)支持丰富的插件

最近在学习什么吗

开放题,不要拘谨,想到啥技术就说啥

怎么学习一个新技术,在网上找不到该技术的资料时

看看有没有对应的官方文档去学校,买点书籍去学习,翻墙去国外找等

为什么要从上一家公司离职

面试之前就要想好具体说辞

数学学的怎么样,还记得线性代数吗

看个人,忘了就是忘了

期望薪资,上一家公司的离职薪资

首先自己期望多少,上一家薪资在期望上少个1000左右就行

未来的职业规划

职业规划,看个人能力,有的是只能做业务,有的可以做组长

南京 中软

css ,less主题色换肤怎么实现

lessmodifyVars方法

modifyVars方法是是基于 less 在浏览器中的编译来实现。所以在引入less文件的时候需要通过link方式引入,然后基于less.js中的方法来进行修改变量
less.modifyVars({
  \'@themeColor\': \'blue\'
});

引入主题色文件
<link rel="stylesheet/less" type="text/css" href="./src/less/public.less" />

更改主题色的事件
// color 传入颜色值
handleColorChange (color) {
    less.modifyVars({  // 调用 `less.modifyVars` 方法来改变变量值\'         @themeColor\':color
         })
    .then(() => {
         console.log(\'修改成功\');
    });
};

使用css变量来进行主题色的修改,替换主题色变量,然后用setProperty来进行动态修改
body{
   --themeColor:#000;
}

.main{
   color: var(--themeColor);
}
document.body.style.setProperty(\'--themeColor\', \'#ff0000\');

less和css区别

1、Less是一门CSS预处理语言,css是一种用来表现HTML或XML等文件样式的计算机语言。

2、less扩展了CSS语言,增加了变量、Mixin、函数等特性。

3、css可以被浏览器直接识别,less需要先编译为css。

数组去重

  1. new Set()实现数组去重

  2. 双重for循环,第一层循环确保数组中的每一项都能被比较,第二层循环确保被比较项后的每一项都能跟被比较项比较。

  3. 利用filter()+indexOf()方法去重

    indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。

  4. some()+循环去重

    some() 方法用于检测数组中的元素是否满足指定条件(函数提供) 。 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。 如果没有满足条件的元素,则返回false。 我们可以定义一个新数组来承接没有重复的数据,遍历原始数组的时候,用新数组来判断数据是否已经出现过。

数据双向绑定底层原理

1.双向数据绑定是通过数据劫持结合发布订阅者的模式和object.defineproprety()来劫持各个属性的setter、getter,如果数据有变动,就发布消息给订阅者触发监听。

2.双向数据绑定的步骤: **第一步:**实现一个数据监听器observer,能够对数据对象的所有属性就行监听。如果有变动就拿到最新值并通知订阅者。 **第二步:**实现一个指令解析器compile,对每个元素节点和指令进行扫描和解析,根据指令模板替换数据以及绑定相应的更新函数。 **第三步:**实现一个watcher,作为链接observer和compile之间的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图。 **第四步:**实现一个MVVM作为数据绑定的入口,作为Observer、compile、watcher之间的桥梁,通过observer来监听自己的modle数据变化,通过compile来解析扫描模板指令,最终利用watcher搭起observer和compile之间的桥梁,实现双向数据绑定的效果。

js0.1+0.2为什么不等于0.3

问题原因: 因为计算机硬件存储数据时,是以二进制(10101010)形式进行存储的。所以计算机计算0.1+0.2的时候,实际上是计算的两个数的二进制的和。

解决:

1、使用toFixed()最简单的方法,四舍五入,只保留小数点后1位,注意toFixed()返回值的类型是String(字符串) 类型

2、将其转换为整数后在进行运算,运算后再转为对应的小数

3、使用第三方库( Math.js 、 big.js )

js为什么可以放在谷歌浏览器运行

JS代码之所以能够在浏览器中运行,是因为浏览器中它嵌入了一种JavaScript引擎(在这里我们把JavaScript引擎称为JS引擎,又称为:JavaScript虚拟机),而JS引擎它可以把JS代码解析成浏览器能够识别的代码,因此JS代码可以在含有JS引擎的浏览器中运行。

登录页怎末做

1,表单验证

2,调用封装好的接口函数

3,收集用户参数,上传给上一步的函数

4,经过请求拦截器,添加请求头

5,为解决跨域问题,代理转发

6,要求后端开启服务器

7,经过响应拦截器处理

8,得到接口调用之后结果

9,保存token到vuex

10,token做持久化

菜单权限怎么做

1.后端返回权限码存放在SessionStorage中,前端根据权限码生成对应的动态菜单menu。

2.前端在beforeRouter的守卫导航中,判断是否已经生成对应的router,若没有,则生成对应的router,添加到总router中。

3.动态菜单List和动态router存放在vuex中。

4.若是跳转回登陆页面,则要清空SessionStorage中的权限码以及清空vuex的动态菜单和动态router。

5.请求接口时,每次请求都在请求头中带上token,后端用于做权限控制。

webscoket怎末用

一般我们前后端交互都是使用http,http是前端发起一个请求,后端回复。它的特点就是前端发起请求后端返回数据,一次交互就没了。而我们在聊天的时候,A给B发送了一个消息,我们后台接收到了消息然后主动推送给B去显示。 websocket是一个双向通信的协议,前后端都可以主动的去发送消息。websocket本质上也是一个请求连接,所以我们也可以像http请求一样传递连接参数。当我们连接成功后,后端会产生一个session,我们可以通过这个session去发消息(它里面提供了一个发送消息的方法) 1.创建一个webSocket对象

2.链接成功的函数onopen

3.链接失败的函数onerror

4.向服务端发送请求send

5.接收消息时触发onmessage

6.链接关闭onclose

国家电网外包

js数据类型

基本数据类型:String、Number、Boolean、Null、Undefined、Symbol、BigInt

引用数据类型:Object【Object是个大类,function函数、array数组、date日期...等都归属于Object】

在ES6 set map

  1. Map是键值对,Set是值的集合,当然键和值可以是任何的值;

  2. Map可以通过get方法获取值,而set不能因为它只有值;

  3. 都能通过迭代器进行for...of遍历;

  4. Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储

  5. map和set都是stl中的关联容器,map以键值对的形式存储,key=value组成pair,是一组映射关

系。set只有值,可以认为只有一个数据,并且set中元素不可以重复且自动排序。

扁平转树形,如何格式化查找, find,父级节点PID,找出子节点ID,判断

/**
 *
 * @param {Array} data
 * @param {string} pid 子树找父级的标识,这里面默认子树的标识为id,如果不为id,就再传一个子树id标识
 * @param {string} child 自定义子树字段名称
 * @returns
 */
export function makeTree(data,pid,child){
    let parents = data.filter(p => p[pid] === '0' ),
        children = data.filter(c => c[pid] !== '0');
    dataToTree(parents, children);
    return parents;
 
function dataToTree(parents, children){
  parents.map(p => {
    children.map((c, i) => {
      if(c[pid] === p.unionId){
        let _children = JSON.parse(JSON.stringify(children));
        _children.splice(i, 1);
        dataToTree([c], _children);
        if(p[child]){
          p[child].push(c);
        }else{
          p[child] = [c];
        }
      }
    })
  })
}
}

ts泛型应用场景?

使用泛型可以创建泛型函数、泛型接口,泛型类

存储的区别 ,前端其他缓存方式?

localStorage

1.存储时间是永久存储。 2.大小在5M左右。 3.ie低版本或者一些使用无痕浏览器都是不支持的 4.存储的是字符串,内容过多时,会消耗内存空间,让页面变卡 5.本地存储,不会和服务器有交互

sessionStorage

大致和localStorage一样,区别,不是永久存储,窗口关闭,随之清除

http协商缓存 强制缓存

强缓存,设置一个过期时间,让客户端在过期前使用本地缓存,直到过期才请求更新鲜的资源。涉及的头字段有 Cache-Control: max-age=Expires

协商缓存,在客户端缓存过期的情况下,和服务端协商一下,是否可以继续使用本地缓存。涉及的头字段有 Last-Modified / If-Modified-SinceETag / If-None-Match

echarts页面大小变化之后的适配?

window.onresize = function () {
       this.myChart.resize();
       // .resize后加括号哦,这里还可以写其他的事件
};

vue插槽 应用场景

flex布局和table布局浮动布局等一些老布局方式的区别

table布局-表格
1table布局:
父级容器 display: table;
子级容器 display:table-cell;
(1)、空间平均划分:子级容器默认是自动平分宽度沾满父级容器;
(2)、设置其中一个table-cell为固定宽度:如果固定好其中一个子级容器,那么其余子级容器会自动平分宽度沾满父级容器;
(3)、设置每一个table-cell为固定宽度;
(4)、把此元素放置在父元素的中部,即垂直居中—>vertical-align:middle
(5)、等高对齐:
不对右侧的box设置display:table-cell,只对左侧,就会出现左侧跟随右侧高度变化而变化,如果要实现不管两个box哪个高度产生变化另一个就跟随,只需要把右侧的box也设置成display:table-cell就可以实现了。

2table布局的优缺点:
缺点
(1)、table 比其他html标签占更多的字节。造成下载时间延迟,占用服务器更多的流量资源(代码冗余)。
(2)、table 会阻挡浏览器渲染引擎的渲染顺序,会延迟页面的生成速度,让用户等待时间更久。
(3)、灵活性差,一旦设计确定,后期很难通过CSS让它展现新的面貌。
(4)、不利于搜索引擎抓取信息,直接影响到网站的排名。
优点
(1)、兼容性好。
(2)、容易上手。

float布局-浮动
1、特点:非完全脱离文档流
(1)、元素"浮动";
(2)、脱离文档流;
(3)、不脱离文本流;
说明:浮动的块元素会脱离正常的文档流,但是还会占用原有文档流的文本空间。

2、对自身的影响:形成“块”(BFC–块格式化上下文)
(1)、父级元素下含非float元素:
float元素宽度之和刚好等于父级元素宽度,所有子级元素宽度大于父级元素;浮动元素会随着浮动方向将非浮动元素顶到末尾,顶不出去了就最末尾的地方浮动在非浮动元素下方(类似于高度塌陷)。
(2)、父级元素下不含非float元素:
float元素宽度之和刚好等于父级元素宽度,正常按浮动方向浮动排序。
(3)、优缺点
缺点:脱离文档流,需要清楚浮动,高度塌陷(float的破坏性主要是指它会使父容器的高度塌陷,也就是父元素在对高度计算的时候会忽略浮动的元素)。
优点:兼容性好,比较简单。

absolute布局-绝对定位
说明:参考css-position:absolute
(1)、优缺点
缺点:绝对定位是脱离文档流的,意味着下面的所有子元素也会脱离文档流,这就导致了这种方法的有效性和可使用性是比较差的。
优点:很快捷,设置很方便,而且也不容易出问题,你可以很快的就能想出这种布局方式。

flexbox布局-弹性盒子布局
CSS3弹性盒(Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。Flexbox布局(Flexible Box)模块旨在提供一个更加有效的方式制定、调整和分布一个容器里的项目布局(基于一维),即使他们的大小是未知或者是动态的,称为Flex;它是一种CSS快速布局方式,相比于传统文档流布局方式,具有简洁、高效和响应式、兼容强等优点。

es6 class和传统构造函数的区别

1.类的内部所有定义的方法,都是不可枚举的(但是在es5中prototype的方法是可以进行枚举的)

2.类的this指向是严格模式"use strict"所以函数内部的this是underfined (但是在es5中里的构造函数this指向为window)

3.ES6可以继承静态方法,而构造函数不能

4.class 只能通过new 实例

typeof instancerof区别

typeof会返回一个变量的基本类型,instanceof返回的是一个布尔值 instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型 而typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了function 类型以外,其他的也无法判断

uniapp的理解

uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。

前后端联调? 接口文档是怎么做的,直接给word还是第三方工具?

可以说是word 或者 swagger或者Markdown,最后最垃圾的是发聊天消息给你

有了接口对应的地址,但是接口还没写好怎么办?

一般可以使用mockj.s、JsonServer等模拟接口数据

工作中遇到无法解决的问题如何处理?

首先看逻辑问题,还是不会使用问题,还是功能问题,这个都可以互相交流,寻找解决方案

react常用的生命周期有哪些

  1. 挂载
  • constructor()
  • render()
  • componentDidMount()
  1. 更新
  • render()
  • componentDidUpdate()
  1. 卸载
  • componentWillUnmount()

react常用的hooks

useEffect 、useState、useMomo、useCallback、useRef、use

useEffect怎么实现组件挂载 和 卸载

带参数、不带参数、传入空数组

你对jsx的理解,它最终会被编译成什么

创建 JSX 语法的本质目的是为了使用基于 xml 的方式表达组件的嵌套,保持和 HTML 一致的结构,语法上除了在描述组件上比较特别以外,其它和普通的 Javascript 没有区别。 并且最终所有的 JSX 都会编译为原生 Javascript。

谈谈你对高阶组件的理解 怎么实现(怎么写)

高阶组件可以看作 React 对装饰模式的一种实现,高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。高阶组件( HOC )是 React 中的高级技术,用来重用组件逻辑。但高阶组件本身并不是 ReactAPI 。它只是一种模式,这种模式是由 React 自身的组合性质必然产生的。

类组件和函数组件区别

①设计思想不同:函数式组件是函数式编程思想,而类组件是面向对象编程思想。面向对象编程将属性和方法封装起来,屏蔽很多细节,不利于测试

②类组件有状态管理,而函数式组件的状态需要使用useState自定义。

③创建组件时,函数式组件只需调用函数即可创建组件,而类组件必须先实例化一个对象,然后通过这个实例化对象调用render函数来创建组件

④类组件是用生命周期钩子函数来实现业务逻辑的,而函数式组件使用react Hooks来实现业务逻辑。

react父传子 子传父 跨组件传参

父传子: 父组件通过在在组件标签上绑定属性来传参 , 子组件通过 props 属性 来接收参数

子传父: 父组件通过在在组件标签上绑定子组件定义的方法属性(形参是接收的参数)来接收参 , 子组件通过在 props 属性上添加自定义的方法来向父组件传递参数

跨组件传参: context实现在跨组件通信,一般用于自定义组件

react怎么实现路由守卫,你路由守卫里做了哪些逻辑

react实现路由拦截的基本思路还是利用Route 的render函数。通过判断拦截条件来实现不同的组件的跳转,从而实现拦截。在之前的版本中,React Router 也提供了类似的 onEnter 钩子,但在 React Router 4.0 版本中,取消了这个方法。React Router 4.0 以后采用了声明式的组件,路由即组件,要实现路由守卫功能,就得我们自己去写了。

为什么React事件处理中要绑定this

react需要绑定this的原因:在组件上绑定事件监听器,是为了响应用户的交互动作,特定的交互动作触发事件时,监听函数中往往都需要操作组件某个状态的值,进而对用户的点击行为提供响应反馈

useState和useRef的区别

1.useState的值在每个render中都是独立存在的。而useRef.current则更像是相对于render函数的一个全局变量,每次他会保持render的最新状态。

2.useState值的更新会触发组件重新渲染,而useRef的current不会触发重渲染。

3.useRef不仅用于Dom引用,“ref”对象是通用容器,其当前属性是可变的,并且可以保存任何值,类似于类的实例属性。

4.如果一个变量是决定视图图层渲染的变量,请使用useState,其他用途用useRef

hooks没有用到React,为什么还需要import引入React

本质上来说JSX是React.createElement(component, props, ...children)方法的语法糖。 所以我们如果使用了JSX,我们其实就是在使用React,所以我们就需要引入React

webpack常用的插件有哪些

webpack-dev-server 、 html-webpack-plugin、terser-webpack-plugin 去掉console.log、debugger、注释、

compression-webpack-plugin 压缩文件, 在传输的时候用gzip压缩,提高资源访问速度。

svg-sprite-loader 加载器

splitChunks 模块分割,为了节省打包时间

预加载 preload,提高用户操作体验

你项目中做了哪些优化

v-if和v-show区分使用场景

(v-if是真正的条件渲染,切换过程中是销毁和重建的,v-show就相当于CSS中的display属性切换)

computed和watch区分使用场景

(computed是计算属性,依赖的属性值发生改变,下一次获取computed的值才会重新计算它的值,watch更多地是观察,)

长列表性能优化

有时候我们的组件是纯粹的数据展示,不会有改变,就不需要Vue劫持我们的数据。可以通过Object.freeze方法冻结一个对象,一旦被冻结的对象就不再被修改了

事件的销毁

Vue组件销毁时,自动清理它与其他实例的连接,但仅限于组件本身事件,如果在JS内使用addEventListense等方法不会自动销毁,我们需要在组件中手动移除这些事件的监听,避免内存泄漏。

图片资源的懒加载

图片过多的页面,为了加速页面加载速度,我们可以等滚动到可视区域再去加载。在项目中可以使用vue-lazyload。然后在vue文件中将img标签的src改为v-lazy,图片的显示方式更改为懒加载显示

<img v-lazy="/static/img/1.png">
路由懒加载(实现方式在(3.路由Vuex中))

Vue是单页面应用,会有很多路由引入,这样webpack打包之后的文件很大,当加载资源过多时,页面会出现白屏的现象,所以我们可以把不同路由对应的组件分割成不同的代码块,在路由被访问的时候才加载对应的组件。

第三个插件按需引入

借助babel-plugin-component。按需引入需要的组件,达到减少项目体积的目的。

优化无限列表性能

如果存在非常长或者无限滚动的列表,需要采用窗口化的技术来优化性能,只需要渲染少部分区域的内容,减少重新渲染组件和创建dom节点的时间

服务端渲染SSR/预渲染

渲染的优点:

更好的SEO

更快的内容到达时间(首屏加载更快)

ant design怎么按需引入

安装babel-plugin-import,然后再package.json配置

ts interface和type区别

1.typeof 的类型别名可以用于其他的类型,比如 联合类型、元组类型、基本类型,interface 不行。

2.type 的别名不可以多次定义会报错,而 interface 则可以多次定义,会将其视为合并到一起。

3.type 能用 in 关键字,而interface不行。

4.默认导出的方式不同,inerface 支持同时声明,默认导出,而type必须先声明后导出

5.扩展方式不同,interface 用 extends 来扩展,而type 用 & 操作符扩展

蓝多瑙

在地址栏输入地址回车后发生了啥?

  1. 解析url地址

  2. DNS解析

  3. TCP链接

  4. 发送http请求

  5. 服务器接收请求

  6. 服务器响应

  7. TCP链接断开

  8. 浏览器解析资源

    最后每一个有可能需要详细解释,所以自己可以去关注下

说说你对前端优化的理解?

一是资源加载

1.多使用内存、缓存和其他方法

2.减少CPU计算量,减少网络加载耗时。

以上适用所有编程的性能优化-空间换时间

3.减少资源体积:压缩代码,图片精灵

4.减少访问次数:合并代码(js模块化,最后打包成一个JS)、SSR服务器端渲染,缓存
二是让渲染更快

1.css放在head,js放在body下面

2.尽早开始执行js,用DOMcontentLoaed触发

3.懒加载(图片懒加载,上滑更多)

4.对DOM查询进行缓存

5.频繁DOM操作,合并到一起进行Dom操作,如存入createDocumentFragment中
6.节流和防抖

说一下浏览器的内核?

IE、Firefox、GoogleChrome、Safari、Opera。

封装一个函数如何获取div的属性?

function getStyle(obj,attr){
        if(obj.currentStyle){
            return obj.currentStyle[attr];
        }else{
            return getComputedStyle(obj,null)[attr];
        }
    }

线程与进程你是怎么理解的。

进程和线程 概念

进程:程序的一次执行,它占有一片独有的内存空间

线程:是进程内的一个独立执行单元,是程序执行的一个完整流程,是CPU的最小的调度单元

单线程和多线程 概念

单线程:一个进程内有一个线程

说说你对promise的理解

一个promise有三种状态:

  • pending:表示初始状态,可以转移到 fullfilled 或者 rejected 状态
  • fulfilled:表示操作成功,不可转移状态
  • rejected:表示操作失败,不可转移状态

不同状态去实现resolve、reject