知识点总结

目录

1、SPA(单页应用)首屏加载速度慢怎么解决?

首屏加载慢的原因:

解决方法:

2、Vue中自定义指令的理解,应用场景有哪些?

一、什么是指令

二、如何实现

三、应用场景

3、说说React生命周期中有哪些坑?如何避免?

哪些坑?

如何避免?

4、说说Real diff算法是怎么运作的?

5、调和阶段setState做了什么?

6、为什么React元素有一个$$type属性?

这个 $$typeof 是什么? 

为什么需要 $$typeof

7、说说Connect组件的原理是什么?

原理

作用

8、说说你对fiber架构的理解?解决了什么问题?

是什么?

如何解决?

9、说说你对事件循环event loop的理解?

10、前端跨域的解决方案?

11、说说你对vue中mixin的理解?

是什么?

特点?

与vuex的区别

与公共组件的区别

12、for...in循环和for...of循环的区别?

13、说说你对Object.defineProperty()的理解?

14、说说你对webSocket的理解?

15、最少说出三种前端清除浮动的方法?

16、说说你对git rebase 和git merge的理解?区别?

理解:

区别:

17、说说你对栈、队列的理解?应用场景?

是什么?

应用场景

18、前端性能优化的手段有哪些?

19.大文件如何做断点续传?

20.原生js如何实现上拉加载下拉刷新?

1.上拉加载

2.下拉刷新


1、SPA(单页应用)首屏加载速度慢怎么解决?


首屏加载慢的原因:

1.网络延迟问题

2.资源文件体积是否过大

3.资源是否重复发送请求去加载了

4.加载脚本的时候,渲染内容堵塞了

解决方法:

1.减少入口文件体积

2.静态资源本地缓存

3.UI框架按需加载

4.图片资源的压缩

5.组件重复打包

6.开启GZip压缩

7.使用SSR

2、Vue中自定义指令的理解,应用场景有哪些?

一、什么是指令

指令系统是计算机硬件的语言系统,也叫机器语言,它是系统程序员看到的计算机的主要属性。因此指令系统表征了计算机的基本功能决定了机器所要求的能力

vue中提供了一套为数据驱动视图更为方便的操作,这些操作被称为指令系统

我们看到的v-开头的行内属性,都是指令,不同的指令可以完成或实现不同的功能

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令

二、如何实现

注册一个自定义指令有全局注册与局部注册

全局注册注册主要是用过Vue.directive方法进行注册

Vue.directive第一个参数是指令的名字(不需要写上v-前缀),第二个参数可以是对象数据,也可以是一个指令函数

局部注册通过在组件options选项中设置directive属性

三、应用场景

用自定义组件组件可以满足我们日常一些场景,这里给出几个自定义组件的案例:

  • 防抖

  • 图片懒加载

  • 一键 Copy的功能

3、说说React生命周期中有哪些坑?如何避免?


哪些坑?


1.getDerviedStateFromProps容易编写反模式代码,使受控组件和非受控组件容易混乱

2.网络请求应该放在componentDidMount生命周期钩子函数中

3.ComponentWillReceivedProps被getDerviedStateFromProps所取代,主要因为性能问题

4.ShouldcomponentUpdate通过返回true或false来确定是否要渲染更新

5.componentWillUpdate 同样是由于新的异步渲染机制,而被标记废弃,不推荐使用,原先的逻辑可结合 getSnapshotBeforeUpdate 与 componentDidUpdate 改造使用。

如何避免?


不在恰当的时候调用不该调用的代码

在该调用的时候不要忘记调用

4、说说Real diff算法是怎么运作的?

虚拟DOM在react中不提倡使用真实的DOM节点,使用虚拟DOM可以提高渲染的速度,在界面发生变化时,通过diff算法对比新旧DOM树,如果用变化,则渲染变化的DOM节点,反之则不该

diff算法:是用来对比两个虚拟DOM树的,通过key属性,如果有key属性,就进行新旧DOM树的比对,如果没有就重新渲染,在进行新旧DOM树比对的时候,如果内容没发生改变,就不要重新渲染了,如果发生了改变,则只重新渲染发生改变的dom节点

