前端-知识点总结

本文探讨了前端性能优化的各种策略,包括使用requestAnimationFrame实现流畅动画,理解CSS的适配技巧,以及如何处理点击事件延迟和节流防抖。此外,还介绍了文件下载和预览的实现方法,以及防止页面白屏的措施,旨在提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

浏览器

屏幕刷新频率

屏幕每秒出现图像的次数。(普通笔记本为60Hz)

动画原理

计算机每16.7ms刷新一次,由于人眼的视觉停留,所以看起来是流畅的移动

实现动画的方式

  1. HTML5:Canvas动画 / requestAnimationFrame API
  2. CSS3:transition / animation;
  3. JS:setTimeout / setInterval
  4. SVG(可伸缩矢量图形)

requestAnimationFrame(rAF)请求动画帧

requestAnimationFrame(rAF)是一个用于请求浏览器在下一次重绘之前执行回调函数的方法。它的优势在于可以让系统决定回调函数的执行时机,通常在每次屏幕刷新时执行,这样可以确保动画流畅,避免卡顿、抖动和丢帧。

优势:

  1. 系统优化: 由于requestAnimationFrame由浏览器进行优化,它会在每个屏幕刷新周期中执行回调函数,通常是每秒60次(60Hz),以保证动画的流畅性和稳定性。

  2. CPU 节能: 相比于使用setTimeoutsetInterval来实现动画,requestAnimationFrame更加节能。因为它会在浏览器进行绘制时才执行回调函数,避免了不必要的计算。

  3. 函数节流: 由于requestAnimationFrame的执行频率与屏幕刷新频率相匹配,可以避免过于频繁地执行回调函数,实现了函数的节流。

缺点:

优雅降级: 在不支持requestAnimationFrame的老旧浏览器中,需要考虑优雅降级的策略,通常是通过使用setTimeoutsetInterval来实现类似的功能。

综上所述,requestAnimationFrame是实现动画效果的一种高效、流畅的方式,尤其适用于需要保证动画流畅性和节能性的场景。

大屏

适配

在这里插入图片描述

数据轮询

const eventSource = new EventSource('http://localhost:3000'); // 建立SSE连接
eventSource.onmessage = (event) => {
  this.currentTime = event.data; // 接收到数据时更新currentTime
};
eventSource.onerror = (error) => {
  console.error('SSE 连接错误:', error);
  eventSource.close(); // 出错时关闭连接
};

Ajax

创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术

优点:减轻服务器的负担,按需取数据,最大程度的减少冗余请求,局部刷新页面,减少用户心理和实际的等待时间,带来更好的用户体验,基于xml标准化,并被广泛支持,不需安装插件等,进一步促进页面和数据的分离

缺点:因为大量的使用了JSAJAX引擎,这些取决于浏览器的支持.在编写的时候考虑对浏览器的兼容性。

如何阻止事件冒泡?

  • IE:e.cancelBubble = true;
  • 非IE:e.stopPropagation();

如何阻止默认事件?

  • e.preventDefault();
  • return false;

单点登录SSO(Single Sign-On)

  • Session + Cookie模式
    去【认证中心】拿到sessionId,存到cookie里,然后访问【子系统】,让【子系统】拿着sessionId去【认证中心】判断
    (优点:认证中心控制权很大 缺点:认证中心压力很大)
    在这里插入图片描述

  • Token模式
    去【认证中心】拿到Token并储存,让【子系统】自行认证
    (优点:认证中心压力小 缺点:认证中心没有能力控制用户下线)
    在这里插入图片描述

  • Token + RefreshToken模式
    Token设置10min过期时间,RefreshToken设置一个月过期时间;10min这段时间里访问都由【子系统】通过Token自行认证;过期后由【认证中心】通过RefreshToken认证,重新生成10min新的Token
    (结合前两者,延伸出来:减少对【认证中心】的高频认证,又保持【认证中心】的强力控制权)
    在这里插入图片描述
    在这里插入图片描述

后端做了认证中心 前端使用了iframe通过window.postmessage实现同域名不同子网的免登陆

