美文网首页JavaScript相关文章Javascript收集
Javascript基础知识5点(2019.1.29)

Javascript基础知识5点(2019.1.29)

作者: 小进进不将就 | 来源:发表于2019-01-29 16:16 被阅读38次

1、什么是 options 请求?
在正式跨域之前,浏览器会根据需要发起一次预检请求(即 options 请求),用来让服务端返回允许的方法(如 get、post)

浏览器会发出两种请求:
(1)简单请求(一次请求,无 预检)

(2)非简单请求(先 预检,通过后,正式发出请求)

区别:预检不会携带 cookie,正式请求会携带 cookie 和 参数。

详情请参考:https://www.jianshu.com/p/5cf82f092201

2、path.join() 和 path.resolve() 的区别(Nodejs)
path.join() :连接参数,返回相对路径

path.join('a', 'b', 'c') // 返回 'a\b\c'

path.join('/a/b','c') // 返回 'a\b\c'

path.join('') // 返回 '.',表示当前工作目录

path.resolve(): 连接参数,返回绝对路径

path.resolve('/a/b', 'c') // 返回 'F:\a\b\c'

path.resolve('') // 返回 F:\ES6Test

path.resolve('a','b','c') // 返回 F:\ES6Test\a\b\c

3、了解过 react-router 内部实现机制吗?
核心机制:实现了 URL(对应 location 对象) 和 UI(对应 React 的 components 组件) 的同步。
也就是 对象location 和 组件components 的同步。

同步的过程:
(1)点击 <Link/> 组件,<Link/> 组件会渲染为 HTML 标签 <a>,它的 to、query、hash 属性会被 组合在一起 并渲染为 href 属性(虽然 Link 被渲染为超链接,但在内部实现上使用脚本拦截了浏览器的默认行为

(2)然后调用了 history.pushState() 方法(注意,该 history 是 history 包里面的 create*History 方法创建的对象,不是 window.history 对象,尽管它们有些 API 相同)

(3)在调用 history.pushState() 的同时,会将 history.pushState() 的参数传输到 createLocation() 方法中,该方法返回一个 location 对象

(4)React-router 会将上述 location 对象作为参数传入到 TransitionTo() 方法中,该方法返回一个 新的 location,然后调用 window.location.hash 或者 window.history.pushState() (注意:尽管 API 相同,但不是 H5 的history)修改了应用的 URL

同时会触发history.listen 中注册的事件监听器。

(5)在得到了新的 location 对象后,React-router 的 matchRoutes() 方法会匹配出Route 组件树中与当前 location 对象匹配的一个子集,并且得到 nextState 对象

(6)在 Router 组件的 componentWillMount 生命周期方法中调用了 history.listen(listener) 方法。

listener 会在上述 matchRoutes 方法执行成功后执行listener(nextState)

(7)接下来执行 this.setState(nextState) 就可以重新渲染 Router 组件(修改 UI)

到这里,app 就完成了点击 Link 组件到页面刷新的全过程

注:原文表达模糊,简单点就是:点击 link -> 得到 location -> 调用 window.history.pushState() ->修改 url -> 根据 location 和 componentTree 算法匹配得到 nextState -> 在 componentWillMount 中执行 this.setState(nextState) ->重新渲染 UI

参考:
React-router路由基本原理(https://blog.csdn.net/leviscar/article/details/81878677
react-router原理(https://blog.csdn.net/qq_36223144/article/details/83247008
React Router 中文文档(https://react-guide.github.io/react-router-cn/index.html
react-router的实现原理(https://blog.csdn.net/tangzhl/article/details/79696055

4、前端缓存的相关知识
前端缓存一般分为「强缓存」和「协商缓存」。

强缓存:一定时间期限内,只使用本地缓存。

当设置 http 请求头的 Cache-Control 的值为 "public, max-age=xxx" 后,在 {max-age} 秒内再次访问该资源,不会向服务器发起请求,而是使用本地缓存。

缺点:当发布新版本后,如果后台接口同步更新,就直接 GG。

协商缓存:每次向服务器验证缓存的有效性。若有效,则使用 本地缓存,若无效,则使用 服务器的新数据。

缺点:耗费服务器资源。

最佳实践:尽可能使用「强缓存」,但在更新版本的时候,要修改静态资源的路径,这样就相当于第一次访问这些资源,从而完成刷新。

综上:

  • HTML:使用「协商缓存」
  • CSS、JS、图片:使用「强缓存」

5、什么是函数防抖和函数分流?

函数防抖:在一定时间范围内,多次触发事件,只调用一次事件处理函数。

生活示例:如果有人进电梯(触发事件),那电梯将在 5s 后关门(执行事件句柄),在 5s 内如果又有人进电梯了,又得再等 5s 再出发(重新计时)。

例:鼠标悬浮,获取后台数据,鼠标移出,不获取数据。
如果鼠标频繁移入移出,那么会频繁调用后台 api,导致资源浪费,可以使用 setTimeout 处理

function getData() {
    console.log('a')
}
//鼠标移入,延迟获取数据
obj.onmousehover = function () {
    //先清除之前的 setTimeout 的ID
    clearTimeout(getData.timer)
    //再设置延迟时间,防止频繁移入移出,调用 getData()
    getData.timer = setTimeout(getData,500)
}

使用闭包保存 setTimeout 的 ID

function getData() {
    console.log('a')
}

function saveTimerID(method,delay) {
    let timer=null;
    return function () {
        var context = this, args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function () {
            method.apply(context,args);
        },delay);
    }
}
obj.onmousemove = saveTimerID(getData,50);

函数分流:在「函数防抖」的前提下,再设置一个 时间阀值,比如 2s ,那么一旦触发时间,不管它 setTimeout 延迟多少, 2s 后一定会 触发。

生活示例:还是坐电梯,5s 内有人进来,就再等 5s,但是最多等 5 分钟,此时电梯门铃响起,必须关门。

例:还是鼠标悬浮、移出,但你不能老移入、移出、移入、移出,让其一直延后 调用函数时间,而是第一次移入后,开始计时,不管其中移入、移出多少次,1s 后必须调用后台 api,显示数据。

//method:getData(),delay:延迟调用的时间,mustRunDelay:必须执行的时间
function do(method, delay, mustRunDelay) {
    let timer = null, args = arguments;
    //start:第一次调用时间,now:最新的调用时间
    let start = 0, now = 0
    return function () {
        let context = this;
        now= Date.now();
        if(!start){
            start = now;
        }
        if(now - start >= mustRunDelay){
            method.apply(context, args);
            start = Date.now();
        }else {
            clearTimeout(timer);
            timer = setTimeout(function () {
                method.apply(context, args);
            }, delay);
        }

    }
}
obj.onmousemove = do(getData, 50, 500);

欢迎关注公众号:gh_042070ae6d0a ,每周分享前端干货和生活感悟!

(完)

相关文章

网友评论

    本文标题:Javascript基础知识5点(2019.1.29)

    本文链接:https://www.haomeiwen.com/subject/vprodqtx.html