5、调和阶段setState做了什么?


在组件中调用了this.setState这个函数之后,react会将传入的参数与当前组件的状态进行合并,然后触发所谓的调和过程。

经过调和之后,react会以高效地方式根据新的状态构建一个react元素数,并且着手渲染整个UI页面。

react得到元素树后,react会进行diff算法进行对比,对比出新树与旧树的差异,然后根据差异对界面进行最小化的更新渲染。

在差异计算算法中,react能够相对准确地知道那些位置放生了改变以及应该如何改变,这就保证了按需更新,而不是全部更新

6、为什么React元素有一个$$type属性?

这个 $$typeof 是什么? 


各种前端框架出现之前,应用通常会构造 HTML 并将它们插入到 DOM 中,例如:

const messageEl = document.getElementById(‘message’);
messageEl.innerHTML = ‘<p>’ + message.text + ‘</p>’;


这代码一般能正常工作,除非你的 message.text 返回 ‘<img src οnerrοr=”stealYourPassword()”>’ 这样的字符串。
为了防止这种情况,可以使用类似于 document.createTextNode()或textContent 仅处理 text 的 api。也可以通过预处理替换 < > 这类特殊的字符。但是这样还是有很多潜在的问题。所以现代前端框架像 React 会为字符串转义成文字内容:
<p>
{message.text}
</p>
就算 message.text 返回 <img> 也会当成字符串处理。要在 React 元素中呈现 HTML ,则需要编写dangerouslySetInnerHTML={{ __html: message.text }},这有助于你在审查代码的时候重视它。
但是这样仍然无法完全禁止注入攻击,例如:<a href={user.website}>,注意 website 为 ‘javascript: stealYourPassword()’的情况。 对用户输入使用 … 运算符也很危险 <div {…userData}>。 

为什么需要 $$typeof

通过上面的介绍我们知道,$$typeof 是为了防止 XSS 攻击。

React 0.14 使用 Symbol 标记每个 React 元素。

{
type: ‘marquee’,
props: {
bgcolor: ‘#ffa7c4’,
children: ‘hi’,
},
key: null,
ref: null,
$$typeof: Symbol.for(‘react.element’),
}


这样就可以规避这个问题,使用 Symbol 类型是因为 JSON 中无法传递 Symbol。React 会检查 element.$$typeof 然后拒绝处理非法的元素。

7、说说Connect组件的原理是什么?

原理

connect([mapStateToProps], [mapDispatchToProps])(component)


看connect使用方法,接收参数为mapStateToProps和mapDispatchToProps两个方法,返回的函数接收参数是组件,从而返回一个新的组件。

在入口文件 中使用Provider组件,在原应用组件上包裹一层,使原来整个应用成为Provider的子组件,接收Redux的store作为props,通过context对象传递给子孙组件上的connect

connect真正连接 Redux 和 React,它包在我们的容器组件的外一层,它接收上面 Provider 提供的 store 里面的 state 和 dispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。


总结:react-redux 库提供的一个 API,connect 的作用是让你把组件和store连接起来,产生一个新的组件(connect 是高阶组件)
 

作用

(1)原组件和store做连接

(2)connect方法使得UI组件变成了容器组件(包含了业务逻辑和数据状态管理)

(3)connect使得组件和store的数据同步关联,connect: store的state数据一变,组件的state会跟着变

(4)属于是一个高阶组件,本质上是一个函数

8、说说你对fiber架构的理解?解决了什么问题?

是什么?

Fiber 是 Facebook 花费两年余时间对 React 做出的一个重大改变与优化,是对 React 核心算法的一次重新实现。从Facebook在 React Conf 2017 会议上确认,React Fiber 在React 16 版本发布

在react中,主要做了以下的操作:

为每个增加了优先级,优先级高的任务可以中断低优先级的任务。然后再重新,注意是重新执行优先级低的任务