工作原理:

  1. 认证中心(通常是一个独立的后端服务)负责用户身份验证和颁发令牌(Token)。

  2. 用户访问不同的子系统或应用程序,这些子系统或应用程序都需要验证用户的身份。

  3. 当用户访问一个需要身份验证的子系统时,子系统会检测用户是否已经登录。

  4. 如果用户尚未登录,子系统将创建一个 iframe,并将 iframe 的源设置为认证中心的登录页面。这个 iframe 通常跨越了不同的子网。

  5. 用户在 iframe 中登录,认证中心验证用户身份后,将用户信息和令牌传递回子系统。

  6. 子系统接收到令牌后,可以验证令牌的有效性,然后允许用户访问应用。

  7. 子系统中的前端页面可以通过 window.postMessage 将用户信息传递给主页面,以便在主页面中显示用户相关的信息。

这种方式的好处是用户只需一次登录就可以访问多个应用程序,提高了用户体验。但需要注意以下几点:

  1. 令牌安全性:确保令牌传递过程中的安全性,以免被恶意截取。

  2. 跨域通信:使用 window.postMessage 需要确保不同子网的域名都信任对方。

  3. 令牌有效期:令牌应该有一个合理的有效期,以便在一段时间后需要重新登录。

  4. 会话管理:管理用户会话和单点注销等问题也需要考虑。

总之,SSO 是一种方便用户的身份认证和授权机制,但在实际应用中需要仔细考虑安全性和合理配置。

window.postMessage(message, targetOrigin, [transfer])

  • message:要发送的消息,可以是字符串、数字、对象等等。这是必需的参数。
  • targetOrigin:指定接收消息的窗口的源。这是一个字符串,表示目标窗口所在的域名。通常应指定具体的域名,以增加安全性,而不使用通配符 *。这是必需的参数。
  • transfer(可选):一个数组,包含要传递给其他窗口的 Transferable 对象。Transferable 对象可以是 ArrayBufferMessagePort 或者 ImageBitmap

注意:

  • window.postMessage 用于实现安全的跨域通信,但要确保目标窗口明确信任来自发送消息的窗口,同时发送消息的窗口也需要明确信任目标窗口。
  • 跨域 postMessage 应该非常谨慎,以防止跨站点请求伪造(CSRF)攻击。建议在消息中包含令牌或其他验证信息以增加安全性。
  • 接收消息的窗口需要添加一个事件监听器来处理传入的消息,通常使用 window.addEventListener("message", handlerFunction)

总之,window.postMessage 是 Web 开发中用于实现跨窗口通信的重要方法,它可以帮助不同窗口之间进行安全的数据传输。

事件循环

一种在 JavaScript 运行时环境(如浏览器或Node.js)中管理任务执行的机制。一次事件循环包括以下主要阶段:

  1. 执行同步任务(Synchronous Tasks): 在事件循环的开始阶段,会执行当前宏任务队列中的所有同步任务,这些任务是按照代码的顺序执行的。

  2. 执行微任务(Microtasks): 在同步任务执行完成后,会执行微任务队列中的所有微任务。微任务包括Promise回调、MutationObserver回调和process.nextTick(在Node.js中)等。微任务通常用于处理与DOM更新相关的操作,以确保在浏览器渲染之前执行。

  3. 更新渲染(Update Rendering): 这个阶段是浏览器特有的,用于更新页面的渲染。在浏览器中,DOM 更新、布局计算和绘制都在这个阶段完成。在Node.js中,这个阶段通常为空。

  4. 执行宏任务(Macrotasks): 在微任务执行完毕后,会执行当前宏任务队列中的一个宏任务。宏任务包括定时器回调、事件处理程序和I/O操作等。执行一个宏任务后,会检查是否有微任务需要执行,如果有,就会进入微任务阶段,然后再执行下一个宏任务。这个过程会一直重复,直到所有任务都执行完毕。

  5. 等待新任务(Waiting for New Tasks): 如果没有新的宏任务被添加到队列中,事件循环会等待新的任务加入,这个等待阶段会持续。

总的来说,事件循环是一个不断循环的过程,它负责执行同步任务、微任务、更新渲染和宏任务,以确保 JavaScript 代码的执行和页面的渲染顺利进行。这种机制使得 JavaScript 能够异步处理各种任务,保持用户界面的响应性。

