1.用css编写一个宽高浏览器一半的正方形
答:设置视口width(宽度)为50vw 高度为50vw
vw
表示视口宽度的 1/100。例如,100vw
表示占据整个视口的宽度。
vh
表示视口高度的 1/100。例如,100vh
表示占据整个视口的高度。
.half-square {
width: 50vw;
height: 50vw;
/* padding-bottom: 50vh; */
background-color: blue;
}
2.说说MVC的认识
答:MVC 是一种软件设计模式,即M模型(Model) - V视图(View) - C控制器(Controller)。
模型(Model):用于负责处理数据和业务逻辑,跟数据库进行交互处理数据的储存,检索,更新和验证
视图(View):主要负责数据的展示,把模型中的数据以用户可见的形式展示出来,比如网页、界面等。视图通常只关注数据的展示形式,不包含业务逻辑。
控制器(Controller):控制器用于接收请求,校验参数,调用 Model 层获取业务数据,构造和绑定上下文,并转给 View 层去渲染
3.说说MVVM框架
-
M:模型(Model) :对应 data 中的数据
-
V:视图(View) :模板
-
VM:视图模型(ViewModel) : Vue 实例对象
-
模型(Model):代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。数据保存—存放着各种数据,有的是固定写死的,大多数是从后端返回的数据
视图 (View):代表UI 组件,它负责将数据模型转化成UI 展现出来,用户界面,也就是DOM -
视图模型(View-Model):监听数据模型的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和Model的对象,连接Model和View。
4.MVVM和MVC的区别?
都是一种设计思想
MVC后台用的多,MVC是Model-view-Controller的简写,即模型-视图-控制器。
MVC的目的就是将M和V的代码分离
MVC是单向通信,也就是View和Model,必须通过controller来承上启下。
MVVM实现了View和Model的自动同步,当Model的属性改变时,不用再自己手动操作DOM元素,提高了页面渲染性能。
5.input和change的区别
input和change都是JavaScript中用于处理表单元素事件的关键词,它们的区别在于:
input:这个事件触发于用户改变输入字段的内容,无论该变化是由键入、剪切板粘贴还是通过其他方式引起的。它会在内容发生变化时立即触发,通常用于实时获取用户的输入值。
change:相比之下,change事件更为谨慎,它只在用户完成输入并离开相关的表单元素(如文本框、下拉列表等)时才会触发。也就是说,只有当用户点击了“确定”按钮或者失去了对焦点(例如按下Enter键),change事件才会被激活。
6.说说闭包的理解
闭包是一个函数加上到创建函数的作用域的连接,闭包“关闭”了函数的自由变量
自由变量(在函数内部引用了一个不在该函数作用域内定义的变量)
2. 闭包可以解决什么问题【闭包的优点】
2.1 内部函数可以访问到外部函数的局部变量
2.2 闭包可以解决的问题
var lis = document.getElementsByTagName('li');
for(var i=0;i<lis.length;i++){
(function(i){
lis[i].onclick = function(){
alert(i);
}
})(i)
}
3. 闭包的缺点
3.1 变量会驻留在内存中,造成内存损耗问题。
解决:把闭包的函数设置为null
3.2 内存泄漏【ie】 ==> 可说可不说,如果说一定要提到ie
7.vue2组件中数据更新视图没有更新如何解决?
方案1:静默刷新(使用v-if的特性)
在修改值之后将元素销毁,然后在修改后的下一次DOM渲染完成时再显示出来,这样就会触发组件重新加载data的数据进行渲染,data中被修改的数据才是最新的。
change(){
this.info = {b:99}
this.show = false
this.$nextTick(()=>{
this.show = true
})
}
方案2:Vue.$set(官方推荐)
使用这个api修改的数据会为其添加响应式getter和setter让其拥有数据响应的特性,vm.$set(要操作的对象或数组, 要新增或者修改的数组或对象key, 对应的值)
方案3:可以使用 this.$forceUpdate 方法强制更新视图(影响性能)
updateName(){
this.userInfo.name='小红'//在此时,确实已经将userInfo对象修改完成
console.log(this.userInfo.name);//输出结果: 小红
this.$forceUpdate();//在这里,强制刷新之后,页面的结果变为'小红'
}
方案4:使用变异方法:对于数组的操作,尽量使用 Vue 能够监测到的变异方法,如 push、pop、shift、unshift、splice、sort、reverse 等。如果需要使用其他方法,可以考虑使用新数组替换原数组。
8.输入url地址栏都做了什么?
-
浏览器获取您输入的网址
- 浏览器会检测输入的内容是否符合有效的 URL 格式。
-
进行域名解析
- 如果输入的是域名(例如:www.example.com),浏览器会向 DNS(域名系统)服务器发送请求,以获取该域名对应的 IP 地址。
-
建立 TCP 连接
- 使用获取到的 IP 地址,浏览器尝试与服务器建立 TCP(传输控制协议)连接。
-
发送 HTTP 请求
- 连接建立成功后,浏览器会向服务器发送 HTTP(超文本传输协议)请求,请求中包含了您想要访问的具体页面路径、请求方法(如 GET、POST 等)、以及一些头部信息(如浏览器类型、语言偏好等)。
-
服务器处理请求
- 服务器接收到请求后,根据请求的内容进行处理,例如从数据库中获取数据、执行相应的脚本等。
-
服务器响应
- 服务器处理完请求后,会向浏览器发送 HTTP 响应,响应包含了状态码(如 200 表示成功、404 表示未找到等)、响应头(如内容类型、长度等)以及响应体(即您请求的网页内容)。
-
浏览器解析和渲染页面
- 浏览器接收到响应后,会根据响应的内容进行解析。如果是 HTML 页面,会构建 DOM 树、计算样式、进行布局和绘制,最终将页面呈现给用户。
-
加载资源
- 在解析 HTML 页面的过程中,如果遇到需要加载的其他资源(如 CSS 文件、JavaScript 文件、图片等),浏览器会再次发起请求获取这些资源,并进行相应的处理和渲染。
9.vue2对比vue3都做了哪些优化
- 响应式系统:Vue3 使用 Proxy 替代 Object.defineProperty 来实现响应式,Proxy 可以直接监听对象的属性变化,并且支持对数组、Set、Map 等数据结构的监听,还可以监听到新增和删除属性。而在 Vue2 中,需要使用 Vue.set 或 $set 来实现对新增属性的监听。
- 编译优化:
- 静态提升:Vue3 在编译阶段会将一些静态的节点或属性提升到渲染函数之外,避免了在每次渲染时都重新创建这些节点或属性,从而提高了渲染性能。在 Vue2 中,无论节点是否参与更新,都会重新创建再渲染。
- PatchFlag:Vue3 在编译阶段会为动态节点添加 PatchFlag,在 diff 算法中,只会比较有 PatchFlag 的节点,从而减少了不必要的比较操作,提高了 diff 算法的效率。而 Vue2 是进行全量的对比,在运行时会对所有节点生成一个虚拟节点树,当页面数据发生变化时,会遍历判断 virtual dom 所有节点(包括一些不会变化的节点)有没有发生变化。
- 静态属性提升:Vue3 还对组件选项进行了优化,将静态属性提升到渲染函数外部,避免了每次渲染都重新创建这些属性的开销。
- 代码结构:Vue3 采用了组合式 API(Composition API),将组件的逻辑拆分成多个函数,使得代码更加清晰和易于维护。而 Vue2 则是Options API,将组件的逻辑写在一个对象中,代码结构相对较为混乱。
- 类型支持:Vue3 基于 TypeScript 进行重构,提供了更好的类型推导和类型检查,使得代码更加健壮和易于维护。而 Vue2 则是基于 JavaScript 的,类型检查相对较弱。
- 体积优化:Vue3 对核心库进行了重构,删除了一些不常用的功能,使得整个库的体积更小。同时,Vue3 还支持 Tree-Shaking,可以将没有使用到的模块进行摇树优化,进一步减小了代码体积。
- 性能优化:
- 事件侦听器缓存:Vue3 使用了更高效的事件处理机制,将事件处理函数缓存起来,避免了每次渲染都重新创建事件处理函数的开销。
- 数据追踪的改进:Vue3 对数据追踪机制进行了改进,使得只有被依赖的数据发生变化时,相关的更新才会被触发,减少了不必要的更新操作。
- 组件级别的异步更新:Vue3 允许在组件级别设置异步更新,只对需要更新的组件进行渲染,避免了全局更新的开销。
- 列表渲染的优化:Vue3 为列表渲染引入了新的动态更新策略,只会对发生变化的列表项进行更新,而不是重新渲染整个列表。
10.链式调用的理解
链式调用是一种编程中的方法调用风格,通过在一个方法调用的返回值上紧接着调用另一个方法,形成一个连续的调用链
优点:
- 提高代码的可读性和简洁性,使得一系列相关的操作可以以一种连贯和直观的方式表达。
- 减少中间变量的使用,避免了为每个中间结果创建新的变量,从而使代码更加紧凑。
- 例如,在 JavaScript 中,如果一个对象的方法返回
this
(即对象本身),就可以实现链式调用。
class MyClass {
value = 0;
increment() {
this.value++;
return this;
}
multiplyBy(n) {
this.value *= n;
return this;
}
}
const obj = new MyClass();
// 链式调用
obj.increment().multiplyBy(2);
console.log(obj.value);
//在上述示例中,increment 和 multiplyBy 方法返回了对象本身,从而支持了链式调用。
11.链式调用的题型
//根据data中的数据根据 groupld字段分组输出,过滤null 和没有分组的id数据
var data = [{groupld: "new",userld:2}, null, null, {groupld: "top",userld:2}, {userld:'2'}, {groupld:"new", userld:2}, {groupld: "new", userld:5}]
let obj = data.filter(item=> item && item.userld && item.groupld).reduce((pre,cur)=>{
if(!pre[cur.groupld]){
pre[cur.groupld] = []
}
pre[cur.groupld].push(cur)
return pre
},{})
console.log(obj);
var obj2 = Object.keys(obj).reduce((pre,cur)=>{
// console.log(obj[cur],'----');
if(!pre[cur]){
pre[cur] = []
// console.log( pre[cur],'----');
}
console.log(obj[cur],'----');
obj[cur].map(e => {
if(!pre[cur].includes(e.userld)){
pre[cur].push(e.userld)
}
})
return pre
},{})
console.log(obj2);
12.如何做移动端适配?
rem的概念
rem 是移动端适配单位,是用来写移动端布局的
1rem 的大小就是1个 html 设置的 font-size 的大小(未设置情况下默认是1rem等于16px)
// 封装一个根据屏幕尺寸自动改变html的font-size大小的函数
function rem() {
// 获取html的宽度
let htmlW = document.documentElement.clientWidth;
// 获取body的宽度
let bodyW = document.body.clientWidth;
// 兼容处理
let W = htmlW || bodyW;
// 设置html的font-size大小
// 因为设计图尺寸是750,所以平分,这样*100之后,1rem就等于100px;
document.documentElement.style.fontSize = (W / 750 * 100) + 'px';
}
// 定义屏幕宽度改变时触发
window.onresize = function () {
rem()
}
// 设置初始触发一次
rem()
13.清除浮动有哪些方式?
1. 触发BFC
2. 多创建一个盒子,添加样式:clear: both;
3. after方式
ul:after{
content: '';
display: block;
clear: both;
}
14.延迟加载JS有哪些方式?
延迟加载:async、defer
例如:<script defer type="text/javascript" src='script.js'></script>
defer : 等html全部解析完成,才会执行js代码,顺次执行js脚本。
async : async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)。
defer
属性:在<script>
标签中添加defer
属性,浏览器会在解析完 HTML 文档后再执行脚本。
<script defer src="script.js"></script>
async
属性:使用async
属性,脚本一旦下载完成就会立即执行,不会阻塞文档的解析,但执行顺序不一定。
<script async src="script.js"></script>
- 动态创建
script
元素:通过 JavaScript 代码在页面加载完成后动态创建script
元素并添加到页面中,从而实现延迟加载。
function loadScript(url) {
var script = document.createElement('script');
script.src = url;
document.head.appendChild(script);
15.JS微任务和宏任务
1. js是单线程的语言。
2. js代码执行流程:同步执行完==》事件循环
同步的任务都执行完了,才会执行事件循环的内容
进入事件循环:请求、定时器、事件....
3. 事件循环中包含:【微任务、宏任务】
微任务:promise.then
宏任务:setTimeout..
要执行宏任务的前提是清空了所有的微任务
流程:同步任务执行完毕==》事件循环(任务队列)【微任务和宏任务】==》微任务==》宏任务=》微任务...