增加了异步任务,调用requestIdleCallback api,浏览器空闲的时候执行

dom diff树变成了链表,一个dom对应两个fiber(一个链表),对应两个队列,这都是为找到被中断的任务,重新执行

从架构角度来看,Fiber 是对 React核心算法(即调和过程)的重写

从编码角度来看,Fiber是 React内部所定义的一种数据结构,它是 Fiber树结构的节点单位,也就是 React 16 新架构下的虚拟DOM

一个 fiber就是一个 JavaScript对象,包含了元素的信息、该元素的更新操作队列、类型


如何解决?

Fiber把渲染更新过程拆分成多个子任务,每次只做一小部分,做完看是否还有剩余时间,如果有继续下一个任务;如果没有,挂起当前任务,将时间控制权交给主线程,等主线程不忙的时候在继续执行

即可以中断与恢复,恢复后也可以复用之前的中间状态,并给不同的任务赋予不同的优先级,其中每个任务更新单元为 React Element 对应的 Fiber节点

实现的上述方式的是requestIdleCallback方法

window.requestIdleCallback()方法将在浏览器的空闲时段内调用的函数排队。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应

首先 React 中任务切割为多个步骤,分批完成。在完成一部分任务之后,将控制权交回给浏览器,让浏览器有时间再进行页面的渲染。等浏览器忙完之后有剩余时间,再继续之前 React 未完成的任务,是一种合作式调度。

该实现过程是基于 Fiber节点实现,作为静态的数据结构来说,每个 Fiber 节点对应一个 React element,保存了该组件的类型(函数组件/类组件/原生组件等等)、对应的 DOM 节点等信息。

作为动态的工作单元来说,每个 Fiber 节点保存了本次更新中该组件改变的状态、要执行的工作。
 

9、说说你对事件循环event loop的理解?


JavaScript是一门单线程的语言,也就是说同一时间只能去做一件事情,为了解决单线程的阻塞问题,JavaScript用到了一种计算机的运行机制,这种运行机制就叫做事件循环

在JavaScript中所有的任务都可以分为:

同步任务:立即执行的任务,同步任务一般会直接进入到主线程中进行执行

异步任务:同步任务执行完之后才会执行异步任务;比如ajax请求,setTimeout定时函数

10、前端跨域的解决方案?


1.JSONP

2.nginx代理

3.WebSocket协议跨域

4.CORS

11、说说你对vue中mixin的理解?

是什么?

混入 (mixins): 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

特点?

1 方法和参数在各组件中不共享

2 值为对象的选项,如methods,components等,选项会被合并,键冲突的组件会覆盖混入对象的

3 值为函数的选项,如created,mounted等,就会被合并调用,混合对象里的钩子函数在组件里的钩子函数之前调用

与vuex的区别

  • vuex:用来做状态管理的,里面定义的变量在每个组件中均可以使用和修改,在任一组件中修改此变量的值之后,其他组件中此变量的值也会随之修改。

  • Mixins:可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的,值的修改在组件中不会相互影响。

与公共组件的区别

同样明显的区别来再列一遍哈~

  • 组件:在父组件中引入组件,相当于在父组件中给出一片独立的空间供子组件使用,然后根据props来传值,但本质上两者是相对独立的。

  • Mixins:则是在引入组件之后与组件中的对象和方法进行合并,相当于扩展了父组件的对象与方法,可以理解为形成了一个新的组件。

12、for...in循环和for...of循环的区别?


for...in和for...of都是JavaScript中遍历数据的方法

for...in是为遍历对象属性而构建的,它以任意顺序遍历一个对象的除Symbol以外的可枚举属性,可用break或者throw跳出

for...of语句在可迭代对象上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句(包括Array,Map,Set,String,TypedArray,arguments等等,不包括Object),可用break或者throw跳出。

13、说说你对Object.defineProperty()的理解?


Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

该方法接受三个参数:

obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性

 var obj = {test:'sss'}
  Object.defineProperty(obj,'test',{
      value:任意类型的值, //不设置该属性 ,默认为undefined
      configurable: true | false, // 是否可以delete删除目标属性或者是否可以再次修改属性的特性
      enumerable: true | false,   //是否可以被枚举(for..in |Object.keys())
      writable: true | false   //是否可以被重写
  })
var obj = {}
  var initValue = 'hello'
  Object.defineProperty(obj,"newKey",{
         get:function(){ return initValue;} | undefined,   //不设置get方法,则默认undefined
         set:function(value){ initValue = value; } | undefined,
         configurable: true | false,
         enumerable: true | false
  })

14、说说你对webSocket的理解?

WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。依靠这种技术可以实现客户端和服务器端的长连接,双向实时通信。

它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

其他特点包括:

  1. 建立在 TCP 协议之上,服务器端的实现比较容易。
  2. 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  3. 数据格式比较轻量,性能开销小,通信高效。
  4. 可以发送文本,也可以发送二进制数据。
  5. 没有同源限制,客户端可以与任意服务器通信。
  6. 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

协议标识符是ws(如果加密,则为wss),服务器网址就是 URL

15、最少说出三种前端清除浮动的方法?


使用带clear属性的空元素

使用css的overflow属性

使用css的::after属性

16、说说你对git rebase 和git merge的理解?区别?

理解:

git rebase 和 git merge 都是将一个分支的提交合并到另一分支上

通过 merge 合并分支会新增一个 merge commit 然后将两个分支的历史联系起来

rebase 会将整个分支移动到另一个分支上,主要的好处是历史记录更加清晰,不好的是会丢失一些分支从何时创建及合并进来的一些信息。

区别:

merge

通过merge合并分支会新增一个merge commit,然后将两个分支的历史联系起来

其实是一种非破坏性的操作,对现有分支不会以任何方式被更改,但是会导致历史记录相对复杂

rebase

rebase会将整个分支移动到另一个分支上,有效地整合了所有分支上的提交

主要的好处是历史记录更加清晰,是在原有提交的基础上将差异内容反映进去,消除了 git merge所需的不必要的合并提交

17、说说你对栈、队列的理解?应用场景?

是什么?


栈:又名堆栈,它是一种运算受限的线性表,限定仅在表尾进行插入和删除操作的线性表,

队列:跟栈十分相似,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作

应用场景


栈:借助栈的先进后出的特性,可以简单实现一个逆序数处的功能,首先把所有元素依次入栈,然后把所有元素出栈并输出

栈的特点就是跟坐电梯一样,先进的后出,后进的先出

队列:当我们需要按照一定的顺序来处理数据,而该数据的数据量在不断地变化的时候,则需要队列来帮助解题队列的使用广泛应用在广度优先搜索种

队列的特点就是跟排队一样

18、前端性能优化的手段有哪些?


前端性能优化分为两类:

1.文件加载更快:

① 让传输的数据包更小(压缩文件/图片):图片压缩和文件压缩

②减少网络请求的次数:雪碧图/精灵图、节流防抖

③减少渲染的次数:缓存(HTTP缓存、本地缓存、Vue的keep-alive缓存等)

2.文件渲染更快:

①提前渲染:ssr服务器端渲染

②避免渲染阻塞:CSS放在HTML的head中 JS放在HTML的body底部

③ 避免无用渲染:懒加载

④ 减少渲染次数:对dom查询进行缓存、将dom操作合并、使用减少重排的标签
 

19.大文件如何做断点续传?

1.客户端下载一个1024K的文件,已经下载了其中512K

2. 网络中断,客户端请求续传,因此需要在HTTP头中申明本次需要续传的片段:

Range:bytes=512000-

这个头通知服务端从文件的512K位置开始传输文件

3. 服务端收到断点续传请求,从文件的512K位置开始传输,并且在HTTP头中增加:

Content-Range:bytes 512000-/1024000

并且此时服务端返回的HTTP状态码应该是206,而不是200。

20.原生js如何实现上拉加载下拉刷新

1.上拉加载

使用场景:移动端历史日志、内容列表等模块中使用