移动端

inputmode:改变弹出键盘类型

<input type="text" inputmode="" />
<textarea inputmode="" />

在这里插入图片描述

如何进行适配

  1. 使用@media screen + rem
  2. 使用vw、vh
  3. 使用flexible.js
  4. 使用meta标签里的viewport属性

解决1px问题

  1. 设置 border-image / transform: scale(0.5)
  2. 使用transfrom + 媒体查询(CSS:@media screen / JS:devicePixelRatio)
  3. 使用 box-shadow / background-image 渐变 / viewport + rem

点击事件延迟300ms的解决方案:

  1. 禁用缩放:user-scalable=no
  2. 使用fastclick.js

点击穿透的解决方案

  1. 将click事件改成touch事件(touchstart、touchend、tap)
  2. 阻止默认行为:e.preventDefault()
  3. 使用fastclick.js

iOS手机容器滚动条滑动不流畅

overflow: auto;
-webkit-overflow-scrolling: touch;

ios的audio无法自动播放、循环播放

var music = document.getElementById('video');
var state = 0;

document.addEventListener('touchstart', function(){
    if(state==0){
        music.play();
        state=1;
    }
}, false);

document.addEventListener("WeixinJSBridgeReady", function () {
    music.play();
}, false);

//循环播放
music.onended = function () {
    music.load();
    music.play();
}

小程序

本地缓存

wx.getStorageSync(同步)可以先获取值

wx.getStorage(异步)需要调用success

生命周期

  • 应用生命周期(小程序)
启动
运行
销毁
  • 页面生命周期(页面)
加载
渲染
销毁

Uni-App

生命周期

  • 应用生命周期:与 小程序 应用的生命周期一致(onLaunch、onShow、onHide 等)
  • 页面生命周期:与 小程序 页面的生命周期一致(onLoad、onUnload、onShow 等)
  • 组件生命周期:与 Vue.js 组件的生命周期一致(mounted、created 等)

JQuery

window.onloadjQuery的ready的区别

JavaScript中的代码:

Window.onload = function(){}

等价于jQuery代码:

$(window).load(function(){});
window.load$(document).ready()
简化写法$(function(){ });
编写个数不能同时编写多个,多个同时存在只运行最后一个能同时编写多个,多个同时存在也会全部运行
执行时机必须等待网页中所有的内容加载完毕后(包括图片)才能执行网页中所有DOM结构绘制完毕后就执行,可能DOM元素关联的内容并没有加载完

框架

单向数据流和双向数据流

单向数据流双向数据流
架构MVCMVVM
框架ReactVue、Angular
例子Vue 中 v-bind 、父传子的 propsVue 中 v-model
特点所有状态的改变可记录、可跟踪,源头易追溯;
一旦数据变化,就去更新页面(data-页面),但是没有(页面-data);
如果用户在页面上做了变动,那么就手动收集起来(双向是自动),合并到原有的数据中;
所有数据只有一份,组件数据只有唯一的入口和出口,使得程序更直观更容易理解,有利于应用的可维护性
无论数据改变,或是用户操作,都能带来互相的变动,并且自动更新

性能优化

页面加载及渲染优化

  1. HTML:文档结构层次尽量少(最好不深于六层)
  2. CSS:样式结构层次尽量简单;少量首屏样式内联放在标签内;动画尽量使用在绝对定位或固定定位的元素上;隐藏在屏幕外,或在页面滚动时,尽量停止动画;
  3. JS:在脚本中尽量减少DOM操作,尽量缓存访问DOM的样式信息,避免过度触发回流;减少通过JavaScript修改元素样式,尽量使用修改class名方式操作样式/动画;尽量缓存DOM查找,查找器尽量简洁;
  4. CSS置顶,JS置底;涉及多域名的网站开启域名预解析
  5. 静态资源使用CDN
  6. 使用字体图标、精灵图
  7. 利用缓存减少重复加载

页面交互优化

懒加载

  1. 可以通过为图片文件添加loading="lazy"的属性来实现
  2. 监听srcoll事件

节流防抖

节流

触发高频事件,但在n秒内只会执行一次,在于稀释函数的执行频率,侧重于一段时间内只执行一次

