赞
踩
答:权限控制(无感刷新)本质上都是对token的处理,方案有很多,我举例比较常见的一种。 权限可以简单的分为3种情况, 1. 未登录 2. 已登录token过期 3. 已登录token和refreshToken都过期 针对上面三种情况,解决方案如下 1. 未登录的话,可以通过封装一个全局的权限组件统一处理,发现没有token,跳转登录页 2. 已登录token过期,一般后台都会再准备一个refreshToken,实现无感刷新 在响应拦截器中判断状态码 401,携带refreshToken到后台获取最新的token或refreshToken,再发送之前请求即可 3. 已登录token和refreshToken都过期,跳转登录页 还是在响应拦截器中判断状态码 401,也判断当前请求是否为 refreshToken,那么跳转登录页
图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。 如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。 如果图片为 css 图片,可以使用 CSSsprite,SVGsprite,Iconfont、Base64 等技术。 如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。 如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。
流式布局: 使用非固定像素来定义网页内容,也就是百分比布局,通过盒子的宽度设置成百分比来根据屏幕的宽度来进行伸缩,不受固定像素的限制,内容向两侧填充。这样的布局方式,就是移动 web 开发使用的常用布局方式。这样的布局可以适配移动端不同的分辨率设备。 响应式开发 那么 Ethan Marcotte 在 2010 年 5 月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端。越来越多的设计师也采用了这种设计。 CSS3 中的 Media Query(媒介查询),通过查询 screen 的宽度来指定某个宽度区间的网页布局。 超小屏幕(移动设备) 768px 以下 小屏设备 768px-992px 中等屏幕 992px-1200px 宽屏设备 1200px 以上 由于响应式开发显得繁琐些,一般使用第三方响应式框架来完成,比如 bootstrap 来完成一部分工作,当然也可以自己写响应式
实时搜索: 通过input事件和定时器防抖来实现 1。每次输入框发生输入变化都会触发绑定input事件函数,来做监听处理 2,为了防止每次输入的值都会去触发事件函数,通过clearTimer方法清除上一个定时器,如果两次输入的时间间隔小于2s中,那么第一个定时器将被清除,同时执行第二个定时器 高亮显示: 通过RegExp来将关键词替换成htm1标签,同时用vue中的v-htm]进行绑定,实现高亮
在具体的应用场景中,常见的应用包括: 1. 定义常量:在一些常量取值固定的情况下,使用枚举可以更加清晰地表示这些常量,例如HTTP状态码、错误码等。 2. 表示状态:在应用程序中经常需要表示一些固定的状态,例如订单状态、用户状态等。使用枚举可以更清晰地表示这些状态,提高代码的可读性和可维护性。 3. 映射关系:在一些多对一的关系中,使用枚举可以更加清晰地表示不同值之间的映射关系,例如在前端开发中使用枚举来表示一些标识符的映射关系。 好处:枚举可以提高代码的可读性、可维护性和健壮性
当时公司的场景大概一个excel文件里就几十条数据,量比较少,和后端商量之后制定了前端主导的方案,解析的过程放到了浏览器端做,当时是参考了一下vue-admin中的现成的方案 准备好一个标准的excel文件,然后通过插件解析成js数据,把js数据格式化一下,最后个通过调用后端接口完成导入 数据量小的情况可以由前端完成解析,当数据量大时,需要由后端完成
1、步骤 1)、默认路由配置里只有登录的配置。 2)、登录成功后,后端返回功能权限,最好直接就是路由配置,如果不是,前端把功能权限处理成路由配置的json数组格式。 使用vue-router对象的addRoutes方法把该路由配置动态添加到路由对象里。同时,把该路由配置保存到sessionStorage里(防止前端刷新后丢失路由配置)。 3)、前端在“App.vue”里的created里,需要读取cookie里或sessionStorage里保存的路由配置,同样需要把读取到的路由配置,使用vue-router对象的addRoutes方法 把该路由配置动态添加到路由对象里。这样刷新页面时,就可以在此处获取到当前用户的路由权限。 2、特别注意: 一定要把获取到的权限数组存放到sessionStorage。否则,刷新页面时,路由配置就会丢失掉。
前端实现大文件上传主要有以下几种方法: 1. 分片上传:将文件分成多个小块,分别上传,上传完成后再合并。这种方法可以避免单次上传过大的问题,同时也可以在上传失败时只重新上传失败的部分。 2. 断点续传:在上传过程中,如果中断了上传,可以记录已经上传的位置,然后下次上传时从上次中断的位置继续上传,这样可以避免重新上传整个文件。 3. WebSocket上传:使用WebSocket协议进行文件上传,可以在上传过程中实时反馈上传进度,并且可以实现断点续传和续传失败的部分。 4. 使用第三方上传组件:如Plupload、WebUploader等,这些组件可以自动处理文件分片、上传进度等问题,使用起来非常方便。 总之,实现大文件上传需要考虑上传过程中可能遇到的各种问题,如上传失败、上传速度慢、断网等问题,需要通过一些技术手段进行解决,以提高上传的可靠性和效率。构建 vue-cli 工程都用到了哪些技术?他们的作用分别是什么?
下拉刷新是一种常见的页面交互方式,它可以在用户下拉页面时自动刷新内容,提高用户体验。实现下拉刷新主要有以下几种方式: 1. 使用原生的下拉刷新:在移动端浏览器中,可以使用原生的下拉刷新功能,通过监听浏览器的scroll事件和touch事件,当用户下拉页面时,触发刷新操作。这种方式简单易用,但不能在APP中使用。 2. 使用第三方组件库:如Mint UI、Vant等,这些组件库提供了下拉刷新的组件,可以在Vue、React等框架中使用,使用起来方便快捷。 3. 自定义实现:通过监听touchstart、touchmove、touchend等事件,实现下拉刷新的效果,主要步骤包括: (1)在touchstart事件中记录下拉开始的Y轴坐标; (2)在touchmove事件中计算下拉的距离,然后根据下拉距离实时更新页面的样式; (3)在touchend事件中判断下拉的距离是否超过阈值,如果超过,则触发刷新操作,否则恢复到原始状态。 总之,实现下拉刷新的方式有很多种,开发者可以根据具体需求和技术水平选择合适的方式。
上传文件需要配置以下参数: url:上传文件的接口地址。 filePath:要上传的文件路径。 name:上传文件对应的 key,服务器端通过这个 key 可以获取到文件的二进制内容。 formData:上传文件时要附带的额外信息,可以是一个对象或数组。 success:上传成功后的回调函数。 fail:上传失败后的回调函数。 complete:上传完成后的回调函数,不论成功或失败都会执行。
1. 什么是websocket? a. 本质: 一种双向通信协议, b. 作用:常用来做即时通讯。 c. 场景:聊天会话、股票交易等。 客服聊天机器人 本质上是使用了 websocket 的客户端和服务端的双向通信实现,页面通过 new WebSocket()链接链接,监听onmessage获取服务端传送过来的数据,实现在线聊天 但是因为需要 机器人客服/智能回复/断线重连 等功能,一般都是使用市场上面比较成熟的 客服系统 即可
Token失效是指在使用Token进行身份验证时,系统验证该Token无效或过期。如果Token失效,需要进行以下处理: 1. 重新获取Token:可以通过重新登录或者刷新Token的方式,重新获取有效的Token。 2. 更新Token:如果Token只是过期了,但仍然有效,可以尝试更新Token,使其保持有效状态。 3. 提示用户重新登录:如果Token失效且不能通过更新或重新获取来解决,应该提示用户重新登录,以获取新的有效Token。 4. 清除Token:如果Token被盗用或存在其他安全问题,应该立即清除该Token并要求用户重新登录,以确保账户的安全。 5. 日志记录和报告:在处理Token失效时,应该记录日志并报告相关信息,以便分析和改善系统的安全性和可靠性。 总之,在处理Token失效时,需要及时、准确地识别问题,并采取相应措施,以确保系统和用户的安全。
一般是测试发布到禅道,后面由组长由组长分配给组内成员
前后端一起开发,前端画页面,用mock模拟数据,后端写接口。 前后端打交道最多就是接口,所以得使用postman。
开发 地址 自测 提交到测试环境 测试 地址 测试 线上 地址 运维
#看项目大小,会在需求评审和技术评审进行排期 #需要前后端和测试一起根据实际情况商量,测试结束后还要进行验收
a.首先根据接口文档看传参,一般传参没问题会和后端沟通 b.更多的是直接看后端返回的数据,自己做的功能,如果数据有问题是能够看出来的
1、有一次上传文件的时候,
#如果后端可以配合我们的话我们可以使用webSocket 跟后端进行实时通讯,前端部署完之后,后端给个通知,前端检测到Message进行提示,还可以在优化一下使用EvnentSource 这个跟socket很像只不过他只能后端往前端推送消息,前端无法给后端发送,我们也不需要给后端发送。 #纯前端实现 安装http-server 开个服务 重新打个包npm run build
作用:DOCTYPE声明于文档最前面,告诉浏览器以何种方式来渲染页面。 如何区分: 严格模式的排版和Js运作模式,以该浏览器支持的最高标准运行。 混杂模式:页面以宽松的向后兼容方式(IE5.5以下的渲染模式)显示,防止站点无法工作 意义:混杂模式服务于旧世规则,严格模式服务于标准规则;
(1)比如:header、content、footer、aside、nav、section、article等语义化标签。 (2)语义化标签的好处:结构清楚,易于阅读,可维护性更高,有利于SEO的优化。
展开> video/audio标签的属性src: 用于告诉video标签需要播放的视频地址 autoplay: 用于告诉video标签是否需要自动播放视频 controls: 用于告诉video标签是否需要显示控制条 poster: 用于告诉video标签视频没有播放之前显示的占位图片 loop: 一般用于做广告视频, 用于告诉video标签视频播放完毕之后是否需要循环播放 preload: 预加载视频, 但是需要注意preload和autoplay相冲, 如果设置了autoplay属性, 那么preload属性就会失效 muted:静音(audio的)
表单类型: email :能够验证当前输入的邮箱地址是否合法 url : 验证URL number : 只能输入数字,其他输入不了,而且自带上下增大减小箭头,max属性可以设 置为最大值,min可以设置为最小值,value为默认值。 search : 输入框后面会给提供一个小叉,可以删除输入的内容,更加人性化。 range : 可以提供给一个范围,其中可以设置max和min以及value,其中value属性可以 设置为默认值 color : 提供了一个颜色拾取器 time : 时分秒 date : 日期选择年月日 datatime : 时间和日期(目前只有Safari支持) datatime-local :日期时间控件 week :周控件 month:月控件 表单属性: placeholder :提示信息 autofocus :自动获取焦点 autocomplete=“on” 或者 autocomplete=“off” 使用这个属性需要有两个前提: 表单必须提交过 必须有name属性。 required:要求输入框不能为空,必须有值才能够提交。 pattern=" " 里面写入想要的正则模式,例如手机号patte="^(+86)?\d{10}$" multiple:可以选择多个文件或者多个邮箱 form=" form表单的ID" 表单事件: oninput 每当input里的输入框内容发生变化都会触发此事件。 oninvalid 当验证不通过时触发此事件。
progress标签:用来表示任务的进度(IE、Safari不支持),max用来表示任务的进度, value表示已完成多少 meter属性:用来显示剩余容量或剩余库存(IE、Safari不支持) high/low:规定被视作高/低的范围 max/min:规定最大/小值 value:规定当前度量值
document.querySelector() document.querySelectorAll() 它们选择的对象可以是标签,可以是类(需要加点),可以是ID(需要加#)
HTML5 提供了两种在客户端存储数据的新方法: localStorage - 没有时间限制的数据存储。除非主动删除数据,否则数据是永远不过期。 sessionStorage - 不是一种持久化的本地存储,仅仅是会话级别的存储。 7.其他 ①拖放:拖放是一种常见的属性,即抓取对象以后拖到另一个位置。<img draggable="true"> 图片拖动案例参考: 原生JS快速实现拖放(drag and drop)效果 ②画布(canvas):canvas 元素使用 JavaScript 在网页上绘制图像。画布是一个矩形区域,可以控制其每一像素。canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。 ③SVG:SVG指可伸缩矢量图形,用于定义用于网络的基于矢量的图形,使用XML 格式定义图形,图像在放大或改变尺寸的情况下其图形质量不会有损失,它是万维网联盟的标准。 ④地理位置:Geolocation(地理位置)用于定位用户的位置。 ⑤webWorker 在当前JavaScript主进程中开启一个异步线程(独立工作,在主线程以外运行) 当开发人员发现 JS 引擎线程超负荷运作的时候,可以通过Web Worker提供的API开辟一个新的线程,用于独立的运行脚本程序(但是该脚本程序不能操作DOM,主要用于计算),避免 JS 引擎线程阻塞 GUI 线程渲染视图。window.postMessage可用于解决跨域数据传输。
⑥ webSocket
websocket### 定义 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。(*它是一个协议) WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。 在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。WebSocket是类似Socket的TCP长连接通讯模式。一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端中断连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。
websocket实现前台提交通知,后台接收,后端会定义一个websocket接口,我们可以创建一个实例与后端接口链接起来,由后端定义数据库录入了什么信息后主动向前端传递数据,我们通过实例.onmessage接收后端传递的数据并操作渲染页面等
var ws = new WebSocket("ws://localhost:8080"); //申请一个WebSocket对象,参数是服务端地址,同http协议使用http://开头一样,WebSocket协议的url使用ws://开头,另外安全的WebSocket协议使用wss://开头 ws.onopen = function(){ //当WebSocket创建成功时,触发onopen事件 console.log("open"); ws.send("hello"); //将消息发送到服务端 } ws.onmessage = function(e){ //当客户端收到服务端发来的消息时,触发onmessage事件,参数e.data包含server传递过来的数据 console.log(e.data); } ws.onclose = function(e){ //当客户端收到服务端发送的关闭连接请求时,触发onclose事件 console.log("close"); } ws.onerror = function(e){ //如果出现连接、处理、接收、发送数据失败的时候触发onerror事件 console.log(error); }
链接(http长轮询可了解):后端通知实现方式_后端通知前端_得求的博客-CSDN博客 一,什么是websocket WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议) 它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的 Websocket是一个持久化的协议 二,websocket的原理 websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信 在websocket出现之前,web交互一般是基于http协议的短连接或者长连接 websocket是一种全新的协议,不属于http无状态协议,协议名为"ws" 三,websocket与http的关系 相同点: 都是基于tcp的,都是可靠性传输协议 都是应用层协议 不同点: WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息 HTTP是单向的 WebSocket是需要浏览器和服务器握手进行建立连接的 而http是浏览器发起向服务器的连接,服务器预先并不知道这个连接 联系: WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的 总结(总体过程): 首先,客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等; 然后,服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据; 最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信。
拖拽 drap drop API
拖拽事件 源对象(draggable元素): 正在被拖动的对象, 该元素的draggable属性应被设置为true 目标对象: 拖拽到的目标对象,需要对元素的drag事件进行监听,并做相应操作才能转化为droppable元素
JS拖拽事件 事件 事件处理函数 作用对象 描述 drag ondrag 源对象 源文件被拖动触发 dragstart ondragstart 源对象 用户开始拖拽源对象 dragend ondragend 源对象 用户结束拖拽操作(例如释放鼠标按键和点击ESC按键) dragenter ondragenter 目标对象 拖拽源对象进入目标对象 dragover ondragover 目标对象 源对象处于目标对象上方(每几百毫秒触发一次) dragleave ondragleave 目标对象 源对象离开目标对象区域 dragexit ondragexit 目标对象 元素不再为可被选择的目标对象 drop ondrop 目标对象 源对象落在目标对象上
拖动案例
1. 标签闭合、标签小写、不乱嵌套、提高搜索机器人搜索几率、使用外链 css 和 js 脚本、结构行为表现的分离, 2. 文件下载与页面速度更快、内容能被更多的用户所访问、内容能被更广泛的设备所访问、更少的代码和组件, 3. 容易维护、改版方便,不需要变动页面内容、提供打印版本而不需要复制内容、提高网站易用性。 w3c盒子模型的范围包括margin、border、padding、content,并且content部分不包含其他部分
用法: lframe 是用来在网页中插入第三方页面,早期的页面使用iframe主要是用于导航栏这种很多页面都相同的部分,这样可以在切换页面的时候避免重复下载。优点:便于修改,模块分离,像一些信息管理系统会用到。但现在基本上不推荐使用。除非特殊需要,一般不推荐使用。 缺点 (1) iframe 的创建比一般的 DOM 元素慢了 1-2个数量级 (2) iframe 标签会阻塞页面的加载,如果页面的onload 事件不能及时触发,会让用户觉得网页加载很慢,用户体验不好在 Safari 和Chrome 中可以通过js 动态设置iframe 的 src 属性来避免阻塞 (3) iframe 对于 SEO 不友好,替代方案一般就是动态语言的Incude 机制和aiax动态填充内容等.
新特性:包括语义化标签、视频和音频标签、canvas绘图、Web存储、Web Workers等
SVG可以创建精美的矢量图形;
Canvas可以提供一个可绘画的区域,可以绘制2D和3D图形;
而WebSocket可以让浏览器和服务器之间实时双向通信。
这些新特性为Web开发带来了更好的交互性和更丰富的用户体验。
选择器优先级: !Important>行内样式>ID 选择器>类选择器>标签选择器>通配符>继承>浏览器默认属性 :::tips !important:!important拥有最高的优先级,加上!importanrt可以覆盖父级的样式,使用方法为直接在样式后添加加上!importanrt,如 color : red !important;
行内样式:行内样式指写在标签style属性中的样式,优先级仅次于!important,缺点为多个元素难以共享样式,不利于代码复用;HTML和CSS代码混杂,结构样式没有分离,不利于后期维护。所以建议尽量少使用行内样式。 ID选择器:ID 选择器会根据该元素的 ID 属性中的内容匹配元素,一个id只能使用一次。 类选择器:类选择器会根据元素的类属性中的内容匹配元素,可以重复使用,是最常用的选择器。 标签选择器:标签选择器是指用HTML标签名称作为选择器,优点是能快速为页面中同类型的标签统一样式,缺点是不能设计差异化样式。 通配符选择器:通配符选择器为*,指给当前界面上所有的标签设置属性。由于通配符选择器是设置界面上所有的标签属性,所以在设置之前会遍历所有的标签,如果当前界面上的标签比较多,那么性能就会比较差。 继承:继承指当子元素没有设置某个属性时,会继承父元素的属性。 浏览器默认属性:浏览器本身设置好的属性,若未对元素设置属性,则会设置为浏览器默认属性。
注:关于继承的详情
不可继承的:display、margin、border、padding、background、height、min-height、max- height、width、min-width、max-width、overflow、position、left、right、top、 bottom、z-index、float、clear、table-layout、vertical-align、page-break-after、 page-break-before和unicode-bidi。
所有元素可继承:visibility和cursor。
内联元素可继承:letter-spacing、word-spacing、white-space、line-height、color、font、 font-family、font-size、font-style、font-variant、font-weight、text- decoration、text-transform、direction。
块状元素可继承:text-indent和text-align。
列表元素可继承:list-style、list-style-type、list-style-position、list-style-image。
表格元素可继承:border-collapse。 ::: 二、CSS权重 * 1.权重:** 第一等 :内联样式,如:style="color:red;",权值为 1000.(该方法会造成 css 难以管 理,所以不推荐使用)。 第二等 :ID 选择器,如:#header,权值为 0100。 第三等 :类、伪类、属性选择器如:.bar, 权值为 0010。 第四等 :标签、伪元素选择器,如:div ::first-line 权值为 0001。 最后把这些值加起来,再就是当前元素的权重了。 其他 : 无条件优先的属性只需要在属性后面使用!important。它会覆盖页面内任何位置定义 的元素样式。(ie6 支持上有些 bug) 通配符,子选择器,相邻选择器等。如,>,+, 权值为 0000。 继承的样式没有权值。 ** 2.CSS 权重计算方式** 2.1.计算选择符中的 ID 选择器的数量(=a) 2.2.计算选择符中类、属性和伪类选择器的数量(=b) 2.3.计算选择符中标签和伪元素选择器的数量(=c) 2.4.忽略全局选择器 2.5.在分别计算 a、b、c 的值后,按顺序连接 abc 三个数字组成一个新的数字,改值即 为所 计算的 选择符的权重。如果两个选择符的计算权重值相同,则采取“就近原则”。 示例:
div#app.child[name="appName"] /*a=1,b=2,c=1 —>权重 = 1 + 100 + 10 +10 = 121*/
注:CSS 选择器: 1、id 选择器( # myid) 2、类选择器(.myclassname) 3、标签选择器(div, h1, p) 4、相邻选择器(h1 + p) 5、子选择器(ul > li) 6、后代选择器(li a) 7、通配符选择器( * ) 8、属性选择器(a[rel = "external"]) 9、伪类选择器(a:hover, li:nth-child)
栅格体系 含义:是指采用JavaScript语言来实现响应式网格布局,可以在不同的屏幕尺寸下自适应地调整元素的大小和位置。它通常用于网站UI设计和前端开发中,可以帮助设计师和开发者更方便地实现布局和排版。
响应式 ------ 根据屏幕的不同分辨率,展示不同的样式
自适应 ------ 在不同的设备上加载不同的样式 ------- 必须使用js文件
响应式布局 答案同上
1.颜色:新增 RGBA,HSLA 模式 2.文字阴影 (text-shadow) 3.边框: 圆角(border-radius) 边框阴影: box-shadow 4.盒子模型: box-sizing 5.背景: background-size 设置背景图片的尺寸background-origin 设置背景图片的原点background-clip 设置背景图片的裁切区域以”,”分隔可以设置多背景,用于自适应布局 6.渐变: linear-gradient、 radial-gradient 7.过渡: transition,可实现动画 8.自定义动画 9.在 CSS3 中唯一引入的伪元素是 selection. 10.媒体查询,多栏布局 11.border-image 12.2D 转换: transform: translate(x,y) rotate(x,y) skew(x,y) scale(x,y) 13.3D 转换
WebStorm和vsCode一样也是一款开发神器。但是WebStorm无需下载vscode一样的很多插件,很多东西都已经配置好了,所以得学习里面的规则。
1、移动端
.font{ // 10px / 12px = 0.83 transform: scale(0.83);}
2、PC端 避免不支持 CSS3 浏览器的情况,我们也可以通过降级处理,将字体变回12px;最后兼容 IE:*font-size:10px;
.font{ font-size: 12px; transform: scale(0.83,0.83) ; *font-size: 10px;}
transcale(0.5)
圣杯布局和双飞翼布局的目的:
三栏布局,中间一栏最先加载和渲染(内容最重要,这就是为什么还需要了解这种布局的原因)。
两侧内容固定,中间内容随着宽度自适应。
一般用于 PC 网页。
圣杯布局和双飞翼布局的技术总结:
使用 float 布局。
两侧使用 margin 负值,以便和中间内容横向重叠。
防止中间内容被两侧覆盖,圣杯布局用 padding ,双飞翼布局用 margin 。
具体代码:
// todo 圣杯布局 // HTML <div id="container" class="clearfix"> <p class="center">我是中间</p> <p class="left">我是左边</p> <p class="right">我是右边</p> </div> // CSS #container { padding-left: 200px; padding-right: 150px; overflow: auto; } #container p { float: left; } .center { width: 100%; background-color: lightcoral; } .left { width: 200px; position: relative; left: -200px; margin-left: -100%; background-color: lightcyan; } .right { width: 150px; margin-right: -150px; background-color: lightgreen; } .clearfix:after { content: ""; display: table; clear: both; } // 双飞翼布局 // HTML <div id="main" class="float"> <div id="main-wrap">main</div> </div> <div id="left" class="float">left</div> <div id="right" class="float">right</div> // CSS .float { float: left; } #main { width: 100%; height: 200px; background-color: lightpink; } #main-wrap { margin: 0 190px 0 190px; } #left { width: 190px; height: 200px; background-color: lightsalmon; margin-left: -100%; } #right { width: 190px; height: 200px; background-color: lightskyblue; margin-left: -190px; }
tips:
上述代码中 margin-left: -100% 相对的是父元素的 content 宽度,即不包含 paddig 、 border 的宽度。 其实以上问题需要掌握 margin 负值问题 即可很好理解。
具体代码
.father { display: flex; justify-content: center; align-items: center; }
1、flex布局 2、子绝父相, position: absolute 和 transform: translate(-50%, -50%)。 3、table布局 4、grid网格布局
1. px 是绝对单位,固定的像素,一旦设置了就无法因为适应页面大小而改变 2. em 和rem相对于px更具有灵活性,他们是相对长度单位,意思是长度不是定死了的,更适用于响应式布局 3. em是相对长度单位,相对自身font-size,没有则相对于父元素, 4. rem相对于根元素的font-size
目的:Css 精灵图,把一堆小的图片整合到一张大的图片(png)上,减轻服务器对图片的请求数量 方法:再利用 css 的“background-image”、“background-repeat”、 “background-position”的组合进行背景定位
less是一种动态样式语言,属于css预处理器的范畴,它扩展了 CSS 语言, 增加了变量、Mixin、函数等特性,使 CSS 更易维护和扩展 LESS 既可以在 客户端 上运行 ,也可以借助Node.js在服务端运行。 #less中的变量 #使用@来申明一个变量:@pink:pink;
使用 CSS 的 text-overflow 属性来实现单行文本溢出的省略样式, 使用 white-space 和 overflow 属性来实现多行文本溢出的省略样式。
Reset 重置浏览器的 css 默认属性 ,浏览器的品种不同,样式不同,然后重置,让他们统一。(暴力的,强制的) • Normalize.css 是 css reset 的替代方案,保护有用的浏览器默认样式而不是完全去掉它们(温和的,根据浏览器特性的) • 一般化的样式:为大部分 HTML 元素提供 • 修复浏览器自身的 bug 并保证各浏览器的一致性 • 优化 CSS 可用性:用一些小技巧 • 解释代码:用注释和详细的文档来。
渐进增强 (progressive enhancement) : 针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。 (从被所有浏览器支持的基本功能开始,逐步地添加那些只有新式浏览器才支持的功能,向页面添加无害于基础浏览器的额外样式和功能。当浏览器支持时,它们会自动地呈现出来并发挥作用。) 优雅降级 (graceful degradation) :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。(Web 站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,则代码会检查以确认它们是否能正常工作。由于 IE 独特的盒模型布局问题,针对不同版本的IE 的 hack 实践过优雅降级了,为那些无法支持功能的浏览器增加候选方案,使之在旧式浏览器上以某种形式降级体验却不至于完全失效。) 区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给而渐进增强则是从一个非常基础的、能够起作用的版本开始,并不断扩充,以适应未来环境的需要。
额外标签法:在浮动元素的最后添加一个块级标签,给其设置一个clear:both 的属性 (缺点:会在页面上产生很多空白标签); 给浮动元素的父元素设置高度:(缺点:不太灵活) 给浮动元素的父元素设置 overflow:hidden; 使用伪元素法:(推荐使用)
IE盒模型(border-box) IE 盒模型:属性 width,height 包含 content、border 和 padding,指的是 content + padding + border 。 W3C标准盒模型(content-box) W3C 标准盒模型:属性 width ,height 只包含内容 content,不包含 border 和 padding 。
Flex布局/弹性布局特点: 是一种浏览器提倡的布局模型。 布局网页更简单、灵活。 避免浮动脱标的问题 作用: 基于 Flex 精确灵活控制块级盒子的布局方式,避免浮动布局中脱离文档流现象发生。 Flex布局非常适合结构化布局 设置方式 : 父元素添加 display: flex,子元素可以自动的挤压或拉伸。 组成部分 : 弹性容器 弹性盒子 主轴 侧轴/交叉轴
字体图标的优点: 灵活性:灵活地修改样式,例如:尺寸、颜色等 轻量级:体积小、渲染快、降低服务器请求次数 兼容性:几乎兼容所有主流浏览器 使用方法: Unicode法 先引入iconfont.css文件 复制粘贴图标对应的Unicode编码 设置文字字体 类名引用 先引入iconfont.css文件 调用图标对应的类名,必须调用2个类名 iconfont类:基本样式,包含字体的使用等 icon-xxx:图标对应的类名 设置文字字体
页面显示样式的优先级取决于其“特殊性”’,特殊性越高,就显示最高的,当特殊性相等时,显示后者. 特殊性表述为 4 个部分:0,0,0,0 一个选择器的特殊性如下: 对于选择器是#id 的属性值,特殊性值为:0,1,0,0 对于属性选择器,class 或伪类,特殊性值为:0,0,1,0 对于标签选择器或伪元素,特殊性值为:0,0,0,1 通配符‘*’特殊性值为:0,0,0,0 内联样式特殊性值为:1,0,0,0
none: 表示隐藏对象,与visibility属性的hidden值不同,display:none不为被隐藏的对象保留物理空间 ,然visibility:hidden就保留 inline(默认值):表示指定对象为内联元素 block: 指定对象为块元素。 list-item: 指定对象为列表项目 inline-block: 指定对象为内联块元素。(这是CSS2中的属性) table: 指定对象作为块元素级的表格。类同于html标签table(CSS2) inline-table: 指定对象作为内联元素级的表格。类同于html标签table(CSS2) table-caption: 指定对象作为表格标题。类同于html标签caption(CSS2) table-cell: 指定对象作为表格单元格。类同于html标签td(CSS2) table-row: 指定对象作为表格行。类同于html标签tr(CSS2) table-row-group: 指定对象作为表格行组。类同于html标签tbody(CSS2) table-column: 指定对象作为表格列。类同于html标签col(CSS2) table-column-group: 指定对象作为表格列组显示。类同于html标签colgroup(CSS2) table-header-group: 指定对象作为表格标题组。类同于html标签thead(CSS2) table-footer-group: 指定对象作为表格脚注组。类同于html标签tfoot(CSS2) run-in: 根据上下文决定对象是内联对象还是块级对象。(CSS3) box: 将对象作为弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3) inline-box: 将对象作为内联块级弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3) flexbox: 将对象作为弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3) inline-flexbox: 将对象作为内联块级弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3) flex: 将对象作为弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3) inline-flex: 将对象作为内联块级弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)
边框图片需要通过4个属性来设置 border-image-source 用在边框图片的路径(确定图片) border-image-slice 图片边框向内偏移(裁剪的尺寸,一定不加单位,上右下左的顺序) border-image-width 边框的宽度(需要加单位) border-image-repeat 用于设置边框图片是否应该平铺,铺满或拉伸(默认拉伸)
常用容器属性有: flex-direction,取值: row; // 默认 横向 从左往右依次排列所有项目 row-reverse; // 横向 从右往左依次排列所有项目 column; // 纵向 从上往下依次排列所有项目 column-reverse; // 纵向 从下往上依次排列所有项目 flex-wrap,取值: nowrap; // 默认 一行显示所有项目(项目超出宽度减少项目宽度) wrap; // 从左往右显示,宽度不够往下换一行接着显示 (项目超出宽度自动换行) wrap-reverse; // 从最下面一行依次从左往右显示,宽度不够往上换行接着显示 flex-flow,是flex-direction和flex-wrap的简写 取值: column wrap; // 从上往下排列 空间不够自动换行 justify-content,取值: center; // 居中对齐 space-between; // 第一个项目排在起点 最后一个项目排在终点 均匀排列每个元素 space-around; // 每个元素周围分配相同的空间 均匀排列每个元素 align-items,取值: flex-start; // 垂直方向 顶点对齐 flex-end; // 垂直方向 底部对齐 center; // 垂直方向 居中对齐 baseline; // 垂直以基线对齐 align-content,该属性对单行弹性盒子模型无效,取值: center; // 垂直方向 将项目放置在中点 space-between; // 第一列项目排在顶点 最后一列项目排在底部 均匀分布项目 space-around; // 均匀分布项目
原因 情况一:浮动元素无法撑开标准流的父元素,导致父元素高度塌陷 解决方法: 1.直接给父元素设置该高度 2.使用额外标签法清除浮动 3.使用单伪元素清除法 4.使用双伪元素清除法 给父元素设置overflow:hidden 情况二:互相嵌套的块级元素,给子元素设置margin-top,父子元素的margin-top会合并,父元素会一起往下移动 1.给父元素设置border-top 2.给父元素设置padding-top 3.设置浮动 4.转换成行内块元素 5.给父元素设置overflow:hidden
1,编译环境不同,scss是通过ruby 在服务器端处理,less是通过js编译,在客户端处理 2,变量符不一样,less是用@,scss是用$ 3,scss支持条件语句,可以使用if{}else{},for{}循环等等。而less不支持。 4,工具库不同
rgba ()和opacity都能实现透明效果,但最大的不同是opacity作用于元素,以及元素内的所有内容的透明度,而rgba ()只作用于元素的颜色或其背景色。
两栏布局非常常见,往往是以一个定宽栏和一个自适应的栏并排展示存在 使用 float 左浮左边栏 右边模块使用 margin-left 撑出内容块做内容展示 为父级元素添加BFC,防止下方元素飞到上方内容 实现三栏布局中间自适应的布局方式有: 两边使用 float,中间使用 margin 两边使用 absolute,中间使用 margin 两边使用 float 和负 margin display: table 实现 flex实现 grid网格布局
BFC(Block Formatting Context): #即块级格式化上下文,它是页面中的一块渲染区域,并且有一套属于自己的渲染规则: 1、内部的盒子会在垂直方向上一个接一个的放置 2、对于同一个BFC的俩个相邻的盒子的margin会发生重叠,与方向无关。 3、每个元素的左外边距与包含块的左边界相接触(从左到右),即使浮动元素也是如此 4、BFC的区域不会与float的元素区域重叠 5、计算BFC的高度时,浮动子元素也参与计算 6、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然 BFC目的是形成一个相对于外界完全独立的空间,让内部的子元素不会影响到外部的元素 触发BFC的条件包含不限于: 根元素,即HTML元素 浮动元素:float值为left、right overflow值不为 visible,为 auto、scroll、hidden display的值为inline-block、inltable-cell、table-caption、table、inline-table、flex、inline-flex、grid、inline-grid position的值为absolute或fixed
可以使用 CSS 的 text-overflow 属性来实现单行文本溢出的省略样式, 使用 white-space 和 overflow 属性来实现多行文本溢出的省略样式。
步骤: 1、创建XMLHttpRequest对象,也就是创建一个异步调用对象. 2、创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息. 3、设置响应HTTP请求状态变化的函数. 4、发送HTTP请求. 5、获取异步调用返回的数据. 6、使用JavaScript和DOM实现局部刷新. get和post请求的区别: 1、GET没有请求主体,使用xhr.send(null) 2、GET可以通过在请求URL上添加请求参数 3、POST可以通过xhr.send('name=cat&age=10') 4、POST需要设置请求头xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 5、GET效率更好(应用多) 6、GET大小限制约4K,POST则没有限制 7、GET请求有缓存相对没那么安全,但是可添加到收藏夹上,POST没有缓存,无法添加到收藏夹
同源源策略是浏览器的一项安全策略,浏览器只允许 js 代码请求和当前所在服务器域名,端口,协议相同的数据接口上的数据,这就是同源策略 为什么会有同源策略? 我们都知道 JavaScript 可以操作 web 文档的内容,试想,如果不对这一点加以限制,那么 JS 可以做的事情就太多了,危险性也太高,所以就针对它可以操作哪些文档的内容有了一个限制,这个限制就是同源策略。 同源策略在什么情况下会起作用呢? 当 web 页面使用多个<iframe>元素或者打开其他浏览器窗口的时候,这一策略就会起作用 同源策略的含义: 脚本只能读取和所属文档来源相同的窗口和文档的属性。这里就涉及到了一个浏览器如何判断两者是否同源以及如何判断脚本来源的问题。注意一点:脚本本身的来源并不作为判断是否同源的依据,而是将脚本所属文档的来 源作为判断依据。 1. 判断脚本来源 例如:文档 A 中通过 script 的 src 引用了一个外部脚本,这个脚本是google 提供的,也是从 google 的主机上加载到文档 A 中的,那么这个脚本的所属文档是谁呢,答案是文档 A。 2. 判断是否同源 理解了脚本来源,接着理解怎么判断是否同源:如果两个文档在协议、主机以及载入文档的 URL 端口这三点中有一点不同,就认为他们不同源。
● HTTP是一种用于 传输超媒体文档 的应用层协议。它是一种无状态协议,即服务器不会记住与客户端之间的通信状态。HTTP 协议使用 TCP 协议作为传输层协议,通常使用 80 端口 HTTP 和 HTTPS 的区别主要有以下几点: 安全性:HTTP 传输的数据是明文的,容易被窃听和篡改,而 HTTPS 使用 SSL/TLS 协议对数据进行加密传输,可以有效保护数据的安全性。 传输速度:HTTPS 比 HTTP 传输速度慢,因为 HTTPS 需要进行加密和解密操作。 端口号:HTTP 使用 80 端口,HTTPS 使用 443 端口。 证书:为了使用 HTTPS,需要从数字证书认证机构(CA)获得 SSL/TLS 证书,证书中包含了网站的公钥和其他信息,用于验证网站的身份和加密通信。
含义:通过请求一个JS文件,JS文件会执行一个回调,回调中就存在我们需要跨域获取的数据。回调的名字是一个随机生成的随机数,将这个名字以callback的参数传给后台,后台会将该函数返回并执行。 优点: 它的兼容性更好,在更加古老的浏览器中都可以运行,不需要 XMLHttpRequest 或 ActiveX 的支持;能够直接访问响应文本,支持在浏览器与服务器之间双向通信。 缺点: 1. JSONP 是从其他域中加载代码执行。如果其他域不安全,很可能会在响应中夹带一 些恶意代码,而此时除了完全放弃 JSONP 调用之外,没有办法追究。因此在使用不是你 自己运维的 Web 服务时,一定得保证它安全可靠。 2. 它只支持 GET 请求而不支持 POST 等其它类型的 HTTP 请求;它只支持跨域 HTTP 请 求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题
步骤: 1、创建XMLHttpRequest对象,也就是创建一个异步调用对象. 2、创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息. 3、设置响应HTTP请求状态变化的函数. 4、发送HTTP请求. 5、获取异步调用返回的数据. 6、使用JavaScript和DOM实现局部刷新.
定义: 查询字符串(URL参数)是指在URL的末尾加上用于向服务器发送信息的字符串(变量) 格式: 将英文的'?'放在URL的末尾,然后再加上'参数=值',可以使用'&'符号进行分隔加多个参数,这个形式可以将想要发送给服务器的数据添加到URL中 //不带参数的URL地址 www.liulongbin.top:3006/api/getbooks //带一个参数的URL地址 www.liulongbin.top:3006/api/getbooks?id=1 //带两个参数的URL地址 www.liulongbin.top:3006/api/getbooks?id=1&bookname=西游记
axios 是通过 promise 实现对aiax技术的一种封装,就像jQuery 实现 ajax 封装一样。 简单来说:ajax技术实现了网页的局部数据刷新axios实现了对ajax的封装。axios是ajax ajax不止axios。 优缺点: ajax: 1.本身是针对MVC的编程不符合现在前端 MVVM的浪潮 2.基于原生的XHR开发,XHR本身的架构不清 晰,已经有了fetch的替代方案 3.JQuery整个项目太大,单纯使用aiax却要引 入整个JQuery非常的不合理 (采取个性化打 包的方案又不能享受CDN服务 axios: 1.从nodejs 创建 http 请求 2.支持 Promise AP 3.客户端支持防止CSRF4.提供了一些并发请求的接口 (重要,方便了很多的操作)
在JS中,每一个对象都有一个原型(prototype),它是一个对象。原型对象可以包含属性和方法,可以被继承,这样的继承机制就叫原型链。 Javascript 是面向对象的,每个实例对象都有一个__proto_属性,该属性指向它原型对象,这个实例对象的构造函数有一个原型属性 prototype,与实例的__proto__属性指向同一个对象。当一个对象在查找一个属性的时,自身没有就会根据__proto__ 向它的原型进行查找,如果都没有,则向它的原型的原型继续查找,直到查到Object.prototype._proto_为 null,这样也就形成了原型链。
字符串方法: 1. length: 长度 2. indexOf('文本',指定索引位置查找): 返回字符串中指定文本首次出现的索引, 没有找到 返回 -1 lastindexOf 3. search(): 方法搜索特定值的字符串 4. slice(起始索引,终止索引): 提取字符串某个部分并返回新的字符串 5. split() : 字符串切割成若干个段,返回一个数组 6. replace(): 替换字符串,返回新的字符串,默认地,只替换首个匹配,接受正则 /gi 7. toUpperCase(): 把字符串转换为大写 8. toLowerCase(): 把字符串转换为小写 9. trim() 方法删除字符串两端的空白符 10. includes: 字符串中是否包含特定值,返回布尔值 11、charCodeAt 方法返回一个整数,代表指定位置字符的 Unicode 编码; 12、charAt 方法返回指定索引位置处的字符。如果超出有效范围的索引值返回空字符串; 13、substring 方法返回位于 String 对象中指定位置的子字符串。 14、substr 方法返回一个从指定位置开始的指定长度的子字符串 15、concat 方法返回字符串值,该值包含了两个或多个提供的字符串的连接; =========================================================== #新增 concat:用于将一个或多个字符串拼接成一个字符串 #删除 slice、substr、substring都是调用他们的一个子字符串,都接收1或2个参数 let stringValue = "hello world"; console.log(stringValue.slice(3)); // "lo world" console.log(stringValue.substring(3)); // "lo world" console.log(stringValue.substr(3)); // "lo world" console.log(stringValue.slice(3, 7)); // "lo w" console.log(stringValue.substring(3,7)); // "lo w" console.log(stringValue.substr(3, 7)); // "lo worl" #修改 trim、trimLeft、trimRight:删除前、后或前后所有空格符,再返回新的字符串 repeat:接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果 padEnd: 复制字符串,如果小于指定长度,则在相应一边填充字符,直至满足长度条件 let stringValue = "foo"; console.log(stringValue.padStart(6)); // " foo" console.log(stringValue.padStart(9, ".")); // "......foo" toLowerCase()、 toUpperCase() 大小写转化 #查 charAt:返回指定索引位置的字符,由传给方法的整数参数指定 indexOf:从字符串开头去搜索传入的字符串,并返回位置(如果没找到,则返回 -1) startWith、includs:从字符串中搜索传入的字符串,并返回一个表示是否包含的布尔值 #转换 split #模板匹配方法 match:接收一个参数,可以是一个正则表达式字符串,可以是RegExp对象,返回对象 search:接收一个参数,可以是一个正则表达式字符串,也可以是一个RegExp对象,找到则返回匹配索引,否则返回 -1 replace:接收俩个参数,第一个参数为匹配的内容,第二个参数为替换的元素
#含义:俩个相互嵌套的函数,内部函数可以访问外部函数的变量 #优点:形成私有空间,避免全局变量的污染 #缺点:持久化存储,会导致内存泄漏 #解决: ○ 1、尽快避免函数的嵌套,以及变量的引用 ○ 2、执行完的变量,可以赋值null,触发垃圾回收机制,进行回收释放内存 #手写闭包 function init() { var name = 'zs', function test(){ console.log(name) } test() } #手写递归 function init(x,n){ if(n === 1){ return x } else { return x * init(x, n - 1) } } console.log(init(2, 2))
1. 存储容量不同:cookie的存储容量最小,只有4KB左右,而localStorage和sessionStorage的存储容量可以达到5MB左右。 2. 有效期不同:cookie的有效期可以设置,可以在一定时间内保持数据有效,而localStorage和sessionStorage没有有效期,除非手动删除。 3. 存储方式不同:cookie的数据会在每次请求时都被发送到服务器,而localStorage和sessionStorage的数据只存储在客户端,不会被发送到服务器。 4. 访问方式不同:cookie可以被JavaScript和服务器端访问,而localStorage和sessionStorage只能被JavaScript访问。 5. 安全性不同:cookie的安全性较低,容易被篡改,而localStorage和sessionStorage的安全性较高,难以被篡改。
Object 是 JavaScript 中所有对象的父对象 数据封装类对象:Object、Array、Boolean、Number、String 其他对象:Function、Argument、Math、Date、RegExp、Error
答: 1. javascript 引擎只有一个线程,强迫异步事件排队等待被执行。 2. setTimeout 和 setInterval 本质上不同的地方是他们如何执行异步代码的。 3. 如果一个定时器正在执行的时候被阻塞了,那么它将会被推迟到下一个可能的执行点,这既是使得延迟时间有可能会超过声明定时器时设置的值。 4. Interval 如果有足够的时间来执行(大于制定的延迟),那么它将会无延迟的一个紧接着一个执行。 原理: 计时器通过设定一定的时间段(毫秒)来异步的执行一段代码。因为 Javascript 是一个单线程语言,计时器提供了一种绕过这种语言限制来执行代码的能力。 总结: 计时器是单线程的, 需要等待上一个执行完, 如果上一个没有执行完, 下一个需要延迟执行, 直到上一个执行完
数组方法: 1. push pop shift unshift 2. arr.splice(从哪开始删除,删除几个,添加的项1,添加的项2,......) 3. slice(起始索引,终止索引): 用数组的某个片段切出新数组 4. toString(): 数组转字符串 5、every: 所有为true才为true some: 某一个为true即可true 6、map: 映射 -> 收集每项的值,不会改变数组长度 -> 返回新数组 7、filter: 过滤 -> 保留为true的项,可能会改变数组长度 -> 返回新数组 8、find: 查找项,没找到 返回 undefined
宏任务与微任务都是异步任务,都是在同一个任务队列中,区别在他们的执行顺序。 在异步任务队列下,又分为宏任务与微任务队列 先走微任务,再走宏任务。当一个宏任务执行结束之前,会在任务队列执行栈中查找是否有微任务,如果有则执行,没有则开启一个新的宏任务,所以微任务总是再宏任务结束之前执行的。 #常见的宏任务有 script(整体代码) setTimeout setInterval #微任务 Promise.then process.nextTick(Node.js 环境)
浏览器缓存是指浏览器在本地存储一些已经请求过的资源,如图片、CSS、JS等,下次请求同样的资源时可以直接从缓存中获取,从而提高页面加载速度。浏览器缓存机制通常分为两种:强缓存和协商缓存。强缓存是指浏览器在一定时间内直接从缓存中获取资源,不会向服务器发送请求,通常通过设置响应头中的Expires或Cache-Control来实现。而协商缓存是指浏览器需要向服务器发送请求验证资源是否有更新,如果资源未更新则从缓存中获取,否则从服务器重新获取,通常通过设置响应头中的Last-Modified和ETag来实现。 常见的缓存策略包括: 1. 强制缓存:通过设置响应头中的Expires或Cache-Control实现,可以缓存一定时间内不会变化的资源。 2. 协商缓存:通过设置响应头中的Last-Modified和ETag实现,可以缓存可能会变化的资源,并在下次请求时 通过If-Modified-Since和If-None-Match头向服务器验证资源是否有更新。 3. 禁止缓存:通过设置响应头中的Cache-Control为no-cache或Pragma为no-cache实现,告诉浏览器不要缓 存该资源。
1、在全局作用域中,this指向全局对象。在浏览器,全局对象中 window,在Node.js中,全局对象是global 2、在函数中,默认情况下,this指向被调用方法的对象。 3、箭头函数中,this指向的是所在作用域的this。箭头函数没有自己的this,因此它不会改变指向。 4、可以使用 call、apply 或 bind 方法显式地指定 this 的指向。
区别: for...in 语句用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。 for in得到对对象的key或数组,字符串的下标 for of和forEach一样,是直接得到值 for of不能用于对象
1.原型链继承(根本方式) 2.构造函数继承 3.组合继承 4.原型式继承 5.寄生时继承 6.寄生组合式继承 原型继承:修改了当前的原型链, 通过修改实例对应的原型对象, 原型替换 --> 只能继承方法,不能继承属性 组合继承: 原型替换 + call硬绑定this, 指向对应的原型对象 --> 通过call修改this指向 寄生组合继承: Object.create(参数对象)创建出新对象 + call硬绑定 --> 通过object.create传入新对象,会自动指向到新对象身上
一、 利用length let arr=[1,2,3]; arr[arr.length-1] //3 二、 数组pop方法 , 删除数组的最后一位 并返回 会修改原数组 let arr=[1,2,3]; arr.pop() //3 三、 数组slice方法,返回值为包含最后一位元素的新数组 let arr=[1,2,3]; arr.slice(-1) //[3] 四、 数组at方法(ES2022新特性) let arr=[1,2,3]; arr.at(-1) //3 五、数组 reverse()方法可以用于颠倒数组中元素的顺序,最前面的元素会变成最后面的元素。 let arr = [1,2,3] arr.reverse()[0]
答:简单的说类是对象的模版。 在 js 中没有类, 所以在 js 中所谓的 类 就是构造函数, 对象就是由构造函数创建出来的实例对象。面向对象就是使用面向对象的方式处理问题, 面向对象是对面向过程进行封装。 面向对象有三大特性 抽象性, 需要通过核心数据和特定环境才能描述对象的具体意义 封装性, 封装就是将数据和功能组合到一起, 在 js 中对象就是键值对的集合, 对象将属性和方法封装起来, 方法将过程封装起来 继承性, 将别人的属性和方法成为自己的, 传统继承基于模板(类), js 中继承基于构造函数
typeof 一般判断基本数据类型。是一个操作符而不是函数,圆括号可有可无。 typeof 返回值有:string,number,boolean,undefined,object ,function, 基本数据类型:Boolean、Number、String、Undefined、Null 基本数据类型中数字,字符串,布尔类型返回其对类型 undefined 返回 undefined 九大内置构造函数及其他所有函数返回 function; 其他所有复杂类型对象和 null 返回 object alert(typeof [1, 2]); //object alert(typeof 'leipeng'); //string var i = true; alert(typeof i); //boolean alert(typeof 1); //number var a; alert(typeof a); //undefined function a(){;}; alert(typeof a) //function
第一种(函数声明): function sum1(num1,num2){ return num1+num2; } 第二种(函数表达式) var sum2 = function(num1,num2){ return num1+num2; } 第三种(函数对象方式) var sum3 = new Function("num1","num2","return num1+num2");
#含义:JS在创建内存的时候回自动分配内存,在不使用的时候会自动周期性的释放内存 #一方面自动分配内存减轻了开发者的负担,开发者不用过多的去关注内存使用,但是另一方面,正是因为因为是自动回收,所以如果不清楚回收的机制,会很容易造成混乱,而混乱就很容易造成"内存泄漏"。 #垃圾回收对是否需要回收的问题主要依赖于对变量的判定是否可访问,由此衍生出两种主要的回收算法: #标记清除:就是标记处被引用的对象,清除未标记的对象 #引用计数:就是对引用次数计数,引用次数大于0则不清除,等于0时清除该对象
含义:new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。 1、创建一个新的空对象{} 2、this指向新对象 3、执行构造函数,去添加新属性 4、最后会自动返回新对象,构造函数里面不需要写return
call 和 apply 会调用函数, 并且改变函数内部this指向. call 和 apply 传递的参数不一样, call 传递参数 aru1, aru2..形式 apply 必须数组形式[arg] bind 不会调用函数, 可以改变函数内部this指向.
答: 事件冒泡:子元素事件的触发会影响父元素事件; 开关事件冒泡: A,开启事件冒泡:element.addEventListener(eventName,handler, false); B,关闭事件冒泡:假设传统方式事件的返回值为 e,就可以通过 e.stopPropagation()来关闭事件冒泡; 事件捕获:父元素的事件会影响子元素的事件; 开启事件捕获:element.addEventListener(eventName,handler,true) e.stopPropagation(); 阻止默认事件: function stopDefault( e ) { //阻止默认浏览器动作(W3C) if ( e && e.preventDefault ) e.preventDefault(); //IE 中阻止函数器默认动作的方式 else window.event.returnValue = false; return false; }
规则:(列举几个,需要的百度) ^表示匹配行首的文本(从谁开始) $表示匹配行尾的文本(以谁结束) +表示重复至少 1 次 ? 表示重复 0 次或1次 \* 表示重复 0 次或多次 {m, n} 表示复 m 到 n 次 [ ] 匹配字符集合 [ ] 里面加上 ^ 取反符号 方法: 1. 判断是否有符合规则的字符串:regObj.test( 被检测字符串 );返回的是布尔值,找到返回true,否则false; 2. 检索 (查找)符合规则的字符串:regObj.exec(被检测字符串);找到返回数组,否则为 null.
防抖: 单位时间内 频繁触发操作多次, 只执行最后一次 1.设置空的延时器 nu11 2.事件触发时,清空当前的延时器 3.再次开启一个延时器,直到监测到某个延时器结束后再发送请求 节流: 单位时间内 频繁触发同一操作,只会触发一次 1.初始化一个标识 flag,布尔值为true 2.事件处理函数中,判断flag如果为true 先置为false,再发送当前请求 3,当获取到响应成功的结果后,将flag置为true 4。这样一个循环往复的过程,就实现了节流 防抖:search搜索,用户在不断输入值时,用防抖来节约请求资源; 节流: 1. 鼠标不断触发某时间的时候,mousedown(单位时间内只发一次);2.监听滚动事件
一、创建节点、追加节点 1、createElement(标签名)创建一个元素节点(具体的一个元素)。 2、createTextNode(节点文本内容)创建一个文本节点 3、createDocumentFragment() //创建一个 DOM 片段 4、appendChild(节点)追加一个节点。 二、插入节点 1、appendChild(节点)也是一种插入节点的方式,还可以添加已经存在的元素,会将其元素从原来的位置移到新的位置。 2、insertBefore(a,b)是参照节点,意思是 a 节点会插入 b 节点的前面。 三、删除、移除节点 1、removeChild(节点) 删除一个节点,用于移除删除一个参数(节点)。其返回的被移除的节点,被移除的节点仍在文档中,只是文档中已没有其位置了。 四、复制节点 cloneNode() 方法,用于复制节点, 接受一个布尔值参数, true 表示深复制(复制节点及其所有子节点), false 表示浅复制(复制节点本身,不复制子节点) 五、替换节点 1、replaceChild(插入的节点,被替换的节点) ,用于替换节点,接受两个参数,第一参 数是要插入的节点,第二个是要被替换的节点。返回的是被替换的节点。 六、查找节点 1、getElementsByTagName() //通过标签名称 2、getElementsByName() //通过元素的 Name 属性的值(IE 容错能力较强,会得到 一个数组,其中包括 id 等于 name 值的) 3、getElementById() //通过元素 Id,唯一性
args剩余参数和 arguments对象的区别 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。 arguments对象不是一个真正的数组,而剩余参数是真正的 Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach或pop。 arguments对象还有一些附加的属性 (如callee属性)。
预解析 JavaScript 代码的执行是由浏览器中的 JavaScript 解析器来执行的。 JavaScript 解析器 执 行 JavaScript 代码的时候,分为两个过程:预解析过程和代码执行过程 预解析过程: 1.把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值 2.把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用 3.先提升 function,在提升 var JavaScript 的执行过程: // 案例 1 var a = 25; function abc() { alert(a); // undefined var a = 10; } abc(); // 案例 2 console.log(a); // 25 function a() { console.log('aaaaa') // 不会执行, 没人调用 a() } var a = 1; console.log(a); // 1 变量提升 变量提升: 定义变量的时候,变量的声明会被提升到作用域的最上面,变量的赋值不会提升 函数提升: JavaScript 解析器首先会把当前作用域的函数声明提前到整个作用域的最前面 //1、----------------------------------- var num = 10; fun(); function fun() { console.log(num); var num = 20; } //2、----------------------------------- var a = 18; f1(); // 调用执行 22 行, 因为后者覆盖前者 f1 函数 function f1() { var b = 9; console.log(a); console.log(b); var a = '123'; } // 3、----------------------------------- f1(); // 再次调用下面的 f1 执行 console.log(c); // 9 console.log(b); // 9 console.log(a); // 18 function f1() { var a = b = c = 9; //这里相当于 var a = 9; b = 9; c = 9, 所以后2个隐藏转换为全局变量了 console.log(a); // 9 console.log(b); // 9 console.log(c); // 9 } 变量声明提升: 使用 var 关键字定义的变量,被称为变量声明 函数声明提升的特点是: 在函数声明的前面,可以调用这个函数
Arguments函数参数集合 arguments[]函数参数的数组 Arguments一个函数的参数和其他属性 Arguments.callee 当前正在运行的函数 Arguments.length 传递给函数的参数的个数 Array 数组 length 属性动态获取数组长度 join(将一个数组转成字符串。返回一个字符串。 reverse0将数组中各元素颠倒顺序 delete 运算符 只能删除数组元素的值,而所占空间还 在,总长度没变(arr.length)。 shift(删除数组中第一个元素,返回删除的那个值,并 将长度减 1。 pop(删除数组中最后一个元素,返回删除的那个值, 并将长度减 1。 unshift 往数组前面添加一个或多个数组元素,长度 要改变。 arrObj.unshift(“ push0往数组结尾添加一个或多个数组元素,长度要 66 6g concat) 连接数组 slice()返回数组的一部分 sort()对数组元素进行排序 splice()插入、删除或替换数组的元素 toLocaleString()把数组转换成局部字符串 toString()将数组转换成一个字符串 Boolean 布尔对象 Boolean.toString() 将布尔值转换成字符串 Boolean.valueOf()Boolean 对象的布尔值 Date日期时间 创建Date对象的方法 (1)创建当前(现在)日期对象的实例,不带任何参数 var today = new Date() (2)创建指定时间戳的日期对象实例,参数是时间戳。 时间戳:是指某一个时间距离 1970年1月1日0时0分0秒,过去了多少毫秒值(1秒=1000 毫秒)。 (3) 指定一个字符串的日期时间信息,参数是一个日 期时间字符串 var timer = new Date(“2015/5/25 10: 00: 00); (4)指定多个数值参数 var timer = new Date(2015+100,4,25,10,20. 0); //顺序为:年、月、 日、时、分、秒,年、月、日是必须的。 方法: Date.getDay( ) 返回一周中的某一天 Date.getFullYear( ) 返回 Date 对象的年份字段 Date.getHours( ) 返回 Date 对象的小时字段 Date.getMilliseconds( ) 返回 Date 对象的毫秒字段 Date.getMinutes( ) 返回 Date 对象的分钟字段 Date.getMonth( ) 返回 Date 对象的月份字段 Date.getSeconds( ) 返回 Date 对象的秒字段 Date.getTime( ) 返回 Date 对象的毫秒表示 Date.getTimezoneOffset( ) 判断与 GMT 的时间差 Date.getUTCDate( ) 返回该天是一个月的哪一天(世界时) Date.getUTCDay( ) 返回该天是星期几(世界时) Date.getUTCFullYear( ) 返回年份(世界时) Date.getUTCHours( ) 返回 Date 对象的小时字段(世界时) Date.getUTCMilliseconds( ) 返回 Date 对象的毫秒字段(世界时) Date.getUTCMinutes( ) 返回 Date 对象的分钟字段(世界时) Date.getUTCMonth( ) 返回 Date 对象的月份(世界时) Date.getUTCSeconds( ) 返回 Date 对象的秒字段(世界时) Date.getYear( ) 返回 Date 对象的年份字段(世界时) Date.parse( ) 解析日期/时间字符串 Date.setDate( ) 设置一个月的某一天 Date.setFullYear( ) 设置年份,也可以设置月份和天 Date.setHours( ) 设置 Date 对象的小时字段、分钟字段、秒字段和毫秒字段 Date.setMilliseconds( ) 设置 Date 对象的毫秒字段 Date.setMinutes( ) 设置 Date 对象的分钟字段和秒字段 Date.setMonth( ) 设置 Date 对象的月份字段和天字段 Date.setSeconds( ) 设置 Date 对象的秒字段和毫秒字段 Date.setTime( ) 以毫秒设置 Date 对象 Date.setUTCDate( ) 设置一个月中的某一天(世界时) Date.setUTCFullYear( ) 设置年份、月份和天(世界时) Date.setUTCHours( ) 设置 Date 对象的小时字段、分钟字段、秒字段和毫秒字段(世界时) Date.setUTCMilliseconds( ) 设置 Date 对象的毫秒字段(世界时) Date.setUTCMinutes( ) 设置 Date 对象的分钟字段和秒字段(世界时) Date.setUTCMonth( ) 设置 Date 对象的月份字段和天数字段(世界时) Date.setUTCSeconds( ) 设置 Date 对象的秒字段和毫秒字段(世界时) Date.setYear( ) 设置 Date 对象的年份字段 Date.toDateString( ) 返回 Date 对象日期部分作为字符串 Date.toGMTString( ) 将 Date 转换为世界时字符串 Date.toLocaleDateString( ) 回 Date 对象的日期部分作为本地已格式化的字符串 Date.toLocaleString( ) 将 Date 转换为本地已格式化的字符串 Date.toLocaleTimeString( ) 返回 Date 对象的时间部分作为本地已格式化的字符串 Date.toString( ) 将 Date 转换为字符串 Date.toTimeString( ) 返回 Date 对象日期部分作为字符串 Date.toUTCString( ) 将 Date 转换为字符串(世界时) Date.UTC( ) 将 Date 规范转换成毫秒数 Date.valueOf( ) 将 Date 转换成毫秒表示 Error 异常对象 Error.message 可以读取的错误消息 Error.name 错误的类型 Error.toString( ) 把 Error 对象转换成字符串 EvalError 在不正确使用 eval()时抛出 SyntaxError 抛出该错误用来通知语法错误 RangeError 在数字超出合法范围时抛出 ReferenceError 在读取不存在的变量时抛出 TypeError 当一个值的类型错误时,抛出该异常 URIError 由 URl 的编码和解码方法抛出 Function 函数构造器 Function.apply( ) 将函数作为一个对象的方法调用 Function.arguments[] 传递给函数的参数 Function.call( ) 将函数作为对象的方法调用 Function.caller 调用当前函数的函数 Function.length 已声明的参数的个数 Function.prototype 对象类的原型 Function.toString( ) 把函数转换成字符串 Math 数学对象 Math 对象是一个静态对象 Math.PI 圆周率。 Math.abs() 绝对值。 Math.ceil() 向上取整(整数加 1,小数去掉)。 Math.floor() 向下取整(直接去掉小数)。 Math.round() 四舍五入。 Math.pow(x,y) 求 x 的 y 次方。 Math.sqrt() 求平方根。 Number 数值对象 Number.MAX_VALUE 最大数值 Number.MIN_VALUE 最小数值 Number.NaN 特殊的非数字值 Number.NEGATIVE_INFINITY 负无穷大 Number.POSITIVE_INFINITY 正无穷大 Number.toExponential( ) 用指数计数法格式化数字 Number.toFixed( ) 采用定点计数法格式化数字 Number.toLocaleString( ) 把数字转换成本地格式的字符串 Number.toPrecision( ) 格式化数字的有效位 Number.toString( ) 将—个数字转换成字符串 Number.valueOf( ) 返回原始数值 Object 基础对象 Object 含有所有 JavaScript 对象的特性的超类 Object.constructor 对象的构造函数 Object.hasOwnProperty( ) 检查属性是否被继承 Object.isPrototypeOf( ) 一个对象是否是另一个对象的原型 Object.propertyIsEnumerable( ) 是否可以通过 for/in 循环看到属性 Object.toLocaleString( ) 返回对象的本地字符串表示 Object.toString( ) 定义一个对象的字符串表示 Object.valueOf( ) 指定对象的原始值 RegExp 正则表达式对象 RegExp.exec( ) 通用的匹配模式 RegExp.global 正则表达式是否全局匹配 RegExp.ignoreCase 正则表达式是否区分大小写 RegExp.lastIndex 下次匹配的起始位置 RegExp.source 正则表达式的文本 RegExp.test( ) 检测一个字符串是否匹配某个模式 RegExp.toString( ) 把正则表达式转换成字符串 String 字符串对象 Length 获取字符串的长度。如:var len = strObj.length toLowerCase() 将字符串中的字母转成全小写。如:strObj.toLowerCase() toUpperCase() 将字符串中的字母转成全大写。如:strObj.toUpperCase() charAt(index) 返回指定下标位置的一个字符。如果没有找到,则返回空字符串。 substr() 在原始字符串,返回一个子字符串 substring() 在原始字符串,返回一个子字符串。 区别:''' “abcdefgh”.substring(2,3) = “c” “abcdefgh”.substr(2,3) = “cde” ''' split() 将一个字符串转成数组。 charCodeAt( ) 返回字符串中的第 n 个字符的代码 concat( ) 连接字符串 fromCharCode( ) 从字符编码创建—个字符串 indexOf( ) 返回一个子字符串在原始字符串中的索引值(查找顺序从左往右查找)。如果没有找到,则返回-1。 lastIndexOf( ) 从后向前检索一个字符串 localeCompare( ) 用本地特定的顺序来比较两个字符串 match( ) 找到一个或多个正则表达式的匹配 replace( ) 替换一个与正则表达式匹配的子串 search( ) 检索与正则表达式相匹配的子串 slice( ) 抽取一个子串 toLocaleLowerCase( ) 把字符串转换小写 toLocaleUpperCase( ) 将字符串转换成大写 toLowerCase( ) 将字符串转换成小写 toString( ) 返回字符串 toUpperCase( ) 将字符串转换成大写 valueOf( ) 返回字符串
1、typeof:检测基础数据类型和函数 它能准确判断出的数据类型有:Number,String,Boolean,Undefined,Symbol,BigInt,Function。 它的缺点就是不能准确判断 null 的类型,而是返回 “object”。对于数组,日期,普通对象等数据,统一返回 “object”。 所以在判断基本数据类型(除了 null)和函数类型时,都会使用它。 2、constructor:返回实例对象的构造函数 构造函数的原型对象上会有一个 constructor 属性,指向了构造函数自身,所以实例对象通过原型链访问 constructor 属性,就能找到自己的构造函数,也就是自己的类型了。 它的本意是用来标识自己的构造函数,却临时拉来当壮丁,用来判断数据类型,当然也存在一定的风险: null,undefined 没有构造函数,自然也就访问不到该属性,因此不能使用此属性来判断 constructor 可以被改写,所以不一定准确。 3、instanceof:沿着原型链去找 它的作用是检测实例对象是不是属于某个构造函数,可以用来做数据类型的检测。 缺点: 不能检测基本数据类型 原型链可能被修改,导致检测结果不准确 只要能在原型链上找到构造函数,就返回 true,所以类型可能不准确 4、Object.prototype.toString 专门检测数据类型 它返回的值是一个形如 [object Object] 的字符串 5、Symbol.toStringTag:自定义类型 Symbol.toStringTag 是一个内置符号属性,它的值是一个字符串,用于表示一个对象的默认描述,也就是调用 Object.prototype.toString 会返回的内容 对于自定义对象,调用上面的方法,都只会返回 [object Object]。此时就可以使用 Symbol.toStringTag 来指定一个确定的类型了 6、Object.prototype.isPrototypeOf isPrototypeOf 和 instanceof 类似,都是基于原型链和原型对象去做判断的。它用来检查一个对象是否存在于另一个对象的原型链上。 7、Array.isArray Array.isArray([]) // true 8、Number.isNaN JS 中有一个特殊的“数字” NaN,表示 not a number,不是一个数字,但它却归属于数字类型 console.log(typeof NaN) // 'number' isNaN(10) // false isNaN('abc') // true isNaN(NaN) // true 9、等比较:与固定值进行比较 let value = null console.log(value === null) // true // 同时判断一个值是 undefined 或者 null let value console.log(value == null) // true
JS 中有多种方法可以将多个数组合并成一个数组。 1、使用 Array.prototype.concat() 合并:concat() 方法可以将多个数组合并成一个新数组。 let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let arr3 = [7, 8, 9]; let mergedArr = arr1.concat(arr2, arr3); console.log(mergedArr); // [1, 2, 3, 4, 5, 6, 7, 8, 9] 2、使用扩展运算符 (...) 合并:扩展运算符可以将多个数组合并成一个新数组。 let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let arr3 = [7, 8, 9]; let mergedArr = [...arr1, ...arr2, ...arr3]; console.log(mergedArr); // [1, 2, 3, 4, 5, 6, 7, 8, 9] 3、使用 Array.prototype.push.apply() 合并:push.apply() 方法可以将多个数组合并成一个新数组。 let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let arr3 = [7, 8, 9]; let mergedArr = [].concat.apply([], [arr1, arr2, arr3]); console.log(mergedArr); // [1, 2, 3, 4, 5, 6, 7, 8, 9] 4、使用 Array.prototype.reduce() 合并: reduce() 函数可以用来构建新数组,将多个数组元素添加到新数组中。 let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let arr3 = [7, 8, 9]; let mergedArr = [arr1, arr2, arr3].reduce((acc, cur) => acc.concat(cur), []); console.log(mergedArr); // [1, 2, 3, 4, 5, 6, 7, 8, 9] 5、使用 Array.prototype.forEach() 合并: forEach() 方法可以遍历多个数组,将元素添加到新数组中。 let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let arr3 = [7, 8, 9]; let mergedArr = []; [arr1, arr2, arr3].forEach(function(array) { array.forEach(function(element) { mergedArr.push(element); }); }); console.log(mergedArr); // [1, 2, 3, 4, 5, 6, 7, 8, 9] 6、使用第三方库 lodash 的 concat() 合并 7、使用第三方库 Ramda 的 concat() 合并
#方法一:利用Set const res1 = Array.from(new Set(arr)); #方法二:两层for循环+splice const unique1 = arr => { let len = arr.length; for (let i = 0; i < len; i++) { for (let j = i + 1; j < len; j++) { if (arr[i] === arr[j]) { arr.splice(j, 1); // 每删除一个树,j--保证j的值经过自加后不变。同时,len--,减少循环次数提升性能 len--; j--; } } } return arr; } #方法三:利用indexOf const unique2 = arr => { const res = []; for (let i = 0; i < arr.length; i++) { if (res.indexOf(arr[i]) === -1) res.push(arr[i]); } return res; } 当然也可以用include、filter,思路大同小异。 #方法四:利用include const unique3 = arr => { const res = []; for (let i = 0; i < arr.length; i++) { if (!res.includes(arr[i])) res.push(arr[i]); } return res; } #方法五:利用filter const unique4 = arr => { return arr.filter((item, index) => { return arr.indexOf(item) === index; }); } #方法六:利用Map const unique5 = arr => { const map = new Map(); const res = []; for (let i = 0; i < arr.length; i++) { if (!map.has(arr[i])) { map.set(arr[i], true) res.push(arr[i]); } } return res; }
伪数组 同样具有length属相 按照索引方式存储数据 不具有数组的push.pop等方法 像调用getElementsByTagName,document.childNodes之类的,它们都返回 NodeList对象都属于伪数组 真数组和伪数组的区别 1 .真数组的长度是可变的 ,伪数组是不可变的 2.真数组可以使用数组中的方法(.forEach),伪数组是不能够使用的 3.真数组可以使用原型辨别,伪数组没有__proto__和prototype 伪数组转化为真数组 1.通过[].slice.call(argument) 2.通过Array.prototype.slice.call(argument) 3.通过Array.from(argument)
一、undefined类型转化为数字类型 Number(undefined) //NaN 二、null类型转化为数字类型 Number(null) //0 三、Boolean值类型转化为数字类型 Number(true) //1 Number(false) //0 四、字符串类型转换为数字类型 Number("123s") //NaN Number("123") //123 如果传入的只含有数字的字符串,则直接转化为数字,如果包含其他非数字的字符串,则返回NaN. 五、Symbol类型转化为数字类型 Number("Symbol(12)") //报错 六、对象类型转化为数字类型 对象类型的数据首先先转化为基本数据类型,转化之后,再按照上述几点进行转换。 对象内部使用toPrimitive(input)来解决问题, 具体的解决方案:如果input为基本数据类型则直接返回,如果不是,则调用valueOf方法,如果是基本数据类型,则返回。否则再调用toString()方法,如果是基本数据类型则返回,否则报错。 例子: console.log([1,2,3] == '1,2,3') //true 这个是因为右边是基本数据类型,左边使用[1,2,3].toString()转换为基本数据类型, console.log("play" == true) //这里左边执行toPrimity()转化为NaN,右边转换为1
重绘:浏览器重新绘制收到影响的部分到屏幕上,这个过程叫做重绘 触发重绘:单独改变DOM的样式而不改变尺寸的大小 重排(回流):当渲染树需要更新并且DOM尺寸(宽高)发生了变化,同时其他的DOM就会受到影响,浏览器就会重新构建渲染树,这个过程就叫重排(回流) 触发重排:添加或删除可见的 DOM ,DOM 位置发生变化,DOM 尺寸大小发生变化,页面初次 渲染,浏览器窗口尺寸发生变化 关系:重绘不一定会重排(回流),重排(回流)一定会重绘
JSON 是轻量级的文本数据交换格式,它使用 JS语法来描述数据对象,支持多种语言,并且具有自我描述性,更易理解.它不仅可以将 JS 对象和字符串值进行转换,,还可以通过parse将符合json标准的字符串转化为js对象
mouseover 和 mouseenter 是两种不同的 JavaScript 事件。 mouseover 事件在鼠标指针移动到元素上方或其子元素上方时触发。 mouseenter 事件则是在鼠标指针进入元素时触发,但不会在其子元素上触发。
答:js是单线程执行的,页面加载时,会从上到下执行主线程上的同步任务,当主线程代码执行完毕时,才开始执行在任务队列中的异步任务。具体如下 1.所有同步任务都在主线程上执行,形成一个执行栈。 2.主线程之外,还存在一个"任务队列(eventloop队列或者消息队列)"。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。 3.一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。哪些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。 4.主线程不断重复上面的第三步。
1、Undefined 和 Null 都是基本数据类型 2、undefined 代表的含义是 未定义 ,null 代表的含义是 空对象 。 3、一般变量声明了但还没有定义的时候会返回 undefined,一般变量声明了但还没有定义的时候会返回 undefined 例: let a, console.log(a), // undefined null主要用于赋值给一些可能会返回对象的变量,作为初始化。 4、undefined 可以作为一个变量名(void 0 ==> 来获取),但是很危险,不推荐 5、两种类型使用 typeof 进行判断时,Null 类型化会返回 “object” 重点:console.log(undefined == null) // true console.log(undefined === null) // false
单页 Web 应用 (single-page application 简称为 SPA) 是一种特殊的Web 应用。它将所有的活动局限于一个 Web 页面中,仅在该 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。 优点: (1)良好的交互式体验,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染; (2)基于上面所说,SPA 对服务器的压力小; (3)前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理。 缺点: (1)初次加载耗时多,为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载(可以使用路由懒加载解决) (2)由于单页应用在一个页面中显示,所以不可以使用浏览器自带的前进后退功能,想要实现页面切换需要自己进行管理 (3)SEO 难度较大,由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。 (4)有兼容性问题,部分平台不支持pushstate
sort()方法
var arr = [123,203,23,13,34,65,65,45,89,13,1]; function func(a,b){ return a-b; } console.log(arr.sort(func)); //(11) [1, 13, 13, 23, 34, 45, 65, 65, 89, 123, 203]
选择排序
基本思想:1、找出最大(小)值放在数组的起始位置 2、从剩余元素中继续寻找最大(小)元素,返回放在已排数组的末尾 重复第二步
var arr = [123,203,23,13,34,65,65,45,89,13,1]; for(var i=0;i<arr.length;i++){ for(var j=i+1;j<arr.length;j++){ //如果第一个比第二个大,就交换他们两个位置 if(arr[i]>arr[j]){ var temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } console.log(arr); //(11) [1, 13, 13, 23, 34, 45, 65, 65, 89, 123, 203]
冒泡排序(重点)
基本思想:**俩俩比较**相邻的数,不符合则互换位置,一次比较就能将最大(小)值放在最后一位 继续对除**【最后一位】**之外的所有元素重复上述过程
var arr = [123,203,23,13,34,65,65,45,89,13,1]; for(var i=0; i<arr.length-1; i++){ //每一轮比较要比多少次 for(var j=0; j<arr.length-1-i; j++){ //如果第一个比第二个大,就交换他们两个位置 if(arr[j]>arr[j+1]){ var temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } console.log(arr); //(11) [1, 13, 13, 23, 34, 45, 65, 65, 89, 123, 203]
插入排序
快速排序(递归)
js中数组排序的五种方式_js 数组排序_不甜呐的博客-CSDN博客
typeof的返回值是一个字符串,用来说明变量的数据类型; instanceof的返回值是布尔值,用于判断一个变量是否属于某个对象的实例。 相同点:JavaScript 中 typeof 和 instanceof 常用来判断一个变量是否为空, 或者是什么类型的 不同点: typeof 操作符返回一个字符串,表示未经计算的操作数的类型 typeof 一般只能返回如下几个结果: number, boolean, string, function, object, undefined。 对于 Array, Null 等特殊对象使用 typeof 一律返回 object, 这正是 typeof 的局限性。 instanceof: 1、返回值为布尔值 2、instanceof 用于判断一个变量是否属于某个对象的实例。 3、instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型。
方法一:将对象转换成字符串,再判断是否等于“{}” let obj={}; console.log(JSON.stringify(obj)==="{}"); //返回true 方法二:for in循环 let result=function(obj){ for(let key in obj){ return false;//若不为空,可遍历,返回false } return true; } console.log(result(obj));//返回true 方法三:Object.keys()方法,返回对象的属性名组成的一个数组,若长度为0,则为空对象(ES6的写法) console.log(Object.keys(obj).length==0);//返回true 方法四:Object.getOwnPropertyNames方法获取对象的属性名,存到数组中,若长度为0,则为空对象 console.log(Object.getOwnPropertyNames(obj).length==0);//返回true 方法五:jQuery中的isEmptyObject()方法,其原理是利用for in的方式来判断(注意:使用这种方式记得引用jquery) console.log($.isEmptyObject(obj));//true
执行上下文: 执行上下文是一种对Javascript代码执行环境的抽象概念,也就是说只要有Javascript代码运行,那么它就一定是运行在执行上下文中 执行上下文的类型分为三种: 全局执行上下文:只有一个,浏览器中的全局对象就是 window对象,this 指向这个全局对象 函数执行上下文:存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文 Eval 函数执行上下文: 指的是运行在 eval 函数中的代码,很少用而且不建议使用 执行栈:也叫调用栈,具有 LIFO(后进先出)结构,用于存储在代码执行期间创建的所有执行上下文 当Javascript引擎开始执行你第一行脚本代码的时候,它就会创建一个全局执行上下文然后将它压到执行栈中 每当引擎碰到一个函数的时候,它就会创建一个函数执行上下文,然后将这个执行上下文压到执行栈中 引擎会执行位于执行栈栈顶的执行上下文(一般是函数执行上下文),当该函数执行结束后,对应的执行上下文就会被弹出,然后控制流程到达执行栈的下一个执行上下文
内存泄漏(Memory leak)是在计算机科学中,由于疏忽或错误造成程序未能释放已经不再使用的内存 并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。 #意外的全局变量 function foo(arg) { bar = "this is a hidden global variable"; } #另一种意外的全局变量可能由 this 创建: function foo() { this.variable = "potential accidental global"; } // foo 调用自己,this 指向了全局对象(window) foo(); 上述使用严格模式,可以避免意外的全局变量 #定时器也常会造成内存泄露 var someResource = getData(); setInterval(function() { var node = document.getElementById('Node'); if(node) { // 处理 node 和 someResource node.innerHTML = JSON.stringify(someResource)); } }, 1000);
浏览器的事件循环机制,也称为事件轮询,是指浏览器在执行代码时,将任务分为两类:同步任务和异步任务。同步任务会在主线程上依次执行,形成一个执行栈。而异步任务则会被推入事件队列(Event Queue)中,等待主线程调用栈中的所有同步任务都执行完毕后,再被依次执行。 事件队列中的异步任务分为宏任务和微任务两种类型。宏任务包括setTimeout、setInterval、I/O等,而微任务则包括Promise、MutationObserver等。在主线程中每次执行完一个宏任务后,都会检查微任务队列是否有任务需要执行,如果有则依次执行所有微任务,执行完所有微任务后再执行下一个宏任务,如此循环往复。 这种机制保证了JavaScript代码的执行顺序,同时也能够处理异步任务,使得JavaScript具有并发处理的能力。
宏任务与微任务都是异步任务,都是在同一个任务队列中,主要区别在于它们的执行顺序。 在异步任务队列下 ,又分为宏任务队列与微任务队列。 先走微任务,再走宏任务。当一个宏任务执行结束之前,会在微任务队列执行栈中查找是否有微任务,如果有则执行,没有则开启一个新的宏任务,所以微任务总是在宏任务结束之前执行的。 常见的宏任务有 script(整体代码) setTimeout setInterval 微任务 Promise.then process.nextTick(Node.js 环境)
JavaScript异步编程是指在代码执行过程中,不会阻塞后续代码的执行,而是通过异步方式来处理某些操作,如定时器、网络请求、文件读写等。常见的异步编程方式包括回调函数、Promise、async/await等。 回调函数是JavaScript中最基础的异步编程方式,通过将一个函数作为参数传递给另一个函数,在完成某个操作后调用该函数来实现异步操作。 Promise是ES6中新增的一种异步编程方式,它可以更加清晰地表达异步操作的状态,包括进行中、成功、失败等,通过链式调用then和catch方法来处理异步操作的结果。 async/await是ES8中新增的一种异步编程方式,它可以让异步代码看起来像同步代码一样,通过async函数和await关键字来实现异步操作。 JavaScript异步编程的实现原理主要是通过事件循环机制来实现的。当JavaScript执行异步代码时,会将该代码交给事件循环机制处理,然后继续执行后续的同步代码,当异步操作完成后,会将回调函数加入到任务队列中,等待事件循环机制将其取出执行。这种方式能够确保异步代码不会阻塞后续代码的执行,从而提高程序的性能。
#DOM 指的是文档对象模型,它指的是把文档当做一个对象,这个对象主要定义了处理网页内容的方法和接口。 #BOM 指的是浏览器对象模型,它指的是把浏览器当做一个对象来对待,这个对象主要定义了与浏览器进行交互的法和接口。BOM的核心是 window,而 window 对象具有双重角色,它既是通过 js 访问浏览器窗口的一个接口,又是一个 Global(全局)对象。这意味着在网页中定义的任何对象,变量和函数,都作为全局对象的一个属性或者方法存在。window 对象含有 location 对象、navigator 对象、screen 对象等子对象,并且 DOM 的最根本的对象 document 对象也是 BOM 的 window 对象的子对象。
JQuery优秀的 Javascript 库。 它是轻量级的 js 库 ,它兼容 CSS3,还兼容各种浏览器(IE 6.0+, FF1.5+, Safari 2.0+, Opera 9.0+),jQuery2.0 及后续版本将不再支持 IE6/7/8 浏览器。jQuery 使用户能更方便地处理 HTML(标准通用标记语言下的一个应用)、events、实现动画效果,并且方便地为网站提供AJAX 交互。 jQuery 还有一个比较大的优势是,它的文档说明很全,而且各种应用也说得很详细,同时还有许多成熟的插件可供选择。 jQuery 能够使用户的 html 页面保持代码和html 内容分离,也就是说,不用再在 html 里面插入一堆 js 来调用命令了,只需要定义 id即可。 jQuery核心理念是 write less,do more(写得更少,做得更多)。 同时它还是免费、开源的,使用 MIT 许可协议。 它的语法设计可以使开发更加便捷,例如操作文档对象、选择 DOM 元素、制作动画效果、事件处理、使用 Ajax 以及其他功能。 除此以外,jQuery 提供 API 让开发者编写插件。其模块化的使用方式使开发者可以很轻松的开发出功能强大的静态或动态网页。
1.jQuery是使用选择器($)选取DOM对象,对其进行赋值、取值、事件绑定等操作,数据和界面是在一起的。 2.Vue则是把值和js对象进行绑定,然后修改js对象的值,Vue框架就会自动把dom的值就行更新。对数据进行操作不再需要引用相应的DOM对象 3.区别 简单来说,最明显的就是思维方式不同,jquery 是以操作dom为主,做了数据处理之后还需要对dom进行操作。vue.js是以操作数据为主,不操作dom,也就是传说中的双向数据绑定,你只需要操作数据就好,dom自动更新。这只是对初学者来说最大的不同。jquery只是一个类库,只是提供了很多的方法,不能算框架,而vue.js是一个框架,有一套完整的体系
TS (TypeScript) 是一种开源的编程语言,它是 JavaScript 的超集,也就是说 TypeScript 扩展了 JavaScript 的功能,并且在其基础上增加了类型系统等特性。以下是 TypeScript 的作用: 1. 强类型:TypeScript 通过引入静态类型检查机制,可以帮助开发者在编写代码的过程中更早地捕捉到潜在的错误,提高了代码的健壮性和可维护性。 2. 代码提示:TypeScript 可以为 IDE 和编辑器提供更精准的代码提示和补全,使得开发效率更高。 3. 可读性:TypeScript 中定义类型的语法使得代码更易于阅读和理解,同时也方便代码的维护。 4. 更好的协作:TypeScript 可以促进团队协作,因为它规范了代码的格式、结构和接口等方面,让团队成员之间的沟通更加清晰。 5. 向后兼容:TypeScript 可以编译成纯 JavaScript 代码,这意味着现有的 JavaScript 项目可以渐进式地迁移到 TypeScript,而不会影响现有的代码库和生态系统。 总之,TypeScript 可以改善 JavaScript 在大型项目开发中出现的一些缺陷,提高代码的可维护性和可读性,从而帮助开发者更轻松地构建高质量的应用程序。
约定了什么类型,就只能给变量赋值该类型的值,否则,就会报错 #作用:给变量添加类型约束,约定了什么类型,代码提示清晰 #TS 新增类型 联合类型 自定义类型 接口 元组 枚举
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。 1、数组解构 数组的解构赋值要一一对应,如果有对应不上的就是 undefined 2、对象解构 对象的属性没有次序,变量必须与属性同名,才能取到正确的值
Promise 是异步编程的一种解决方案,将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。 异步操作“未完成”(pending) 异步操作“已完成”(resolved,又称fulfilled) 异步操作“失败”(rejected) 异步操作成功,Promise对象传回一个值,状态变为resolved。 异步操作失败,Promise对象抛出一个错误,状态变为rejected。 Promise的状态会凝固,⼀旦promise的状态被修改了,就会状态凝固,不能再更新状态了 对于已经实例化过的 promise 对象可以调用 promise.then() 方法,传递 resolve 和 reject 方法作为回调。then()方法接收两个参数:onResolve 和 onReject,分别代表当前promise 对象在成功或失败时
ES6 标准中,JavaScript 原生支持模块(module)了。这种将 JS 代码分割成不同功能的小块进行模块化,将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用。 export 用于对外输出本模块(一个文件可以理解为一个模块)变量的接口。 import 用于在一个模块中加载另一个含有 export 接口的模块。 import 和 export 命令只能在模块的顶部,不能在代码块之中。
forEach: 遍历 map: 映射 -> 收集每项的值,不会改变数组长度 -> 返回新数组filter: 过滤 -> 保留为true的项,可能会改变数组长度 -> 返回新数组reduce: 求和累加,携带参数 起始累加值 every: 所有为true才为true some: 某一个为true即可true from: 伪数组转真数组 -> 伪数组: 只具备Tength可以被遍历,不具备数组的其它方法 find: 查找项,没找到 返 undefined findIndex: 查找下标值,没找到 返回 -1
#rest参数,用于获取函数的实参,代替 arguments,将接收的参数序列转化为一个数组对象 !语法格式: fn(a,b,...args),写在参数的最后面 #应用场景:参数不定的情况 let fn = (a, b, ...args) => { console.log(a); console.log(b); console.log(args); }; fn(1, 2, 3, 4, 5); // 1 2 [3,4,5]
#将一个数组、伪数组转化为用逗号分隔的参数序列,对数组、对象进行解包 #运用:数组合并 #1、数组合并 #2、数组克隆,浅拷贝 let arr = [ 1, 2, 3 ] let arr2 = [...arr] console.log(arr) #3、将伪数组转化为真数组 const divs = document.querySelectorAll('div') let divs = [...divs] console.log(divs) #4、对象合并
#set是一种常见的数据结构,类似于数组 ● Set 是一种无序的数据集合,其中的元素都是唯一的。Set 中的元素可以是任意类型的值。 ★ Set 支持的操作包括添加、删除、查找和枚举,可以使用 for-of 循环来遍历 Set 中的所有元素。 #属性和方法 ● st.size: 返回的集合个数 ● st.add(item):添加,返回当前集合 ● st.delete(item):删除,返回boolean值 ● st.has(item):判断,返回boolean值 ● st.clear():清空集合 ● 集合转化为数组: [...st] ● 合并俩个集合:[...st1, ...st2] 以下是一个简单的 Set 的使用示例: const set = new Set([1, 2, 3, 4, 5]); console.log(set.has(3)); // true console.log(set.has(6)); // false set.add(6); set.delete(5); for (const value of set) { console.log(value); } 在这个示例中,我们创建了一个 Set 对象,并通过构造函数传入了一个数组 [1, 2, 3, 4, 5]。然后我们使用 Set 的 has() 方法来检查 Set 中是否存在某个元素。接下来我们使用 add() 方法向 Set 中添加一个新元素 6,并使用 delete() 方法删除 Set 中的元素 5。最后我们使用 for-of 循环遍历 Set 中的所有元素。 #数组去重 let arr1 = [1,2,3,3,4,5] let res1 = [1,2,3,4,5] console.log(res1) // [1,2,3,4,5] #数组求交集 let arr2_1 = [1,2,3,4,5] let arr2_2 = [7,6,3,4,5] let res2 = arr2_1.filter(v=> new Set(arr2_2).has(v)) console.log(res2) // [3,4,5] #数组求并集 let arr3_1 = [1,2,3,4,5] let arr3_2 = [7,6,3,4,5] let res3 = [...new Set([...arr3_1, ...arr3_2])] console.log(res2) // [1,2,3,4,5,6,7] #数组求差集 let arr4_1 = [1,2,3,4,5] let arr4_2 = [7,6,3,4,5] let res4 = [...new Set(arr4_1)].filter(v=> !(new Set(arr4_2).has(v))) console.log(res2) // [1,2]
● Map 是一种无序的键值对集合,其中的元素都是以键值对的形式存储的。Map 中的键和值可以是任意类型的值。 ● Map 支持的操作包括添加、删除、查找和枚举,可以使用 for-of 循环来遍历 Map 中的所有元素。 #Map的属性和方法: (k为键,v为值) ● size: 返回 Map 的元素 (键值对) 个数 ● set(k,v): 增加一个键值对,返回当前 Map ● get(k): 返回键值对的键值 ● has(): 检测 Map 中是否包含某个元素 ● clear(): 清空集合,返回 undefinedclear 以下是一个简单的 Map 的使用示例: const map = new Map([ ['name', 'John'], ['age', 30] ]); console.log(map.get('name')); // John console.log(map.get('age')); // 30 map.set('country', 'USA'); map.delete('age'); for (const [key, value] of map) { console.log(`${key}: ${value}`); } 在这个示例中,我们创建了一个 Map 对象,并通过构造函数传入了一个数组 [ ['name', 'John'], ['age', 30] ]。然后我们使用 Map 的 get() 方法来获取 Map 中的元素值。接下来我们使用 set() 方法向 Map 中添加一个新的键值对 ['country', 'USA'],并使用 delete() 方法删除 Map 中的键值对 ['age', 30]。最后我们使用 for-of 循环遍历 Map 中的所有元素。
ES6 标准中,JavaScript 原生支持模块(module)了。这种将 JS 代码分割成不同功能的小块进行模块化,将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用。 export 用于对外输出本模块(一个文件可以理解为一个模块)变量的接口。 import 用于在一个模块中加载另一个含有 export 接口的模块。 import 和 export 命令只能在模块的顶部,不能在代码块之中。
用一对反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符 串,也可以在字符串中嵌入变量,js 表达式或函数,变量、js 表达式或函数需要写在${ }中
1.重复声明 var允许重复声明,let、const不允许 2.变量提升 var会提升变量的声明到作用域的顶部,但let和const不会(说白了就是let和const没有变量提升) 3.暂时性死区 只要作用域内存在let、const,它们所声明的变量或常量就会自动“绑定”这个区域,不再受外部作用域的影响 4.window对象的属性和方法(全局作用域中) 全局作用域中,var声明的变量,通过function声明的函数,会自动变为window对象的变量,属性或方法,但const和let不会 5.块级作用域 var没有块级作用域,let和const有块级作用域
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。 1、数组解构 数组的解构赋值要一一对应,如果有对应不上的就是 undefined 2、对象解构 对象的属性没有次序,变量必须与属性同名,才能取到正确的值
箭头函数基本语法: 1. 箭头函数属于表达式函数,因此不存在函数提升; 2. 箭头函数只有一个参数时可以省略圆括号 (); 3. 箭头函数函数体只有一行代码时可以省略花括号 {},并自动做为返回值被返回; 4. 加括号的函数体返回对象字面量表达式; 箭头函数参数: 1. 普通函数有arguments 动态参数 2. 箭头函数没有 arguments 动态参数,但是有剩余参数 ..args 箭头函数this: 箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this。
一、.then 方法是 Promise 对象添加状态改变时的回调函数,有两个参数。 then的第一个参数是一个函数,它在promise被解析时运行,并接收结果。 then的第二个参数是一个函数,当promise被拒绝时运行,并接收错误。 如果我们只对成功完成感兴趣,那么我们只能为.then提供一个函数参数 二、 .catch是用于指定当promise对象的状态从pending变成rejected的回调函数 。 如果我们只对错误感兴趣,那么可以使用null作为第一个参数:.then(null, errorHandlingFunction)。或者我们可以使用.catch(errorHandlingFunction),两者完全相同; 调用.catch(f)完全是对.then(null, f)的模拟,它只是一个简写。 三、 .finally 1. finally 方法用来指定在 promise 结束时,无论结果是 fulfilled 或者是 rejected,都会执行的回调函数。这样可以避免同样的语句需要在 then() 和 catch() 中都要写一次的情况。 2. finally 方法的回调函数不接受任何参数,这意味着没有办法知道前面的 Promise 状态到底是 fulfilled 还是 rejected。这表明,finally 仅用于无论最终结果如何都要执行的情况,而不能依赖 Promise 执行结果。 3. finally 方法本身无异常抛出的情况下,总是会返回原来的 Promise 对象值;若抛出异常,则返回异常的 Promise 对象。
reject 是用来抛出异常,catch 是用来处理异常 reject 是 Promise 的方法,而 catch 是 Promise 实例的方法 reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch 网络异常 (比如断网),会直接进入catch而不会进入then的第二个回调
#async和await 俩种语法可以让异步代码变成同步 #async修饰函数的声明,await修饰函数的调用,被 await 修饰的函数必须返回一个promise 异步对象,使用 await 修饰后,就会将 promise 异步对象转换成一个同步操作. async/await中的return/throw会代理自己返回的Promise的resolve/reject,而一个Promise的resolve/reject会使得await得到返回值或抛出异常。 如果方法内无await节点 return 一个字面量则会得到一个{PromiseStatus: resolved}的Promise。 throw 一个Error则会得到一个{PromiseStatus: rejected}的Promise。 如果方法内有await节点 async会返回一个{PromiseStatus: pending}的Promise(发生切换,异步等待Promise的执行结果)。 Promise的resolve会使得await的代码节点获得相应的返回结果,并继续向下执行。 Promise的reject 会使得await的代码节点自动抛出相应的异常,终止向下继续执行。 ============================================================================ async/await 的特点: 1. async/await 是基于 Promise 的:async 函数返回一个 Promise 对象,可以使用 then() 方法进行链式调用。 2. async/await 代码更加简洁易读:async/await 可以让我们使用同步代码的方式来编写异步代码,避免了回调地狱,代码更加简洁易读。 3. async/await 可以捕获异常:使用 try-catch 可以轻松地捕获异步操作中的异常。 4. async/await 可以处理异步函数中的返回值:可以使用 await 关键字来等待 Promise 对象的解决,然后返回异步操作的结果。 async/await 的使用场景: 1. 异步操作:适用于任何需要异步操作的场景,比如从服务器获取数据、读取文件等等。 2. 串行执行异步操作:可以使用 async/await 实现串行执行异步操作,保证操作的顺序和正确性。 3. 错误处理:可以使用 try-catch 捕获异步操作中的异常,从而更容易地处理错误。 总之,async/await 是一种更加简洁易读、更易于处理异步操作的方式,可以提高代码的可维护性和可读性,是现代前端开发中不可或缺的一部分。
1、注册内网的gitLab账号 2、项目管理员拉我进项目 3、有了权限后,git clone 'url' 项目到本地 4、自己创建新的项目分支git branch '分支名' 5、开始编码。。。。。。。。。。 =========================================================== 6、git clone 默认是下载了所有分支的代码 7、git branch-r 查看项目所有分支 8、git branch-a 查看项目所有远程分支 9、git checkout '分支名' 切换分支 10、git branch 打印出来所有包括自己的分支 11、git log 查看提交记录,退回英文状态下Q 12、git reflog 查看修改记录(包括git reset的回退记录) 13、git reset --hard(conmmit id) 回退版本 14、git stash 代码放进暂存区(未被commit的代码) 15、git stash apply 还原 16、git stash drop 清除最近一次的stash记录 17、git stash pop 还原并清除最近一次stash 18、git stash list 查看暂存列表 19、git stash clear 清空所有的stash记录 20、git remove -v 显示所有的远程仓库 21、git remove add url 添加一个远程仓库 22、git remove rm name 删除远程仓库 23、git remove rename old name new name 修改仓库名 git init # 在本地新建一个仓库 git add # 将工作区的修改提交到暂存区 git commit # 将暂存区的修改提交到当前分支 git reset # 回退到某一个版本 git stash # 保存某次修改 git pull # 从远程更新代码 git push # 将本地代码更新到远程分支上 git reflog # 查看历史命令 git status # 查看当前仓库的状态 git diff # 查看修改 git log # 查看提交历史 git revert # 回退某个修改
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。 Node.js 的包管理器 npm,是全球最大的开源库生态系统。 NodeJS 的特点 其特点为: 1. 它是一个 Javascript 运行环境 2. 依赖于 Chrome V8 引擎进行代码解释 3. 事件驱动 4. 非阻塞 I/O 5. 轻量、可伸缩,适于实时数据交互应用 6. 单进程,单线程 NodeJS 的优缺点: 优点:1. 高并发(最重要的优点)2. 适合 I/O 密集型应用 缺点:1. 不适合 CPU 密集型应用;CPU 密集型应用给 Node 带来的挑战主要是:由于JavaScript 单线程的原因,如果有长时间运行的计算(比如大循环),将会导致 CPU 时间片不能释放,使得后续 I/O 无法发起; 2. 只支持单核 CPU,不能充分利用 CPU 3. 可靠性低,一旦代码某个环节崩溃,整个系统都崩溃 4. 开源组件库质量参差不齐,更新快,向下不兼容 5. Debug 不方便,错误没有 stack trace 原因:单进程,单线程 解决方案: (1)分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞 I/O调用的发起; (2)Nnigx 反向代理,负载均衡,开多个进程,绑定多个端口; (3)开多个进程监听同一个端口,使用 cluster 模块;
#####
1、GIT 是分布式的,SVN 是集中式的 2、git 是每个历史版本都存储完整的文件,便于恢复,svn 是存储差异文件,历史版本不可恢复。(核心) 3、git 可离线完成大部分操作,svn 则不能。 4、git 有着更优雅的分支和合并实现。 5、git 有着更强的撤销修改和修改历史版本的能力 6、Git 下载下来后,在本地不必联网就可以看到所有的 log,很方便学习,SVN 却需要联网;git 速度更快,效率更高。 7、Git 没有一个全局的版本号,而 SVN 有。
区别1:模块加载的时间 require:运行时加载 import:编译时加载(效率更高)【由于是编译时加载,所以import命令会提升到整个模块的头部】 区别2:模块的本质 require:模块就是对象,输入时必须查找对象属性 import:ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,再通过 import 命令输入(这也导致了没法引用 ES6 模块本身,因为它不是对象)。 区别3:严格模式 CommonJs模块和ES6模块的区别: (1)CommonJs模块默认采用非严格模式 (2)ES6 的模块自动采用严格模式,不管你有没有在模块头部加上 “use strict”; (3)CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。 require 的性能相对于 import 稍低。 因为 require 是在运行时才引入模块并且还赋值给某个变量,而 import 只需要依据 import 中的接口在编译时引入指定模块所以性能稍高
Git 工作区包括以下几个部分: 1. 本地仓库:本地仓库是 Git 管理的文件的集合,它存储在本地磁盘上。 2. 工作目录:工作目录是用来修改和查看文件的地方。它包含了本地仓库中的文件的实际内容,也就是我们平常使用的文件。 3. 暂存区(Staging Area):暂存区是用来准备下一次提交的地方。当我们在工作目录中修改了文件,如果想要把这些修改提交到本地仓库,就需要先把修改的文件添加到暂存区。 4. 版本库(Repository):版本库是用来存储所有提交的地方。它包含了所有的提交历史,以及每次提交时本地仓库的快照。 在 Git 中,我们通常会在工作目录中修改文件,然后使用 git add . 命令将修改的文件添加到暂存区,再使用 git commit 命令将暂存区中的修改提交到本地仓库。本地仓库中的文件就会更新为最新的版本,同时也会把提交记录存储到版本库中。
从输入url到页面加载完成发生了什么 1. 解析URL,判断url是否合法,然后浏览器查找当前URL是否存在缓存,并比较缓存是否过期。 2. DNS解析URL对应的IP。 3. 根据IP建立TCP连接(三次握手)。 4. HTTP发起请求。 5. 服务器处理请求,浏览器接收HTTP响应。 6. 渲染页面,构建DOM树。 7. 关闭TCP连接(四次挥手)。
含义:本地存储是H5新增的API,用来在本地存储数据,在不影响服务器性能的情况下来在本地存储大量的数据。 使用: 存储数据 localStorage.setItem("key","val") 在本地存储中键是唯一的,如果存储相同键的数据,后面的值会把前面的值覆盖掉 读取数据 localStorage.getItem("key") //清除当前数据 localStorage.removeItem("key") 流程: 本地存储的数据都是以键值对的形式存储 key value key和value都必须为字符串,如果需要存储数组或者对象类型的数据需要将数组或者对象用JSON.stringify()转换为字符串类型 本地存储分为localStorage和sessionStorage localStorage和sessionStorage有着一样的API,但是localStorage可以实现数据永久存储,sessionStorage浏览器关闭数据消失。
HTTP状态码指示Web服务器向HTTP客户端返回的响应的状态。以下是常见的HTTP状态码及其含义: 1xx (信息性状态码): - 100 Continue:请求成功,客户端应继续请求。 - 101 Switching Protocols:服务器已经理解了客户端的请求,并将通过协议升级的方式来与客户端进行通信。 2xx (成功状态码): - 200 OK:请求成功。 - 201 Created:请求已被成功处理,并创建了资源。 - 204 No Content:请求成功,但没有返回任何内容。 3xx (重定向状态码): - 301 Moved Permanently:永久性重定向,请求的资源已经永久移动到新地址。 - 302 Found:临时性重定向,请求的资源临时移动到新地址。 - 304 Not Modified:请求资源未修改,可以使用缓存的版本。 4xx (客户端错误状态码): - 400 Bad Request:请求无效,服务器无法理解。 - 401 Unauthorized:请求需要身份验证。 - 403 Forbidden:请求被服务器拒绝。 - 404 Not Found:请求的资源不存在。 - 405 Method Not Allowed:请求方法不允许。 5xx (服务器错误状态码): - 500 Internal Server Error:服务器遇到了意料不到的错误。 - 502 Bad Gateway:服务器作为网关或代理,从上游服务器收到无效响应。 - 503 Service Unavailable:服务器暂时无法处理请求。 - 504 Gateway Timeout:服务器作为网关或代理,但是没有及时从上游服务器收到响应。
跨域的产生原因其实就是三要素不一致,加上浏览器同源策略导致的,如果我可以在前端和接口端之间架设一台之间服务器,保证它和前端三要素一致,和接口端因为是服务对服务不走浏览器 所以不跨域 就可以解决这个问题
答: 1.https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。 2.http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。 3.http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。 4.http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
1. 每个特定的域名下最多生成的cookie个数有限制 2. IE和Opera 会清理近期最少使用的cookie,Firefox会随机清理cookie 3. cookie的最大大约为4096字节,为了兼容性,一般不能超过4095字节 4. 安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。
客户端发送网络包,服务端收到了。 ==》 客户端的发送能力、服务端的接收能力是正常的。 服务端发包,客户端收到了。 ==》 服务端的接收、发送能力,客户端的接收、发送能力是正常的。 客户端发包,服务端收到了。 ==》 客户端的接收、发送能力,服务端的发送、接收能力是正常的。
1、四次挥手 第一次分手:主机1(可以使客户端,也可以是服务器端)向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了。 第二次分手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求。 第三次分手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态。 第四次分手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。 (通俗:主机1告诉主机2,我没有数据要发送了,希望断开连接。主机2接到请求后说,同意断开。主机2告诉主机1可以关闭连接了。主机1接到可以关闭的指令后,关闭连接,四次挥手完成) 三次握手是用于在两台计算机之间建立网络连接。它包括以下三个步骤: 1. 客户端向服务器发送连接请求。 2. 服务器向客户端发送确认消息,表明服务器已准备好接受连接。 3. 客户端向服务器发送确认消息,表明客户端已收到服务器的确认消息,并准备好开始数据传输。 四次挥手是用于在两台计算机之间终止网络连接。它包括以下四个步骤: 1. 客户端向服务器发送断开连接请求。 2. 服务器向客户端发送确认消息,表明服务器已收到断开连接请求。 3. 服务器向客户端发送断开连接请求。 4. 客户端向服务器发送确认消息,表明客户端已收到服务器的断开连接请求。
浏览器的事件循环机制,也称为事件轮询,是指浏览器在执行代码时,将任务分为两类:同步任务和异步任务。同步任务会在主线程上依次执行,形成一个执行栈。而异步任务则会被推入事件队列(Event Queue)中,等待主线程调用栈中的所有同步任务都执行完毕后,再被依次执行。 事件队列中的异步任务分为宏任务和微任务两种类型。宏任务包括setTimeout、setInterval、I/O等,而微任务则包括Promise、MutationObserver等。在主线程中每次执行完一个宏任务后,都会检查微任务队列是否有任务需要执行,如果有则依次执行所有微任务,执行完所有微任务后再执行下一个宏任务,如此循环往复。 这种机制保证了JavaScript代码的执行顺序,同时也能够处理异步任务,使得JavaScript具有并发处理的能力。
正向代理,"它代理的是客户端,代客户端发出请求",是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。 正向代理的用途: 访问原来无法访问的资源,如Google 可以做缓存,加速访问资源 对客户端访问授权,上网进行认证 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息 反向代理,"它代理的是服务端,代服务端接收请求",主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息。 反向代理的作用: 保证内网的安全,通常将反向代理作为公网访问地址,Web服务器是内网 负载均衡,通过反向代理服务器来优化网站的负载
1.使用 localStorage 或 sessionStorage:它们可以在同一浏览器的不同标签页之间共享数据。 2.使用 Broadcast Channel API:它可以在不同的浏览器标签页之间进行通信。 3.使用 Shared Worker:它可以被多个浏览器标签页共享 4.使用 WebSocket:它可以在不同浏览器标签页之间建立持久连接,实现实时通信。
浏览器缓存 浏览器缓存是指浏览器在本地存储一些已经请求过的资源,如图片、CSS、JS等,下次请求同样的资源时可以直接从缓存中获取,从而提高页面加载速度。浏览器缓存机制通常分为两种:强缓存和协商缓存。强缓存是指浏览器在一定时间内直接从缓存中获取资源,不会向服务器发送请求,通常通过设置响应头中的Expires或Cache-Control来实现。而协商缓存是指浏览器需要向服务器发送请求验证资源是否有更新,如果资源未更新则从缓存中获取,否则从服务器重新获取,通常通过设置响应头中的Last-Modified和ETag来实现。 常见的缓存策略包括: 1. 强制缓存:通过设置响应头中的Expires或Cache-Control实现,可以缓存一定时间内不会变化的资源。 2. 协商缓存:通过设置响应头中的Last-Modified和ETag实现,可以缓存可能会变化的资源,并在下次请求时通过If-Modified-Since和If-None-Match头向服务器验证资源是否有更新。 3. 禁止缓存:通过设置响应头中的Cache-Control为no-cache或Pragma为no-cache实现,告诉浏览器不要缓存该资源。
步骤01: 下载并引入echarts.js (图表依赖这个js库) 步骤02: 准备一个具备大小的DOM容器 (生成的图表会放入到这个容器中) 步骤03: 初始化echarts实例对象 ( var myChart = echarts.init(document.getElementById('main')) ; ) 步骤04: 指定配置项和数据(option) (根据具体的需求修改配置选项) 步骤05: 将配置项设置给echarts实例对象 (myChart.setOption(option);)
因为 vue 在更新渲染 dom 的时候是根据新旧 dom 数进行对比的,使用 key 来给每个节点做一个唯一标识,Diff 算法就可以正确的识别此节点,找到正确的位置区插入新的节点 ============================================================ v-for的使用注意事项 绑定key值作用: 提高虚拟DOM的对比复用性能, 更加精准的对数据进行响应式处理 :key="id" 一般都是id值,唯一性 1. 不设置key: 默认同级兄弟元素,按照"下标"进行比较 2. 设置了key: 按照"相同key"的新旧元素比较 为了跟踪到v-for循环出来的每个节点,则需要为v-for所在的节点提供一个唯一的 key 属性。key属性的类型只能为 string 类型或者 number 类型。 ============================================================ 当以数组下标 index 作为 key 值时,其中一个元素 ( 例如: 在增,删,改,查时 ) 发生了变化,这就有可能导致所有的元素的key值发生改变。diff算法在比较同级之间的不同时,会以key来进行关联,当对数组进行下标的变换时,比如删除第一条数据,那么以后所有的index都会发生改变,key 值自然也跟着发生改变,所以index作为key值是不稳定的,而这种不稳定性有可能导致性能的浪费,会导致diff算法无法关联起上一次一样的数据。 因此,能不使用index作为key就不使用index。
v-for比v-if优先级高,所以使用的话,每次v-for都会执行v-if,造成不必要的计算,影响性能,尤其是当之需要渲染很小一部分的时候。 ============================================================ 解决方案: 1. 在循环外部可以在外层嵌套已成template(页面不生成dom节点)、在外层v-if判断、然后在进行使用v-for循环 2. 如果条件出现在循环内部、可以通过计算属性computed提前过滤掉那些不需要展示的数据
MVC 和 MVVM 二者都是设计思想。主要区别是 MVC 中的 C(Controller) 演变成 MVVM 中的 VM(viewModel) ● MVVM 中的数据和视图是双向绑定的 ● MVC中没有双向绑定的概念,需要通过 DOM 操作,来渲染数据和获取数据。 所以,数据操作比较多的场景,需要大量操作 DOM 元素时,采用 MVVM 的开发方式,会更加便捷,让开发者更多的精力放在数据的变化上,避免繁琐的 DOM 操作。
虚拟 dom 本质是js对象,保存Dom的关键信息,相当于在 js 和真实 dom 中间加了一个缓存,利用 dom 的 diff 算法避免了没有必要的 dom 操作,从而提高性能。 #为什么要用虚拟DOM? 因为改变页面样式只能通过操作DOM来实现,但是这种方式会很消耗性能和计算资源,每操作一次DOM就要重构整个dom树,所以就使用虚拟DOM,以对象嵌套的方式来表示 dom 树及其层级结构,那么每次 dom 的更改就变成了对 js 对象的属性的增删改查了,这样一来查找 js 对象的属性变化要比查询 dom 树的性能开销小。 #虚拟dom的优势如下: 简单方便,如果使用手动操作真实dom完成页面,繁琐并容易出错,在大规模应用下维护起来也很困难。 性能方面,使用virtualDom能够有效避免真实dom树的频繁更新,减少重绘和回流提高性能。 跨平台,react借助虚拟dom带来了跨平台的能力,一套代码多端运行。 #缺点:是因为首次渲染大量dom,由于多一层虚拟dom计算,速度比正常稍慢。 VirtualDOM 工作过程有三个简单的步骤: 1、每当底层数据发生改变时,整个 UI 都将在 VirtualDOM 描述中重新渲染 2、然后计算之前 DOM 表示与新表示的之间的差异 3、完成计算后,将只用实际更改的内容更新 realDOM
如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data(类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据) Object是引用数据类型,里面保存的是内存地址,单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
v-show 指令是通过修改元素的 display 的 CSS 属性让其显示或者隐藏 v-if 指令是直接销毁和重建 DOM 达到让元素显示和隐藏的效果
将当前组件的<style>修改为<style scoped> 原理: 为组件实例生成一个唯一标识,给组件中的每个标签对应的dom元素添加一个标签属性,data-v-xxxx 给<style scoped>中的每个选择器的最后一个选择器添加一个属性选择器,原选择器[data-v-xxxx],如:原选择器为.container #id div,则更改后选择器为.container #id div[data-v-xxxx]
1、v-bind: 给标签属性设置vue变量的值 2、v-on:给标签绑定事件 3、v-model:双向数据绑定 4、v-show; v-if 5、v-text和v-html 注意:会覆盖插值表达式;但是{{ }} 不会覆盖内容 6、v-for:数据循环
开发环境下跨域: 1. jsonp: 利用script标签身上的 src属性不受同源策略的影响,需要后端配合处理 callback回调函数 2. cors: 需要后端设置,浏览器通过options方法,发送一个预检请求,获知服务器端是否允许该跨域请求,服务器端确认后方可发起,服务器端也可以告知客户端是否需要身份证认证信息,前端设置响应头即可进行跨域请求. 3. 反向代理: webpack/本地起一个服务器, 服务器与服务器之间不存在跨域问题 前端设置在vue.config.js配置文件中,配置 proxy代理,属性中包含 目标服务器, 通过它代理我们的请求,替我们发送 生产环境下跨域: 1. cors: 后端配置 2. nginx代理 或 node中间件代理 nginx: 配置一个服务器作为 跳板机, 反向代理访问 domain 域名接口,并顺便修改cookie中的domain信息,方便当前域cookie写入,实现跨域请求 node中间件代理: 服务器与服务器之间不存在跨域问题, 配置一个服务器,让它代替我们发送请求
1、采用 ES6 的 import ... from ...语法或 CommonJS 的 require()方法引入组件 2、对组件进行注册:全局注册,局部注册 components: { "组件名": 导入进来的组件对象 3、使用组件<my-component></my-component>
父传子: 在子组件身上绑定传输的值, 子组件通过props进行接收, 其中有type类型, required必填,default默认值 子传父:使⽤$emit通知⽗组件,父组件在子组件身上绑定派发的事件,通过methods中自定义事件处理相应业务 .sync修饰符: ⽗组件传值时使⽤.sync,子组件使⽤update提交修改 1. props 和$emit ⽗组件向⼦组件传递数据是通过 prop 传递的,⼦组件传递数据给⽗组件是通过$emit 触发事件来做到 2. $parent,$children 获取当前组件的⽗组件和当前组件的⼦组件 3. $attrs 和$listeners A->B->C。Vue 2.4 开始提供了$attrs 和$listeners 来解决这个问题 4. ⽗组件中通过 provide 来提供变量,然后在⼦组件中通过 inject 来注⼊变量。(官⽅不推荐在实际 业务中使⽤,但是写组件库时很常⽤) 5. $refs 获取组件实例 6. EventBus 兄弟组件数据传递 这种情况下可以使⽤事件总线的⽅式 创建⼀个中央事件总线EventBus 兄弟组件通过$emit触发⾃定义事件,$emit第⼆个参数为传递的数值 另⼀个兄弟组件通过$on监听⾃定义事件 7. vuex状态管理
babel 用来出来 es6 转 es5 plugin 配置 webpack 的一些插件 loader 用来配置解析处理第三方文件的
11个生命周期函数,其中8个阶段: 创建实例前后, dom挂载前后,更新数据前后, 销毁实例前后 beforeCreate --> 组件实例被创建之初 vue 实例的挂载元素 el 和数据对象 data 都为 undefined,还未初始化,适 用于加loading事件 在加载实例时触发。 created --> 组件实例已经完全创建 vue 实例的数据对象 data 有了,el 还没有, 适用于初始化完成时的事件及 异 步请求。 beforeMount --> 组件挂载之前,dom还未更新 vue 实例的$el 和data都初始化了,但还是挂载之前为虚拟的 dom 节点, data.message 还未替换。 mounted --> 组件挂载到实例上去之后 vue 实例挂载完成,data.message 成功渲染。可用于获取DOM节点 beforeUpdate --> 组件数据发生变化,更新之前 (data变化) updated --> 组件数据更新之后 beforeDestroy --> 组件实例销毁之前 可以做一个确认停止事件的确认框 destroyed --> 组件实例销毁之后 activated --> keep-alive 缓存的组件激活时 deactivated --> keep-alive 缓存的组件停用时调用 errorCaptured --> 捕获一个来自子孙组件的错误时被调用
低耦合。视图(View)可以独立于 Model 变化和修改,一个 ViewModel 可以绑定到不同的"View"上,当 View 变化的时候 Model 可以不变,当 Model 变化的时候View 也可以不变。 可重用性。你可以把一些视图逻辑放在一个 ViewModel 里面,让很多 view 重用这段视图逻辑。 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。 可测试。界面素来是比较难于测试的,而现在测试可以针对 ViewModel 来写。
vue 数据驱动,通过数据来显示视图层而不是节点操作。 jQuery 是一个快速、简洁的 JavaScript 框架 , jQuery 是基于事件驱动
<keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件 实例,keep-alive可以提高组件的性能, 内部包裹的标签不会被销毁和重新创建, 触发激活和非激活的生命周期方法 对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated 提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
webpack: 基于nodejs的静态模块打包工具, 将多个文件打包压缩处理过程 打包的好处: 减少请求次数,减轻服务器压力,加快页面访问速度 @vue/cli 目录和代码分析 node_modules下都是下载的第三方包 public/index.html – 浏览器运行的网页 src/main.js – webpack打包的入口文件 src/App.vue – vue项目入口页面 package.json – 依赖包列表文件 webpack可以做的: 1. 合并压缩: html/css/js图片等资源,进行资源 合并压缩 处理,也就是所谓的打包 2. 语法转换: less/scss/stylus 转换为css es6/es7 转换为 es5/es3 TS转换为 原生js 3. 提供开发服务器: 监测代码变化,实时打包,实时刷新浏览器 webpack属于传统打包方式,必须"优先抓取并构建"整个应用, 实时打包浏览器运行 vite属于直接编译输出,将一部分模块化依赖加载解析功能交由浏览器来工作, 原生ESM方式提供源码,让浏览器接管打包程序的部分工作,实现了情景导入代码,并按需提供源码
1、数据驱动(基于操作 dom 的方式) (1)、Dom 是数据的一种自然映射(双向数据绑定)手动改变 DOM 非常麻烦使用vue.js 之后,只需要改变数据,通过改变 Directives 指令,当数据发生变化,会通过数据指令去修改对应的 DOM (2)、Vue.js 还会对事件进行一定的监听,当我们改变视图(view)的时候通过 DOM Listeners 来改变数据 通过以上两点就实现了数据的双向绑定 2、组件化 Vue-cli:(它是 vue 的脚手架工具) 作用:帮助我们完成基础的代码(包括:目录结构、本地调试、代码部署、热加载、单元测试)
通过插槽可以动态指定某一个组件模板部分的渲染,我们在调用组件的时候,在组件的调用标签中间传递了什么样的标签结构,那么该组件就会把我们传递的标签结构放在他的模板部分进行渲染 1. 组件内用<slot></slot>占位 2. 使用组件时<Pannel></Pannel>夹着的地方, 传入标签替换slot
单项数据流是指数据是单向的,父组件的数据传递给子组件,只能单项绑定,不可以在子组件修改父组件的数据,父子之间的通讯。 双向数据绑定:是指数据和页面进行双向绑定,相互影响
npm 和yarn npm i 包名+ yarn add 包名
含义:@vue/cli是Vue官方提供的一个全局模块包(得到vue命令), 此包用于创建脚手架项目 安装:yarn global add @vue/cli 创建项目:vue create 文件名 入口文件:程序入口文件 main.js 页面入口文件 app.vue
渐进式javacript框架, 一套拥有自己规则的语法 渐进式:逐渐进步, 想用什么就用什么, 不必全都使用
.stop - 阻止事件冒泡 .prevent - 阻止默认行为 .once - 程序运行期间, 只触发一次事件处理函数
.number 以parseFloat转成数字类型 .trim 去除首尾空白字符 .lazy 在change时触发而非inupt时
单选上v-model放在input上,变量名是相同的 多选上vue变量是非数组时,关联的是checked属性,若是数组,关联的是value属性
循环出新的虚拟DOM和旧的结构对比,优先尝试标签复用,就地更新原则
虚拟DOM是一种用JavaScript对象模拟真实DOM的技术,它可以在不实际操作DOM的情况下更新视图,从而提高页面渲染的效率。具体来说,当页面数据发生变化时,虚拟DOM会将数据与旧的虚拟DOM进行比较,然后只更新需要更新的部分,最后再将更新后的虚拟DOM渲染到页面上。虚拟DOM的优点是可以提高页面渲染的效率,因为不需要频繁操作真实DOM;缺点是需要额外消耗一定的内存空间,同时对于一些复杂的操作可能需要手动优化。
动态class :class="{类名:布尔值}" 动态style :style="{css属性名:值,css属性值:值}"
#作用:就是一个函数,传入值返回处理后的值 #定义过滤器 全局过滤器(main.js): Vue.filter('过滤器名字',(值) => {return '返回处理后的值'}) 局部过滤器:filters:{过滤器名:() => return '返回处理后的值'}
# 作用: 函数内部使用的变量改变,重新计算结果返回,计算属性,基于依赖项的值进行缓存,依赖项的值进行缓存,依赖的变量从缓存结果; 若依赖项值发生变化,函数会 “自动” 重新执行,并缓存新的值 computed:{"计算属性名": {get(){return "值"},set(){}}}
作用:可以侦听data/computed属性值的变化 定义:完整写法: watch:{'被侦听的属性名':{immediate:true,deep:true,handler(newVal,oldVal){ }}}
#methods: 数据是非响应式, 必须以函数的方式调用, 每次都会执行函数, 处理业务逻辑功能 #计算属性computed: 1、支持缓存,只有依赖数据发生改变,才会重新进行计算 2、不支持异步,当computed内有异步操作时无效,无法监听数据的变化 3、如果computed需要对数据修改,需要写get和set两个方法,当数据变化时,调用set方法。 4、computed擅长处理的场景:一个数据受多个数据影响,例如购物车计算总价 #侦听属性watch: 1、不支持缓存,数据变,直接会触发相应的操作; 2、watch支持异步;监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值; 3、immediate:组件加载立即触发回调函数执行 4、deep:true的意思就是深入监听,任何修改obj里面任何一个属性都会触发这个监听器里的 handler 方法来处理逻辑 5、watch擅长处理的场景:一个数据影响多个数据,例如搜索框
三部分 template 里面相当于放的html标签 script 里面放的js属性 style 里面放的css样式
1、在子组件上,通过 this.$emit( '自定义事件',值 )触发自定义事件,还可以传参 2、在父组件上,监听自定义事件 @自定义事件 = “事件处理函数”
beforeCreate created beforeMount mounted
nextTick 方法主要是使用了宏任务和微任务(事件循环机制),定义了一个异步方法,多次调用 nextTick 会将方法存入 队列中,通过这个异步方法清空当前队列。 所以这个 nextTick 方法就是异步方法 。 nextTick是将回调函数延迟在下一次dom更新数据后调用,简单的理解是: 当数据更新了,在dom中渲染后,自动执行该函数
作用是切换组件的显示和隐藏 Vue内部提供的组件component组件作用是:实现动态的渲染组件,按需显示组件。 component 标签是 vue 内置的,作用:组件的占位符 is 属性的值,表示要渲染的组件的名字 is 属性的值,应该是组件在 components 节点下的注册名称
slot就是插槽,主要是封装组件的时候,用它来占位。 然后其他组件使用这个封装的组件的时候,给 slot 提供页面结构。 1 默认插槽 在子组件中写入slot,slot所在的位置就是父组件要显示的内容 2 具名插槽 在子组件中定义了多个slot标签,则需要通过name属性来区分这些插槽,加入了name属性的插槽就是具名插槽。 在父组件中使用template并写入对应的slot名字来指定该内容在子组件中现实的位置 3 作用域插槽 在子组件的slot标签上绑定需要的值<slot :data="user"></slot>。 在父组件上使用v-slot:插槽名="user" 或 #插槽名="user" 来接收子组件传过来的值
对普通 DOM 元素进行底层操作 全局注册和局部注册 全局注册:注册一个全局自定义指令 v-focus Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } }) ● el:指令绑定到的元素。这可以用于直接操作 DOM。 ● binding:一个对象,包含多个属性。 #在Vue中,自定义指令的生命周期(也叫钩子函数),有5个事件钩子:1. bind 被绑定, 2. inserted 被插入, 3. update 开始更新, 4. componentUpdated 更新完成,5. unbind 解除绑定。我们可以设置指令在某一个事件发生时的具体行为。 1、bind:只调用一次,指令第一次绑定到元素时调用。和样式相关的操作可以用 bind。 2、inserted:元素插入父节点时调用。和js行为有关的操作,最好用 inserted。 3、update:更新时调用,一般里面的代码逻辑与 bind方法中一致。 4、componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。 5、unbind:只调用一次,指令与元素解绑时调用。 应用场景: 表单防止重复提交 图片懒加载 一键 Copy的功能
声明式导航: 方式一 1、在router-link上的to属性传值 2、语法:to="/path?参数名=值" 3、对应页面组件接收传递过来的值 4、$route.query.参数名 方式二 1、语法:to="/path/值" 2、在main.js中 路由定义 有:的路径代表要接收具体的值 3、在Part.vue准备接收路由上传递的参数和值 $route.params.参数名 4、在router-link上的to属性传值 编程式导航: 语法:this.$router.push({ path: "路由路径", // 都去 router/index.js定义 name: "路由名" })
$route : 一条路由规则,包括 path,params,hash,query,fullPath,matched,name 等当前路由信息参数 $router: 全局的路由实例对象,通过根实例注入router实例,每个组件都可以用到router,整个应用都会用到路由功能,包含history对象,调用其push() go() replace()方法
#含义:vuex 是 vue 框架中状态管理。 #使用:在main.js中引入 store,新建一个目录 store, ... export 有五种,分别是 State、 Getter、Mutation 、Action、 Module vuex 的 State 特性: A、Vuex 就是一个仓库,仓库里面放了很多对象。其中 state 就是数据源存放地,对应于一般 Vue 对象里面的 data B、state 里面存放的数据是响应式的,Vue 组件从 store 中读取数据,若是 store 中的数据发生改变,依赖这个数据的组件也会发生更新 C、它通过 mapState 把全局的 state 和 getters 映射到当前组件的computed 计算属性中 vuex 的 Getter 特性: A、getters 可以对 State 进行计算操作,它就是 Store 的计算属性 B、虽然在组件内也可以做计算属性,但是 getters 可以在多组件之间复 用 C、 如果一个状态只在一个组件内使用,是可以不用 getters vuex 的 Mutation 特性 Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态;Action 可以包含任意异步操作。 vuex 的 Action 特性 包含任意异步操作,通过提交 mutation 间接更变状态vuex 的 Module 特性,异步:ajax请求,定时器,延时器 将 store 分割成模块,每个模块都具有 state、mutation、action、getter、甚至是嵌套子模块
页面刷新会清除vuex中保存的状态,因为vuex的状态是保存在内存中的。所以,页面刷新后,重新加载页面时,vuex状态会被初始化,之前的状态会丢失。 为了解决这个问题,可以使用以下方法: 将vuex状态保存到浏览器本地存储中,例如localStorage或sessionStorage。这样,在页面刷新后,可以从本地存储中恢复vuex状态。 在应用程序初始化时,从服务器端加载数据,并将其保存到vuex状态中。这样,在页面刷新后,可以从服务器端重新加载数据并恢复vuex状态。 使用vuex插件,例如vuex-persistedstate,它可以自动将vuex状态保存到本地存储中,并在页面刷新后自动恢复状态。 总之,页面刷新会影响vuex状态,但可以通过保存状态到本地存储或从服务器端加载数据来解决这个问题。
在vue.js中,懒加载可以帮助减小应用的初始加载大小,并在路由访问时再加载对于的组件。 通过Vue 的异步组件和Webpack的代码分割实现 #步骤 1、将组件定义为异步组件,被访问时才加载,使用Vue的component属性提供一个工厂函数来实现这一点 const SomeComponent = () => ({ // 这个组件会在被访问时异步加载 component: import('./some-component.vue'), loading: SomeLoadingComponent, error: SomeErrorComponent, delay: 200, timeout: 3000 }) 2、路由中配置异步组件 const router = new VueRouter({ routes: [ { path: '/some-route', component: SomeComponent } ] }) #访问 /some-route 时,组件 some-component.vue 就会被异步加载,而不是在应用初始加载时一并加载。 #注意,上面的例子假设你已经使用了 Webpack 和 vue-loader,并且在 Webpack 配置中启用了代码分割功能。这样,Webpack 就会将组件分割成独立的包,并在被访问时动态加载。
三种 全局导航钩子 router.beforeEach(to, from, next)router.beforeResolve(to, from, next)router.afterEach(to, from ,next) router.beforeResolve:全局解析守卫,在beforeRouteEnter调用之后调用 router.afterEach:全局后置钩子,进入路由之后 组件内钩子 beforeRouteEnter,beforeRouteUpdate. beforeRouteLeave 单独路由独享组件 beforeEnter 路由组件内的守卫 beforeRouteEnter():进入路由前 beforeRouteUpdate():路由复用同一个组件时 beforeRouteLeave():离开当前路由时
Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分: 加载渲染过程 父 beforeCreate -> 父 created -> 父 beforeMlount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父mounted 子组件更新过程 线 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 公 updated 父组件更新过程 父 beforeUpdate -> 父 updated 销毁过程 父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 少 destroyed
答: ref="domName"用法: this.$refs.domName
列表中使用唯一 key 变量本地化:把会多次引用的变量保存起来,每次访问this.xxx,因为是响应式对象,都会触发getter收集相关代码,导致性能越来越差 第三方插件 按需导入 路由懒加载 keep-alive缓存页面 事件的销毁 图片懒加载
路由懒加载,会将原来打包一个 app.js 的文件打包成多个文件 异步组件,按需加载 组件异步加载,将子组件 webpack 开启 gzip 压缩 如果图片过多,开启图片懒加载 使用 cdn 资源 如果首页是登录页,做多入口
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用 window.location.hash 读取。特点: hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。 history模式: history采用HTML5的新特性;且提供了两个新方法: pushState),replaceState)可以对浏览器历史记录栈进行修改,以及popstate事件的监听到状态变更
vue-router 默认使用hash 模式,所以在路由加载的时候,项目中的 URL 会自带“#”。如果不想使用“#”,可以使用 vue-router 的另种模式 history: new Router ( mode : history', routes:[ ]}) 需要注意的是,当我们启用 histov 模式的时候,由于我们的项目是一个单页面应用,所以在路由跳转的时候,就会出现访问不到静态资源而出现“404”的情况,这时候就需要服务端增加一个看盖所有情况的候选资源:如果 URL匹配不到任何静态资源,则应该返回同人“index.htm”页面。
vue是组件级更新,当前组件里的数据变了,它就会去更新这个组件。 当数据更改一次组件就要重新渲染一次,性能不高,为了防止数据一更新就更新组件,所以做了个异步更新渲染。(核心的方法就是nextTick)
一、vue作为一款轻量级框架,门槛低,上手快,简单易学。 二、vue可以进行组件化开发,数据与结构相分离,使代码量减少,从而提升开发效率,易于理解 三、vue最突出的优势在于对数据进行双向绑定,使用虚拟DOM 四、相较于传统页面通过超链接实现页面跳转,vue会使用路由跳转不会刷新页面 五、vue是单页面应用,页面局部刷新,不用每次跳转都请求数据,加快了访问速度,提升了用户体验
目的: 为了系统的安全性,只有登录过有token且没有过期才能认为是身份认证通过的 前置路由守卫: router.beforeEach: 页面组件在进入浏览器渲染视图之前,进行的守卫检查 参数1: to 要去哪 参数2: from 来自哪 参数3: next 无论结果如何都要放行 路由后置守卫 afterEach --> 处理页面组件进入后相关操作 --> 关闭进度条 分两种情况: 有token 1. 去登录页 -> 跳转至首页 2. 继续访问其他页面 -> 随意访问 无token 1. 访问白名单 -> 随意访问 2. 除去login页面 访问其他页面 -> 重定向至登录页
可以 <el-input v-model="value" v-on="{ input:onInput, focus:onFocus, blur:onBlur }" > </el-input> methods:{ onInput(value){ console.log('onInput',this.value) }, onFocus(value){ console.log('onFocus',this.value) }, onBlur(value){ console.log('onBlur',this.value) }, }
其目的就是改变第三方组件库的样式,但是又不想去除scoped属性造成组件之间的样式污染。 用了样式穿透后,在deep之后的选择器最后就不会加上标识。 Vue 提供了样式穿透:deep() 他的作用就是用来改变 属性选择器的位置
1、v-model主要提供了两个功能,view层输入值影响data的属性值,属性值发生改变会更新层的数值变化. 2、v-model指令的实现: 2.1 v-bind:绑定响应式数据 2.2 触发input事件并传递数据 (核心和重点) 3、其底层原理就是(双向数据绑定原理): 3.1 一方面modal层通过defineProperty来劫持每个属性,一旦监听到变化通过相关的页面元素更新。 3.2 另一方面通过编译模板文件,为控件的v-model绑定input事件,从而页面输入能实时更新相关data属性值。
环境一般分为开发环境,测试环境,生产环境 因为每个环境的接口域名.webpack 配置都是不同的,所以在打包构建时,我们需要区分这些环境,这时就用到了环境变量 。在开发环境和生产环境可能会有不用的环境 通过在.env.development(开发时的用到的) 和 .env.production(生产时用到的)文件中 设置环境变量来解决,就比较方便 便于维护 可以设置若干个 环境变量 方便 使用 通过 process.env.VUE_APP_ (自定义) 来拿到环境变量
1. 写法不同 query的语法用于path编写传参地址 params的语法用于name编写传参地址 2. 接收方式不同 query接受参数的时候用 this.$route.query.name params接受参数的时候用 this.$route.params.name 3. query在刷新页面的时候参数不会消失 但params在刷新页面的时候参数会消失 可以考虑本地存储解决此问题 4.query传过来的参数会显示到地址栏中 而params传过来的参数不会显示到地址栏中 直白的来说 query相当于get请求,而params相当于post请求
// mixins 文件中 可以写跟组件一模一样的选项 // 规则: // 1.如果mixins和组件中 都有相同的生命周期钩子 会进行合并,mixins中的生命周期钩子先执行,组件内的后执行 // 2.mixins中可以使用组件中的任何数据 组件也可以使用mixins中的任何数据 // 3.对象类型的配置(包含data) 如果组件和mixins中有同名的话 ,会覆盖,以组件为准 // 使用场景:多个组件 都有同一套逻辑的时候 并且这套逻辑中的代码散落到 data、computed、methods....这时候可以使用mixins // 使用mixins的步骤 // 1.声明一个mixins的js文件 // 2.在组件中混入mixins文件
diff算法是一种通过同层的树节点进行比较的高效算法 其有两个特点: 比较只会在同层级进行, 不会跨层级比较 在diff比较的过程中,循环从两边向中间比较 diff 算法的在很多场景下都有应用,在 vue 中,作用于虚拟 dom 渲染成真实 dom 的新旧 VNode 节点比较
watch:vue中,使用watch来响应数据的变化。并调用因为变化需要执行的方法。可以通过watch动态改变关联的状态 深度侦听:当需要监听复杂数据类型(对象)的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听 立即侦听:当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。
路由传参方式有四种:URL参数传递、路径参数传递、查询参数传递和state参数传递。 1. URL参数传递是通过在URL中添加参数来传递数据,可以通过`this.$route.query`来获取参数值。 2. 路径参数传递是通过在URL路径中添加参数来传递数据,可以通过`this.$route.params`来获取参数值。 3. 查询参数传递是通过在URL中添加查询参数来传递数据,可以通过`this.$route.query`来获取参数值。 4. state参数传递是通过在跳转页面时使用`router.push`方法的`state`参数来传递数据,可以通过`this.$route.state`来获取参数值。 6. 在传递敏感数据时,路径参数传递和state参数传递是相对安全的,而URL参数传递和查询参数传递会将数据暴露在URL中,不太安全。 7. 不同的传递方式适用于不同的场景,需要根据实际情况选择合适的传递方式。
构建vue-cli工程的过程中,涉及到了以下技术: 1. Node.js:vue-cli是基于Node.js开发的,需要安装Node.js环境。 2. npm:Node.js的包管理器,用于安装各种依赖包。 3. webpack:模块打包工具,用于将各种模块打包成静态资源文件。 4. babel:JavaScript的编译器,用于将ES6及以上的语法转换为ES5语法,以便在不支持ES6的浏览器上运行。 5. Vue.js:基于MVVM模式的前端框架,用于构建vue-cli工程。 6. ESLint:代码风格检查工具,可以规范代码风格,提高代码质量。 7. PostCSS:CSS后处理器,可以使用各种插件来处理CSS,如自动添加前缀、压缩等。 这些技术在构建vue-cli工程中扮演着不同的角色,主要作用如下: 1. Node.js和npm用于管理依赖包,方便工程的开发和构建。 2. webpack用于将各种模块打包成静态资源文件,提供了多种功能,如代码分割、代码压缩、热更新等。 3. babel用于将ES6及以上的语法转换为ES5语法,以便在不支持ES6的浏览器上运行。 4. Vue.js是一个前端框架,提供了各种组件和API,方便快速构建前端应用程序。 5. ESLint可以规范代码风格,提高代码质量。 6. PostCSS可以处理CSS,提高CSS的可维护性和可读性。 总之,这些技术在vue-cli工程的构建中相互配合,提供了一个高效、可靠、可维护的开发环
1.props不能被其所在的组件修改,从父组件传递进来的属性不会在组件内部更改;props意为属性,只可父组件改变子组件的props,而子组件不能自更新,props是子组件暴露给外部的公有接口 2.state只能在所在组件内部更改,或在外部调用setState函数对状态进行间接修改。 3.在组件状态上移的场景中,父组件正是通过子组件的Props, 传递给子组件其所需要的状态。 4.props主要是用于组件之间传递参数,获取组件的属性值。 组件之间数据单向流动 ,从父组件流向子组件。 5.state主要用于组件更新控制,如果想重新渲染或更新组件,只需要修改state即可,然后根据具体修改的state, 6.props和state是经常要结合使用的,父组件的state可以转化为props来为子组件进行传值。在这种情况下,子组件接收的props是只读的,想要改变值,只能通过父组件的state对其进行更改。
Vue的双向绑定是通过响应式原理实现的。 当一个Vue实例被创建时,Vue会遍历对象的每个属性,使用Object.defineProperty()方法将属性转换为getter/setter,并在内部维护一个依赖列表。当数据改变时,Vue会自动重新计算依赖列表,并通知所有相关的组件进行更新。 具体来说,Vue会将数据对象的每个属性都转换为getter/setter,这样当属性被访问或修改时,Vue会自动触发相应的getter/setter方法。在getter方法中,Vue会收集依赖并将当前组件添加到依赖列表中。在setter方法中,Vue会通知依赖列表中的所有组件进行更新。 这种响应式原理使得Vue可以实现双向绑定,即当数据改变时,相关的组件会自动更新,而当组件中的数据发生改变时,数据对象也会自动更新。这种自动化的双向绑定使得开发者可以更加专注于业务逻辑的实现,而不必手动处理DOM操作和数据同步的问题。
Vue中的ref和document.querySelector()都可以用来获取DOM元素,但两者有以下区别: 1. ref是Vue提供的一种特殊的属性,可以在模板中对DOM元素进行标记,并在Vue实例中通过this.$refs来访问这些元素。而document.querySelector()是原生JS提供的方法,需要手动编写JS代码来获取DOM元素。 2. ref可以在Vue实例中直接访问DOM元素,而document.querySelector()需要通过DOM API来访问元素。 3. ref只能用于访问当前Vue实例中的DOM元素,而document.querySelector()可以用于访问整个文档中的DOM元素。 4. ref可以用于访问组件中的DOM元素,而document.querySelector()只能用于访问普通的HTML元素。 总的来说,ref是Vue提供的一种方便的方式来获取DOM元素,而document.querySelector()是原生JS提供的一种通用的方法,可以用于访问整个文档中的DOM元素。在Vue中,我们通常优先使用ref来获取DOM元素,因为它更加方便和直观。
实质区别:vuex存储的是状态,存储在内存中;localStorage是浏览器提供的接口,存的是接口,以文件形式存储到本地 应用场景:vuex用于组件中的传值,localStorage主要用于页面之间的传值。 永久性:刷新页面,vuex存储的值会丢失,localStorage不会。 ============================================================================================================================= 总结:为什么有了localStorage还需要用vuex 对于不变的数据,localStorage可以代替vuex,==> (响应式原理) 但是如果俩个组件中的数据源发生改变,希望另一个组件也响应变化,这时候就得需要xuex。vuex是vue的状态管理机制,方便组件之间通信。一组数据变化会映射到使用这个数据的其他组件。而localStorage是本地存储,是将存储到浏览器的方法,一般在跨页面的时候使用。 注意:localStorage保存对象的时候,需要将对象转化成json字符串,然后获取的时候转化为对象形式。
#含义:loader 用于对模块的"源代码"进行转换,在 import 或"加载"模块时预处理文件 #常见loader: style-loader: 将css添加到DOM的内联样式标签style里 css-loader :允许将css文件通过require的方式引入,并返回css代码 less-loader: 处理less sass-loader: 处理sass postcss-loader: 用postcss来处理CSS autoprefixer-loader: 处理CSS3属性前缀,已被弃用,建议直接使用postcss file-loader: 分发文件到output目录并返回相对路径 url-loader: 和file-loader类似,但是当文件小于设定的limit时可以返回一个Data Url html-minify-loader: 压缩HTML babel-loader :用babel来转换ES6文件到ES5 可以通过 loader 的预处理函数,为 JavaScript 生态系统提供更多能力。用户现在可以更加灵活地引入细粒度逻辑,例如:压缩、打包、语言翻译和更多其他特性
$set是Vue.js提供的一个方法,用于在响应式对象上设置一个新的属性或修改已有属性的值。它可以确保Vue.js能够正确地检测到对象属性的变化,从而实现响应式更新。
$set 是 vue2 中对象用来追加响应式数据的方法 ; 使用格式 : $set(对象 , 属性名 , 值 ) vue3中使用 proxy 替代了 Object.defineProperty 实现对象的响应式数据 ,所以在 vue3 中直接添加对象属性就是响应式的数据 ,用不上 $set 方法 ;
【必答】 webpack会先打包,然后启动开发服务器,请求服务器时直接给予打包结果,当项目文件大的时候会出现打包时间长的问题启动服务器缓慢的问题;vite是直接启动开发服务器,请求哪个模块再对该模块进行实时编译,所以启动速度快,感受好,启动服务器时的优势相对明显 【必答】在热更新方面,当改动了一个模块后,仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高。 【选答】当需要打包到生产环境时,vite使用传统的rollup进行打包,因此,vite的主要优势在开发阶段。另外,由于vite利用的是ES Module,因此在代码中不可以使用CommonJS
答题技巧:以下4部分内容,挑选出你能够hold得住的去回答即可
vscode插件和调试工具方面
代码高亮,语法提示方面:vue2项目主要用Vetur插件,vue3中主要用Volar
语法片段方面:在vue2中我们一直使用Vue 2 Snippets,在vue3我们推荐使用Vue 3 Snippets,因为它支持vue3的同时完全向前兼容vue2
在浏览器调试工具方面:vue2版本的chrome devtools不再支持vue3,vue3我们需要单独下载Vue.js devtools beta
兼容性方面:
vue2 不支持 IE8 及以下版本,因为 Vue2 使用了 IE8 无法模拟的 ECMAScript 5 特性,例如:Object.defineProperty()
vue3 不支持 IE11 及以下版本。
语法层面
在vue2中,我们只要定义在data()方法中的数据就是响应式数据,在vue3中我们可以使用ref和reactive定义的响应式数据
组合式api:为了让相关代码更紧凑vue3提出了组合式api,组合式api能将同一个逻辑关注点相关代码收集在一起。 组合式api的入口就是setup方法。
在 vue2 中template不支持多根节点组件,vue3支持了多根节点的组件
底层实现方面
vue2的响应式使用的是Object.defineProperty()实现的,Vue3使用的Proxy实现的
参考:对比Vue2总结Vue3新特性(2022年最全,2.5w字!) - 掘金
Vue3中的`setup()`函数是一个新的组件选项,用于设置组件的响应式数据、计算属性、方法和监听器等功能。它是Vue3中替代了Vue2中的`data()`,`computed`,`methods`和`watch`等选项的一个统一入口。 `setup()`函数会在组件实例化之前执行,它接收两个参数:props和context。其中props包含了传递给组件的属性,而context包含了组件的一些上下文信息,例如attrs(非prop特性)、emit(事件派发)等。 在`setup()`函数中,可以通过调用Vue3提供的一些API来定义响应式数据、计算属性、方法、监听器等,或者通过普通的JavaScript代码直接定义变量。这些定义的值可以在模板中直接使用,并且会自动进行响应式更新。 总的来说,`setup()`函数是Vue3中编写组件逻辑的主要入口,能够更加灵活地处理组件的状态和行为,并且可以更好地与TypeScript等类型检查工具结合使用。
含义:TypeScript 是 JavaScript 的类型的超集,支持ES6语法,支持面向对象编程的概念,如类、接口、继承、泛型等 区别: TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法 TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译 TypeScript 文件的后缀名 .ts (.ts,.tsx,.dts),JavaScript 文件是 .js 在编写 TypeScript 的文件的时候就会自动编译成 js 文件
vue3中 v-model 通过 :modelValue 传递数据 通过 @update:modelValue 绑定方法 Vue3使用了Proxy对象来实现双向绑定。当数据发生变化时,Proxy会自动触发set方法,从而通知Vue进行响应式更新。同时,Vue3还引入了新的API,如setup函数和ref函数,使得开发者可以更方便地管理组件状态和数据。总之,Vue3的双向绑定机制更加高效和灵活,可以提高开发效率和代码质量。
Vuex和Pinia都是vue.js的状态管理工具,Vuex是vue2使用,而在vue3推荐了Pinia,主要有以下几点区别:
Pinia没有mutation,他只有state,getters,action【同步、异步】使用它来修改state数据
Pinia语法上比vuex更容易理解和使用,灵活。
Pinia没有modules配置,每一个独立的仓库都是definStore生成出来的、
Pinia的state是一个在函数中返回的对象,和vue组件中的data编写方式差不多
vuex的不足 : Pinia和Vuex都是非常好用的数据管理工具,在某些情况下,使用Pinia的web应用程序会比使用Vuex更快,这种性能的提升可以归因于Pinia的极轻的重量,Pinia体积约1KB。
微信小程序是一种新型的应用程序,它的原理主要包括以下几个方面: 1. 基于Web技术:微信小程序采用了Web技术,包括HTML、CSS和JavaScript,开发者可以使用这些技术来构建小程序的界面和逻辑。 2. 基于微信平台:微信小程序是基于微信平台开发的,开发者需要使用微信提供的开发工具来开发和调试小程序。 3. 框架与运行环境:微信小程序提供了一个基于MVVM模式的框架,包括视图层、逻辑层和数据层,同时提供了一个运行环境,可以在微信中直接运行。 4. 运行机制:微信小程序采用了一种类似于Web的运行机制,即在小程序启动时,会下载代码包和配置文件,然后在本地解析和运行,最终呈现出小程序的界面和功能。 5. 安全性:微信小程序具有较高的安全性,它采用了一些安全机制,如代码加密、沙箱机制、数据隔离等,保证小程序的安全性和稳定性。 总之,微信小程序是一种基于Web技术、基于微信平台、具有较高安全性的新型应用程序,它提供了一种快速开发和便捷使用的方式,可以满足用户的多种需求。
答:小程序的主要语言是JavaScript,框架为微信开发团队开发的小程序框架,其内部采用了MVVM架构,具有高效、易用、灵活等特点。小程序具有开发周期短、内容丰富、流量消耗少、实时性高、操作性强等优势。
答:小程序的生命周期包括App、Page、Component等,每个生命周期在小程序运行过程中都有不同的作用和触发时机。小程序的更新机制主要包括自动更新和手动更新两种方式,自动更新主要是针对小程序代码的更新,而手动更新是针对小程序的各类资源更新。
答:小程序中用户数据存储和管理方案主要有本地缓存、全局数据和云服务三种形式。小程序通过本地缓存来存储一些小程序的临时数据,通过全局数据来管理小程序中的共享数据,通过云服务来为小程序提供数据存储和管理服务。
答:小程序中常用的API和组件包括视图组件、表单组件、媒体组件、网络请求API、系统API等,可以通过小程序框架提供的API调用方式来使用。
答:小程序中可以通过不同的方式来实现数据传递和页面通信,包括事件机制、全局变量、路由传参、全局数据管理等方式。
1. 调用后端接口生成订单编号(请求头携带 token,需要传递收货地址、需要传递购物车中的信息 [{ goodsId, goodsPrice, goodsCount }])。 2. 预支付(根据订单编号调用接口拿到支付相关的参数)。 3. 根据上面获取到的支付参数,调用 wx.requestPayment 发起微信支付。 4. 再次根据订单编号调用接口查询支付状态,根据支付状态做相关的操作。 5. 如果支付成功,跳转到支付页面(包含了支付方式、金额、状态...)。 具体的做法: 打开某小程序,点击直接下单 wx.login获取用户临时登录凭证code,发送到后端服务器换取openId 在下单时,小程序需要将购买的商品Id,商品数量,以及用户的openId传送到服务器 服务器在接收到商品Id、商品数量、openId后,生成服务期订单数据,同时经过一定的签名算法,向微信支付发送请求,获取预付单信息(prepay_id),同时将获取的数据再次进行相应规则的签名,向小程序端响应必要的信息 小程序端在获取对应的参数后,调用wx.requestPayment()发起微信支付,唤醒支付工作台,进行支付 接下来的一些列操作都是由用户来操作的包括了微信支付密码,指纹等验证,确认支付之后执行鉴权调起支付 鉴权调起支付:在微信后台进行鉴权,微信后台直接返回给前端支付的结果,前端收到返回数据后对支付结果进行展示 推送支付结果:微信后台在给前端返回支付的结果后,也会向后台也返回一个支付结果,后台通过这个支付结果来更新订单的状态 其中后端响应数据必要的信息则是wx.requestPayment方法所需要的参数
方法一、使用APP定义全局变量 1、在app.js中的APP({})传入对象中定义一个全局属性globalData,作为保存全局变量的对象。 2、声明变量进行引入。 3、进行全局变量的赋值。 4、在page页面引入app,同时声明变量,获得所需要的全局变量。 方法二、用引入的JS的方法定义全局变量 方法三、使用全局状态管理库 方法四、引入redux组件
优点: 1. 无需下载 2. 打开速度快 3. 开发成本低 4. 为用户提供良好的安全保障。发布有一套严格的审查流程,不能通过审查的程序无法发布上线 5. 服务请求快 缺点: 1. 依托微信,不能开发后台管理功能 2. 大小限制不能超过 2M,不能打开超过 5 个层级的页面
1. 先创建一个 components 文件夹,用来存放所有自定义组件的,目录结构依然是 js,wxml,json,wxss 2. 在 components 目录中新建 authorization 目录,然后在右键在菜单中找到【新建 Component】,输入组件名称后会自动创建组件。 3. 注册组件(页面注册和全局注册) 4. 使用组件: 在 index.wxml 中引用,在 index.js 进行配置
百度的,也可以参照老师的文档自己讲讲
小程序的位置获取可以通过微信小程序提供的API进行实现。以下是获取位置的步骤: 1. 在小程序中引入wx.getLocation() API。 2. 调用wx.getLocation() API获取用户的地理位置信息。 3. 处理用户地理位置信息的回调函数。
1、模板语法不同:小程序用的时Mustache模板语法,Vue使用的时 HTML 的模板语法 2、数据流向不同:在小程序中,视图层和逻辑层是分开的,数据的流动是通过 setData 方法实现的; Vue中,数据的更新是同步的,直接修改数据即可 3、数据更新时机不同:在小程序中,数据的更新是异步的,通过setData方法更新; 在Vue中,数据的更新是同步的,双向绑定 4、数据绑定方式不同:在小程序中,数据绑定通过在标签中使用{{}}实现; 在Vue中,数据绑定通过在标签中使用v-bind或{{}}实现
1.wx.navigateTo:保留当前页面,跳转到应用内的某个页面,使用 wx.navigateBack 可以返回到原页面。这种方式会保留原页面的状态,但是最多只能同时保留 5 个页面。 2.wx.redirectTo:关闭当前页面,跳转到应用内的某个页面,不可返回。这种方式会销毁原页面,无法返回原页面。 3.wx.switchTab:跳转到应用内的某个 tab 页面,只能跳转到 tab 页面,无法跳转到其他非 tab 页面。 4.wx.reLaunch:关闭所有页面,打开应用内的某个页面。这种方式会销毁所有页面,打开新的页面。 5.wx.navigateBack:关闭当前页面,返回上一页面或多级页面
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。