简述:当列表滑动到底部时,再做请求加载下一页列表,有利于减少http请求和浏览器渲染压力,提高页面首次加载速度

原理:

获取滑动内容外部盒子高度:document.querySelector(".container").clientHeight

获取整个内容的高度:document.querySelector(".ul").scrollHeight

获取卷曲出去的高度:let tops = document.querySelector(".container").scrollTop

外部盒子高度+卷曲出去的高度>=内容的高度 - 离底部距离高度(自定义)

监听滑动事件scroll 当满足以上条件时执行异步请求,这里需要加一个节流,当触发是禁止再次触发,等到异步事件加载完毕后,才允许再次上拉触发。

2.下拉刷新

简述:向下滑动页面刷新数据

原理:

监听touchstart、touchmove、touchend三个事件

通过touchstart记录手指触摸时位置

通过touchmove记录向下滑动的距离,同时通过设置transform:translateY(x)来设置内容向下移动,控制滑动距离到达某个值时,禁止页面再做滑动

通过touchend记录手指离开事件,对滑动距离达到限定值时,做刷新请求数据处理,未到限定值时自动回弹translateY(0px),并添加过渡动画

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="viewport"
        content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
</head>
<style type="text/css">
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .container {
        width: 100vw;
        height: 100vh;
        overflow: scroll;
    }

    .ul li {
        width: 100%;
        height: 70px;
        line-height: 70px;
        border-bottom: 1px solid #000000;
        text-align: center;
    }

    .tip {
        width: 100%;
        text-align: center;
        height: 80px;
        line-height: 80px;
        position: absolute;
        top: 0;
        left: 0;
    }
</style>

<body>
    <div class="container">
        <p class="p"></p>
        <ul class="ul"> </ul>
    </div>
</body>
<script type="text/javascript">        init()
    function init() {
        for (let i = 1; i <= 10; i++) {
            var bd = document.createElement("li");
            bd.innerHTML = i
            document.querySelector(".ul").appendChild(bd)
        }
    }                //上拉加载        
    let hook = true
    document.querySelector(".container").addEventListener("scroll",
        function () {
            let Height = document.querySelector(".container").clientHeight
            let height = document.querySelector(".ul").scrollHeight
            let tops = document.querySelector(".container").scrollTop
            if (Height + tops >= height - 50 && hook) {
                hook = false
                console.log("添加数据")
                for (let i = 1; i <= 10; i++) {
                    var bd = document.createElement("li");
                    bd.innerHTML = i
                    document.querySelector(".ul").appendChild(bd)
                } hook = true
            }
        })                        //下拉刷新        
    var stratX = null
    var endX = null
    document.querySelector(".container").addEventListener("touchstart", function (e) {
        if (this.scrollTop == 0) {
            stratX = e.touches[0].clientY
        }
    })
    document.querySelector(".container").addEventListener("touchmove", function (e) {
        if (this.scrollTop == 0) {
            endX = e.touches[0].clientY - stratX
            if (endX < 100) { document.querySelector(".ul").style.transition = 'transform 0s ease'; document.querySelector(".ul").style.transform = 'translateY(' + endX + 'px)' }
        }
    })
    document.querySelector(".container").addEventListener("touchend", function () {
        if (endX < 100) {
            document.querySelector(".ul").style.transition = 'transform 0.5s ease'; document.querySelector(".ul").style.transform = 'translateY(0px)'
            return false
        } document.querySelector(".p").innerHTML = "加载中..."; document.querySelector(".p").classList.add("tip")
        setTimeout(() => {
            while (document.querySelector(".ul").hasChildNodes()) { document.querySelector(".ul").removeChild(document.querySelector(".ul").firstChild); }
            init()
            document.querySelector(".ul").style.transition = 'transform 0.5s ease'; document.querySelector(".ul").style.transform = 'translateY(0px)'
            document.querySelector(".p").innerHTML = ""; document.querySelector(".p").classList.remove("tip")
        }, 2000)
    })    
</script>

</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值