(就像游戏里无论手速多快,多次平A也有频率上限)

应用场景:

  • window对象的resize、scroll事件
  • 拖拽事件的mousemove
  • 射击游戏中的mousedown、keydown事件
  • 文字输入、自动完成的keyup事件
防抖

触发高频事件后,n秒内只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间,侧重于一段时间内多次触发只在最后执行一次

(就像游戏里释放技能的时候,再按一次技能就会重新冷却)

应用场景:

  • 提交按钮、用户注册时候的手机号验证、邮箱验证
```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            height: 4000px;
            background-color: #000;
        }
    </style>
</head>

<body>
    <input id="input"></input>
    <div id="div"></div>

    <script>
        function sendRequest() {
            console.log("发送请求");
        }

        // 节流:
        // document.getElementById("div").onscroll = throttle(sendRequest, 1000)

        const onscroll = throttle(sendRequest, 1000)

        function throttle(fn, delayTime) {
            let valve = true;
            return function () {
                if (!valve) {
                    return;
                }
                valve = false;
                setTimeout(() => {
                    fn && fn()
                    valve = true;
                }, delayTime)
            }
        }

        // 防抖:输入完成后间隔一秒再发送请求
        document.getElementById("input").oninput = antiShake(sendRequest, 1000);

        function antiShake(fn, delayTime) {
            let timer = null;
            return function () {
                if (timer) {
                    clearTimeout(timer)
                };
                timer = setTimeout(() => {
                    fn && fn();
                }, delayTime)
            };
        }
    </script>
</body>

</html>

服务器

服务的有状态和无状态

都是负载均衡服务

判断两个来自相同发起者的请求在服务器端是否具备上下文关系

有状态无状态
数据同步需要/
资源消耗保存数据/
带宽消耗数据同步/
部署发布需要额外的数据同步直接部署
failover数据可能丢失,同步不完全数据不会丢失,负载均衡失效转移

Node

package-lock.json 作用为什么要lock,它是怎样保证版本依赖下载正确

通过锁定依赖包的版本和依赖关系,以及记录安全信息,保证了在不同环境下安装依赖时的一致性和安全性

第一次安装依赖
确定版本号
记录在package-lock.json
锁定版本
后续都是根据package-lock.json安装依赖
锁定依赖包之间的关系保持版本一致

网络

ajax和axios请求的区别

在这里插入图片描述

跨文档消息传递

在这里插入图片描述

常见的业务

文件下载

文件下载可以通过以下几种方式来实现:

  1. 基于链接的下载: 在 HTML 中提供一个链接,指向需要下载的文件,用户点击链接后浏览器会自动下载文件。

    <a href="/path/to/file.pdf" download="filename.pdf">点击下载文件</a>
    

    这个链接指向了文件的路径,并且使用了 download 属性,这样浏览器在点击链接时会下载文件,而不是打开它。

  2. 使用后端接口下载: 在后端提供一个接口,接收客户端的下载请求,并返回文件的内容。前端通过发起请求到这个接口来下载文件。

    例如,使用 JavaScript 发送 GET 请求来下载文件:

    function downloadFile() {
        fetch('/api/download/file.pdf')
            .then(response => response.blob())
            .then(blob => {
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = 'filename.pdf';
                document.body.appendChild(a);
                a.click();
                window.URL.revokeObjectURL(url);
            })
            .catch(error => console.error('Error downloading file:', error));
    }
    

    在后端,需要处理 /api/download/file.pdf 这个路由,根据路由中的文件名找到相应的文件,并将文件内容返回给客户端。

  3. 使用 Blob 对象: 在前端使用 JavaScript 构造一个 Blob 对象,然后创建一个指向这个 Blob 对象的 URL,并将这个 URL 赋值给 a 标签的 href 属性,最后触发点击 a 标签的事件,实现下载。

    function downloadFile() {
        const fileContent = 'file content here';
        const blob = new Blob([fileContent], { type: 'application/octet-stream' });
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'filename.txt';
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
    }
    

这些方法可以根据需求选择使用,基于链接的下载适用于静态文件,后端接口下载适用于动态生成文件,Blob 对象适用于在前端构造文件内容并下载。

文件预览

文件预览通常需要根据文件类型选择不同的方式来实现。以下是一些常见文件类型的预览方法:

  1. 图片预览: 对于图片文件,可以直接在网页中使用 <img> 标签来显示。

    <img src="/path/to/image.jpg" alt="Image Preview">
    
  2. PDF 文件预览: 可以使用 <embed><iframe> 标签来嵌入 PDF 文件,并显示在网页中。

    <embed src="/path/to/file.pdf" type="application/pdf" width="100%" height="600px" />
    <!-- 或者 -->
    <iframe src="/path/to/file.pdf" width="100%" height="600px"></iframe>
    
  3. 视频文件预览: 对于视频文件,可以使用 <video> 标签来播放。

    <video controls width="100%" height="auto">
        <source src="/path/to/video.mp4" type="video/mp4">
        Your browser does not support the video tag.
    </video>
    
  4. 音频文件预览: 对于音频文件,可以使用 <audio> 标签来播放。

    <audio controls>
        <source src="/path/to/audio.mp3" type="audio/mp3">
        Your browser does not support the audio tag.
    </audio>
    
  5. 文本文件预览: 对于文本文件,可以直接在页面中显示文本内容,或者使用 <iframe> 标签嵌入一个包含文本内容的页面。

    <!-- 直接显示文本内容 -->
    <pre>
        Text content here...
    </pre>
    
    <!-- 或者 -->
    <iframe src="/path/to/textfile.txt" width="100%" height="600px"></iframe>
    
  6. 其他文件类型预览: 对于其他类型的文件,可以考虑使用第三方库或在线服务进行预览。例如,使用 Google Docs Viewer 来预览文档文件。

场景题

白屏化

原因:

  • 加载速度慢
  • 依赖文件丢失
  • JS错误

避免措施:

  1. 优化页面加载:
  • 浏览器缓存
  • CDN
  1. 异步加载非首屏需要的资源
  2. 使用SSR
  3. 减少频繁的DOM操作

从开发的角度简述手机验证码实现的过程

用户 前端 后端 短信服务提供商 请求获取验证码 发送验证码请求 请求发送短信验证码 返回发送结果 返回发送结果 显示验证码发送结果 输入验证码 发送验证码验证请求 验证验证码 返回验证结果 显示验证码验证结果 用户 前端 后端 短信服务提供商

封装一个sleep 方法,让sleep(5000)后面的代码延迟5s后执行

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function delayedExecution() {
  console.log("开始");
  await sleep(5000);
  console.log("5秒后");
}

delayedExecution();

声明一个变量a,让(a==1&&a==2&&a==3)条件成立

let a = {
  value: 1,
  valueOf: function() {
    return this.value++;
  }
};

if (a == 1 && a == 2 && a == 3) {
  console.log("条件成立");
} else {
  console.log("条件不成立");
}

假如请求回来 10000 条数据,然后染到页面, 怎么做优化才能使页面不会太卡顿

  1. 监听用户界面延迟加载数据
    使用IntersectionObserver和getBoundingClientRect来判断空白是否在页面底部

  2. setTimeOut+分页渲染

const renderList = async () => {

    const list = await getList()

    const total = list.length
    const page = 0
    const limit = 200
    const totalPage = Math.ceil(total / limit)

    const render = (page) => {
        if (page >= totalPage) return
        setTimeout(() => {
            for (let i = page * limit; i < page * limit + limit; i++) {
                const item = list[i]
                const div = document.createElement('div')
                div.className = 'sunshine'
                div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
                container.appendChild(div)
            }
            render(page + 1)
        }, 0)
    }
    render(page)
}
  1. requestAnimationFrame代替setTimeOut(减少reflow次数,提高性能)
const renderList = async () => {
    const list = await getList()

    const total = list.length
    const page = 0
    const limit = 200
    const totalPage = Math.ceil(total / limit)

    const render = (page) => {
        if (page >= totalPage) return

        requestAnimationFrame(() => {
            for (let i = page * limit; i < page * limit + limit; i++) {
                const item = list[i]
                const div = document.createElement('div')
                div.className = 'sunshine'
                div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
                container.appendChild(div)
            }
            render(page + 1)
        })
    }
    render(page)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

刘泽宇Developer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值