1.css3新特性
- border-radius:创建圆角边框
- box-shadow:为元素添加阴影
- border-image:使用图片来绘制边框
- background-size:背景图片大小
- transition:过渡
- animation:动画
渐变
flex布局
2.css优先级
!important<内联 > ID > 类、伪类、属性选择器 > 标签 >通配符
3.px,vw/vh,rem的区别
px, 表示像素,所谓像素就是呈现在我们显示器上的一个个小点,每个像素点都是大小等同的,
所以像素为计量单位被分在了绝对长度单位中
rem,相对单位,相对的只是HTML根元素`font-size`的值
vw ,就是根据窗口的宽度,分成100等份,100vw就表示满宽,50vw就表示一半宽。
同理,`vh`则为窗口的高度
4.es6新特性
symbol,表示独一无二的值,即每个symbol类型的值都不相同
新加了俩了声明变量的关键词let和const
解构赋值是对赋值运算符的扩展。它是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
assign用于浅拷贝源对象可枚举属性到目标对象
扩展运算符 用于拷贝目标对象所有可遍历的属性到当前对象
is方法和(===)功能基本类似,用于判断两个值是否绝对相等。
biglnt 数据类型是为了让javascript程序能表示超出Number类型支持的数值范围,在等于大整数进行数学运算时
以任意精度表示整数的能力尤为重要 有了biglnt整数溢出将不再是一个问题
5.如何理解响应式网站?
响应式网站是指能够适应不同设备和屏幕尺寸的网站。它通过使用灵活的布局、自适应的图片和媒体查询等技术,
以确保在各种设备上都能提供最佳用户体验。
理解响应式网站可以从以下几个方面入手:
1.弹性布局:响应式网站使用弹性布局来适应不同屏幕尺寸。相对于固定宽度的布局,
弹性布局使用相对单位(如百分比)和流动的盒模型,使得网站的元素能够自动伸缩和调整大小,以适应屏幕的变化。
2.媒体查询:媒体查询是一种CSS3的功能,它可以根据不同的设备特性(如屏幕宽度、浏览器窗口大小等)来应用不同的样式。
通过媒体查询,可以为不同的屏幕尺寸定义不同的布局和样式,使得网站在各种设备上都能呈现最佳的展示效果。
3.自适应图片:在响应式网站中,图片也是需要适应不同屏幕尺寸。通过使用CSS max-width属性、picture元素、srcset属性等技术,
可以为不同设备提供适当大小的图片,以避免加载过大的图片、提高网站加载速度并节省带宽。
4.视口设置:视口是指浏览器中用于显示网页内容的区域。
在响应式网站中,通过设置视口的meta标签(如viewport),可以控制网页如何在移动设备上进行缩放和布局。
通过设置合适的视口参数,可以让网站在移动设备上呈现好的可读性和用户体验。
总之,响应式网站是一种能够根据不同设备和屏幕尺寸自适应展示的网站。通过使用弹性布局、媒体查询、自适应图片和视口设置等技术,
可以使网站在不同设备上都能提供优良的用户体验。
6.闭包
a.怎么理解闭包
闭包指有权访问另一个函数作用域中变量的函数。简单理解就是一个作用域可以访问另一个函数内部的局部变量
b.闭包的作用
封闭数据 实现数据私有 外部也可以访问函数内部的变量
闭包很有用 因为他运行将函数与其所操作的某些数据(环境)关联起来
c.优缺点
优点:
延长变量作用域 在函数的外部可以访问函数内部的局部变量
缺点:
容易造成内层泄漏,因为闭包中的局部变量永远不会被回收 解决方法:需要手动清除 把变量变为null
d.概念
一个函数对周围状态的引用捆绑在一起,闭包让开发者可以从内部函数访问外部函数的作用域
e.闭包是指函数嵌套时, 内层函数访问外层函数的局部变量
总结:
1. 一旦发生闭包, 意味着外层函数的局部变量不会随着函数的结束而释放, 会长期存在一个叫 closure (闭包)的空间中
2. 闭包会导致内存泄漏, 但这种内存泄漏是必要的, 我们无法阻止的, 只能说尽量少用闭包, 但必须用的时候还是得用
7.原型和原型链
原型:js的每个函数在创建的时候,都会生成一个属性prototype,
这个属性指向一个对象,这个对象就是函数的原型对象,该原型对象中有个属性为constructor,
指向该函数,这样原型对象和他的函数直接就产生了联系
原型链:当访问一个对象的某个属性时,会先在这个对象本身属性上查找,
如果没有找到,则会去它的__proto__隐式原型上查找,
即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,
这样一层一层向上查找就会形成一个链式结构,我们称为原型链
复制代码
8.js继承
JavaScript 对象是动态的属性(指其自有属性)“包”。
JavaScript 对象有一个指向一个原型对象的链。
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,
以及原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾
9.如何用css画一个三角形
先设置1个盒子 给出边框色和边框宽度
再给边框宽度增加 设置border边四个颜色
然后给盒子的宽高给0 再消除掉其他的三个边颜色 此时就能得到一个三角形
10.如何拓展数组的方法
给数组(Array)对象添加一个原型对象名叫max,并且给这个叫max的原型对象设置一个方法。
但是方法里操作的数据不能写死,而应该谁调用就用谁的数据,所以也就是说要用this
Array.prototype.max = function (){
let max = this[0]
for(let i = 1; i <this.length ; i++){
if(this[i] >max){
max = this[i]
}
}
return max
}
let arr1 = [1,2,3]
let arr2 = [10,20,30]
let res1 = arr1.max()
let res2 = arr2.max()
console.log(res1)
console.log(res2)
这样,就在Array里设置好了一个叫max的原型对象,由于所有数组都属于Array对象,
所以任意一个数组都能通过原型链的方式找到这个叫max的原型对象,并调用该方法
11.数组的常见方法?
1.push
定义:向数组的末尾追加元素
@params:追加的项(多个任意类型)
@return:新增数组的长度
是否改变原数组:改变
2.unshift
定义:向数组的开头增加元素
@params:追加的项(多个任意类型)
@return:新增数组的长度
是否改变原数组:改变
3.shift
定义:删除数组的开头项
@params:无
@return:删除的那一项
是否改变原数组:改变
4.pop
定义:删除数组的结尾项
@params:无
@return:删除的那一项
是否改变原数组:改变
5.splice
定义:实现数组的增加、删除、修改;
@params:n,m,x
@return:修改后的新数组
是否改变原数组:改变
6.slice
定义:实现数组的查询
@params:n,m
@return:把找到的内容以新数组的形式返回
是否改变原数组:不改变
7.concat
定义:实现数组拼接(合并)
@params:拼接的项(多个任意值)
@return:拼接后的新数组
是否改变原数组:不改变
8.toString
定义:把数组转换为字符串
@params:无
@return:转换后的字符串,每一项用逗号分隔
是否改变原数组:不改变
9.join
定义:把数组转换为字符串
@params:按指定的分隔符连接
@return:转换后的字符串
是否改变新数组:不改变
12.如何判断数据类型
a.可以根据typeof运算符来看返回类型,但是typeof只能用来判断简单(值)类型的,
不能用来判断引用类型
列如:
let a = 8
console.log(typeof a )
在控制台上面的结果是number 说明是数值 以此类推
b.通过tostring来判断
通过objcet原型链(prototype)上的toString来判断变量的类型
是最直接靠谱的这也是各大 框架底层用来判断数据类型的方法
let a = 8
let b = '8'
let c = true
let d = [1,2,3,4,5]
let e ={id:1,name:'15'}
let f =undefined
myTypeof(a)
myTypeof(b)
myTypeof(c)
myTypeof(d)
myTypeof(e)
myTypeof(f)
function myTypeof(obj){ console.log(Object.prototype.toString.call(obj)) }
13.var, let和const的区别
1.var 声明的变量可以`重复声明`,let、const不可以;
2.var 声明的变量会`提升到当前作用域的最前面`,let、const不会;
3.var声明的变量会`挂载到window上`,成为window的属性,let、const不会;
4.let、const会产生`块级作用域`,var不会
5.let、const存在`暂时性死区`(声明之前不能调用),var没有
针对cosnt声明的变量:
6.cosnt 声明时,`必须赋值`,否则会报错,
这是因为const声明的变量在初始化之后就不能再次赋值,因此必须在声明时赋值。
7.cosnt声明的是常量,`不能更改`,
指的是基本数据类型不能更改值,而引用数据类型不能更改他的引用地址,
这意味着无法通过赋值语句来更改常量的值,但是如果const声明的变量是一个对象或数组,
则仍然可以更改其属性或元素的值。
14.defineproperty 和 Proxy
defineproperty 只能监听某个属性而不能监听整个对象
proxy 不用设置具体属性,直接监听整个对象
defineproperty 监听需要知道是哪个对象的哪个属性
而 proxy 只需要知道哪个对象就可以了
也就是会省去 for in 循环提高了效率
15.防抖和节流
防抖和节流都是用来提升浏览器性能的优化手段,他们的区别在于:
防抖:在单位时间内频繁的触发事件 只会执行最后一次
应用场景:实时搜索(keyup) 、 拖拽(mousemove)
节流:在单位时间内频繁的触发事件 只会执行一次
应用场景:窗口调整(resize)、页面滚动(scroll)、抢购和疯狂点击(mousedown)、
16.箭头函数
箭头函数是Es6新增的一种定义函数表达式的语法,它简化了我们之前写的函数书写方式,
箭头函数实例化的函数对象与我们Es5之前创建的函数表达式的创建函数行为是相同的。在任何使用函数表达式的地方,
都可以使用箭头函数。
let sum = function(a,b){
return a + b;
}
let sum1 = (a,b) =>{
return a + b;
}
console.log(sum(1,2));
console.log(sum1(1,2));
可以看到我们少写了function,如果我们只传递一个参数还可以把小括号去掉
直接写 let sum1 = a =>{} 也可以运行
17.重绘和回流
什么是回流:
当我们对DOM的修改引发了DOM几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,
浏览器需要重新计算元素的几何属性(其他元素的几何属性和位置也会因此受到影响),
然后再将计算机的结果绘制出来。这个过程就是回流(也叫重排)
由本身的大小宽高改变,引发局部或全局的排班,会引发回流或局部回流
全局范围: 从根节点html开始对整个渲染树进行重新布局
局部范围: 对渲染树的某部分或某一个渲染对象进行重新布局
什么是重绘:
我们对DOM的修改导致了样式的变化,却并未影响其几何属性(比如修改颜色或背景色)时
浏览器不需要重新计算元素的几何属性,直接为该元素绘制新的样式。这个过程叫做重绘
只改变外观、风格、不影响布局、会引发重绘
回流比重绘大
重绘:某些元素的外观被改变,列如:元素的填充颜色
回流:重新生成布局,重新排列元素
局部范围重排:
用局部布局来解释这种现象,把一个DOM的宽高之类的几何信息定死,然后在DOM内部重排
就只会重新渲染该dOM内部的元素,而不会影响到外界。
就如上面的概念一样,单单改变元素的外观,肯定不会引起网页的重新生成布局,
之后,将会重新绘制受到这次重排影响的部分
一句话概括:回流必将引起重绘、重绘不一定会引起回流
18. 递归函数
递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。
简单理解函数内部调用自己,这个函数就是递归函数
优点:结构清晰,可读性强 需要有结束条件 return
缺点:效率低,调用栈可以会溢出,其实每一个函数调用会在内存栈中分配空间,
而且每个进程的栈的容量是有限的,当调用的层数太多时,就会超出栈的容量,从而导致栈溢出性能
19.微任务和宏任务
首先因为Javascript是一门单线程的语言,意味着同一时间内只能做一件事,
但是着并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环
在JavaScript中所有的任务都可以分为
同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
异步任务:异步执行的任务,比如ajax1网络请求,setimeout定时函数等
在异步任务中又分为微任务和宏任务
微任务:
一个需要异步执行的函数,执行时机是在主函数执行结束之后,当前宏任务结束之前
常见的微任务有:
Promise.then
MutaionObserver
object.observe
process.nextTick(node.js)
宏任务:
可以理解是每次执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并方到执行栈中执行)
常见的宏任务有:
script(可以理解为外层同步代码)
setTimeout/setlnterval
ul rendering/ul事件
postMessage,MessageChannel
setlmmediate
20.eventloop
由于js是单线程的,一次只能执行一个任务。 那么多个任务堆在一起时,
就要这些任务排排队。按照先进先出的规则,形成一条 消息队列
多个任务源,形成多条 消息队列 这就形成一条事件循环的执行队列。
事件循环:
就是一个执行消息队列的机制。 首先选择 优先级最高的
21.v-show和v-if
首先v-show和v-if都是用来控制元素显示和隐藏的,但是其中的原理和使用方法也有差别
v-show隐藏是为该元素添加display:none,元素还在
v-if隐藏是将元素中的某个节点删除
一般来说v-if有更高的切换开销,而且v-show有更高的初始渲染开销。因此,如果需要非常频繁的切换,
则使用v-show较好,如果在运行时条件很少改变,则使用v-if较好
22.key的作用
key的作用
提升diff算法效率,因为diff算法需要进行节点的对比,早期如果不设置key的值的话
它是一个undefined,现在会自动生成一个唯一值,但是你不管是没设置key,或者key值是索引来表示的话,
它们的key值还是一样的,它的效率会降低,如果你设置了唯一值的话,在比较两个虚拟dom是不是一样的时候
它首先会看你的key值是不是一样的,如果不一样它就会跳过
设置key就是唯一标识
主要是为了更高效的更新虚拟DOM,因为它可以非常精确的找到相同节点,因此patch过程会非常高效
vue在patch过程中会判断俩个节点是不是相同节点时u,key是一个必要条件。
比如渲染列表时,如果不写key,Vue在比较的时候,就可能会导致频繁更新元素,使整个Patch过程比较低效,影响性能
如果用index作为下标的话会出现什么
key的值不是唯一的话可能会导致上面图中表示的bug,使vue无法区分其他,
还有比如在使用相同标签元素过渡切换的时候,就会导致只替换内部属性而不会触发过渡效果
从源码里可以知道,Vue判断俩个节点是否相同主要判断两者的元素类型和Key等,
如果不设置Key就可能永远让这俩个是相同节点,只能去做更新操作,
就造成大量不必要的DOM更新操作,明显是不可取的
23.虚拟dom
vue1是没有虚拟dom的,是vue2新出来的新特效,解决了跨平台的问题,不仅可以在浏览器运行,还可以在ios,安卓手机端运行
没有虚拟dom的话,这是没有方法实现的,比如修改了一个数据,虚拟dom会重新生成
但是虚拟dom最终会变成什么样子,这得由平台方去决定,虚拟dom其实就是一个对象,他有个属性,有键值对
但是怎么把对象表示的含义变成真正的元素,这是个由平台决定的,这就是虚拟dom1最大的好处
24.diff算法
跟虚拟dom配套出来的,也就是意味着不会去操作真实dom,diff算法的目的就是找出新旧不同虚拟dom之间的差异
使最小化的更新视图,他是交叉比较,他判断节点是使用一个api,singweload 比较的条件就是key值
这就是为什么在做虚拟循环的时候脚手架会让我们要加key1的值,这也是为了diff算法更加的方便
difference(全拼)提升效率,它一定要用递归去比较
25.hash路由和history路由
hash
vue-router默认为hash模式,使用URl的hash来模拟一个完整的URL,当URL改变时,
页面不会重新加载;
路由的hash模式是利用了window 可以监听 onhashchange 事件来实现的,
也就是说hash值是用来指导浏览器动作的,对服务器没有影响,HTTP 请求中也不会包括hash值,
同时每一次改变hash值,都在浏览器的访问历史中增加一个记录,使用“后退”按钮,就可以回到上个位置
所以,hash模式是根据hash值来发生改变,根据不同的值,渲染指定DOM位置的不同数据。
优点:
url中带一个
可以改变URL,但不会触发页面重新加载(hash的改变会记录在 window.hisotry 中)因此并不算是一次 HTTP 请求,
所以这种模式不利于 SEO 优化
只能修改
只能通过字符串改变 URL
通过window.onhashchange监听hash的改变,借此实现无刷新跳转的功能。
每改变一次hash(window.location.hash),都会在浏览器的访问历史中增加一个记录。
路径中从
发给服务器
History:
history 是路由的另一种模式,在相应的router配置时将mode设置为 history 即可。
history 模式是通过调用 window.history对象上的一系列方法来实现页面的无刷新跳转。
利用了 HTML5 History Interface中新增的ushState()和replaceState()方法。
这两个方法应用于浏览器的历史记录栈,在当前已有的back、forward、go的基础之上,
它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会向后端发送请求。
27.nextTick
页面的DOM还未渲染,这时候也没办法操作DOM,如果想要操作DOM。需要使用nextTick来解决这个问题
实现原理:
nextTick的核心是利用了如Promise MutaionObserver Setlmmediate setTimeout的原生Javascript
方法来模拟对应的微/宏任务的实现,本质是为了利用javascript的这些异步回调任务队列
来实现Vue框架中自己的异步回调队列
Vue在更新DOM时是异步执行的。当数据发生变化,Vue将开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一更新
应用场景:
1.一个输入框本来是隐藏的,想让他显示的同时获取焦点
2.在数据变化后执行的某个操作,而这个操作需要使用数据变化而变化的DOM结构的时候,这个操作就需要方法在的回调函数中
3.在vue生命周期中,如果在created()钩子进行dom操作,也一定要放在的回调函数中
28.mixin的优点和缺点
在导出的对象中可以写组件的配置项如:data methods computed watch
作用:将组件内相同的业务逻辑提取到一个公共的模块,当组件内需要时再混入到组件内
特性:
1.要混入的对象中如果是生命周期函数 依次执行 先执行混入的生命钩子函数
2.要混入的对象中的data 如果变量的值冲突 以组件内的值为准(覆盖)
3.要混入的对象中methods 如果函数名冲突,以组件内的值为准(覆盖)
优点:
可以组件复用
缺点:
不可知 不易维护
因为在mixins里面几乎可以加任何代码 props data methods 各种东西
就导致如果不了解mixins封装的代码话 是很难维护的
30.eventBus的原理?
EventBus是一种事件发布/订阅模式的实现,它用于解耦不同组件之间的通信,使得组件能够松散地耦合并提高代码的可维护性。
EventBus的原理如下:
1.注册和订阅:组件可以通过订阅特定的事件来表明自己对该事件感兴趣。
在EventBus中,组件需要将自己注册到EventBus,并指定要订阅的事件类型。
2.发布和通知:当某个组件发生了特定的事件,它可以将该事件发布到EventBus中。
EventBus会根据事件的类型,通知所有订阅了该事件的组件。
3.事件分发:EventBus会维护一个事件注册表,其中记录了每个事件类型所对应的订阅组件列表。
当事件发布时,EventBus会遍历相应事件类型的注册表,依次通知所有订阅组件。
4.异步处理:EventBus可以支持异步事件处理,即事件发布和订阅是非阻塞的。这意味着事件发布后,
发布方可以继续执行其他任务,而不需要等待所有订阅组件完成处理。
总结起来,EventBus的原理就是通过组件的注册和订阅,以及事件的发布和通知,实现组件间解耦的事件通信机制。
它能够提高代码的可维护性,使得系统的各个组件能够更加松散地协作。
31.vue2生命周期
vue的生命周期就是vue实例从创建到销毁的过程
也就是从开始创建 初始化数据 编译模板 挂载dom->渲染 更新 渲染 准备销毁 销毁在等一系列过程
vue的生命周期常见的主要分为四大阶段八个钩子函数
a.创建前/后
执行before create执行的时候 data和method还没初始化 只有一些vue默认的方法
created执行的时候 data和method已经初始化完成可以操作了
b.挂载前/后
在before mount执行的时候 模板已经在内存中渲染好了 但是还没有真正的渲染到页面中去
在mounted 执行的时候 将内存中渲染好的模板 真正的替换到浏览器中
执行完mounted vue实例的初始化阶段已经结束 此时已经脱离创建阶段 进入执行阶段
c.更新前/后
在beforeupdate执行的时候 页面的数据还是旧的 但是data的数据已经是最新的,页面还没和data保存同步
在updated执行的时候 已经把更新后的数据渲染到视图中了 页面的数据已经是最新的了 和data保持同步
d.销毁前/后
在beforeDestroy执行的时候 实例进入准备销毁的阶段 此时data methods 指令等还是可用状态
在destroyed执行的时候 实例已经完成销毁 此时data methods 指令等都不可用
另外三个生命周期函数不常用
keep-alive主要用于保留组件状态或避免重新渲染
activated只有在keep-alive组件激活时调用
deactivated只有在keep-alive组件停用时调用
errorCapured当捕获一个来自子孙组件的错误时被调用 此钩子会收到三个参数
错误对象 发生错误的组件实例以及一个包含错误来源信息的字符串,
此钩子可以返回false已阻止错误继续传播
32.created和mounted的区别?
created
执行before create执行的时候 data和method还没初始化 只有一些vue默认的方法
created执行的时候 data和method已经初始化完成可以操作了
mounted
在before mount执行的时候 模板已经在内存中渲染好了 但是还没有真正的渲染到页面中去
在mounted 执行的时候 将内存中渲染好的模板 真正的替换到浏览器中
执行完mounted vue实例的初始化阶段已经结束 此时已经脱离创建阶段,进入执行阶段
区别:
created是在组件实例一旦创建完成的时候立刻调用,这时候页面`dom`节点并未生成mounted
是在页面`dom`节点渲染完毕之后就立刻执行的触发时机上created是比mounted要更早的两者相同点:
都能拿到实例对象的属性和方法讨论这个问题本质就是触发的时机,
放在mounted请求有可能导致页面闪动(页面dom结构已经生成),
但如果在页面加载前完成则不会出现此情况建议:放在create生命周期当中
33.v-model和.sync
v-model和.sync的共同点 都是语法糖 都可以实现父子组件中的数据的双向通信
v-model和.sync的不共同点
v-model:
a.父组件的v-model=""子组件@(input,value)
b.一个组件只能绑定一个v-model
c.v-model针对更多的是最终操作结果是双向绑定的的结果,是value,是一种change操作
.sync:
a.父组件:my-prop-name.sync子组件@update:my-prop-name的模式来替代事件触发。
实现父子组件间的双向绑定
b.一个组件可以多个属性用.sync修饰符,可以同时双向绑定多个prop
c..sync针对更多的是各种各样的状态,是状态的互相传递,是status,是一种update操作
34.组件之间的通信方式
a.父向子通信:在子组件的标签上通过自定义属性传递父组件的数据,子组件内部通过props接收父向子传递的数据
b.子向父通信:在子组件的标签上自定义事件,自定义事件的值是父组件的方法,在子组件内部通过this.#emit()方法触发事件
第一个参数为自定义事件,第二个参数可以传递子组件的内部数据,此时父组件中的方法就可以执行了
c.兄弟组件通信:可以采取eventbus实现数据传递,但是这种方式我们在开发中基本不用,多组件共享数据都用的是vuex
d.后代组件通信:可以采取依赖注入的方式,在祖先组价中通过provide提供数据,在后代组件中通过inject接收数据
e.无关联系组件通信:在开发中我们都是使用的vuex
35.vuex
vuex是一个专为了Vue.js应用程序开发的状态管理模式。它采用集中存储管理应用的所有组件的状态,并以相应的规则保证
状态,状态以一种可预测的方式发生变化
vuex的出现解决了
a.多个组件共享状态时,单向数据流的简洁性很容易被破坏
b.多个视图依赖于同一状态
c.来自不同视图的行为需要变更同一状态
vuex中五个主要的成员
state 是用来存储数据的
mutations 是用来修改state中数据的方法
actions 是用来处理一些异步操作数据的行为方法
getters 有点类似于计算属性,是对state中的数据做了一些处理
modules 是用来对复杂业务分模块的,每个模块也可以有state mutaions actions gettets
36.