vue
vue的优点
1、简单易学,国内使用者多,文献多
2、学习了angular的双向绑定,react的组件化。
3、虚拟DOM(下边有描述)
4、运行速度更快:相比较react而言,操作虚拟DOM,在性能上vue存在很大的优势
5、让程序员把更多精力放在逻辑处理上
v-model
简单描述: v-model是vue中的双向绑定的指令,能将页面上控件输入的值同步更新到绑定的相关data属性中去,也会在更新data绑定属性的时候,更新到页面输入(输出)控件的值。全写v-model:value="XXX" 简写 v-model="XXX"。一般应用于表单输入框(input,select,textarea)
1.v-model 跟 v-bind 的区别在于,v-bind是单项绑定,v-model是双向绑定。
2.v-model通过视图层更新data的原理,可以理解为在input框里面通过v-bind动态绑定一个value,然后在input框里面通过@input(v-on:input)事件输入的值,然后重新给变量赋值就可以了。
虚拟DOM
具体点击这里 (参考文献)
简单描述: 首次渲染会调用一次 patch 并创建新的vnode,不会进行更深层次的比较,然后是在组件中数据发生变化时,会触发 setter 通过 Notify 通知 watcher, 对应的watcher会通知更新并执行更新函数,它会执行 render 函数获取新的虚拟 DOM,然后执行 patch 对比上次渲染结果的老的虚拟DOM,并计算出最小的变化,再根据这个最小的变化去更新真是DOM。
1、Diff 算法
(1) 只比较同一层级,不跨级比较
(2) 比较标签名:如果同一层级的比较标签名不同,就直接移除老的虚拟 DOM 对应的节点,不继续按这个树状结构做深度比较,简化比较次数。
(3) 比较key,如果标签名相同,key 也相同,就会认为是相同节点,也不继续按这个树状结构做深度比较,比如我们写 v-for 的时候会比较 key,不写 key 就会报错,这也就是因为 Diff 算法需要比较 key。
key的作用主要是为了更高效的更新虚拟DOM,因为它可以非常精确的找到相同的节点,因此 patch 过程会非常高效。
Vue 在 patch 过程中会判断两个节点是不是相同节点时,key 是一个必要条件。比如渲染列表时,如果不写 key,Vue 在比较的时候,就可能会导致频繁更新元素,使整个 patch 过程比较低效,影响性能。
应该避免使用数组下标作为 key,因为 key 值不是唯一的话可能会导致上面图中表示的 bug,使 Vue 无法区分它他,还有比如在使用相同标签元素过渡切换的时候,就会导致只替换其内部属性而不会触发过渡效果。
从源码里可以知道,Vue 判断两个节点是否相同时主要判断两者的元素类型和 key 等,如果不设置 key,就可能永远认为这两个是相同节点,只能去做更新操作,就造成大量不必要的 DOM 更新操作,明显是不可取的。
路由守卫
面试简洁回答:三种路由守卫,分别是全局前置守卫、路由独享守卫、组件内守卫。
共有三种路由守卫,分别是:
1、全局前置守卫:使用router.beforeEach()方法,用于在路由跳转之前进行拦截和权限校验等操作。
2、路由独享守卫:在定义时通过beforEnter属性来注册,只对当前路由生效,用于实现特定路由的权限控制。
3、组件内守卫:在组件通过beforRouterEnter、beforRouteUpdate、beforRouteLeave等属性注册,用于在组件内部控制路由跳转,例如在组件内部进行异步数据加载等操作。
data为什么return
是为了达成组件与组件之间的数据私有化
v-if 与 v-show 的区别
v-if 根据判断的条件渲染一块内容,如果不成立就不会渲染到页面上。
v-show 不管条件是否成立,都会渲染到页面上,只不过是用了display:none隐藏了。
单项 数据流 props 页面刷新 数据丢失 怎么处理
单项数据流是指父组件通过props向子组件传递数据,子组件只能通过事件向父组件传递数据,这样能够保证组件之间的数据流向清晰明确。
怎么处理数据丢失呢:
1、将数据传保存到接口里
2、保存在本地
3、使用路由参数 可以在路由中定义参数,将需要保留的数据作为参数传递给下一个页面。
4、vuex持久化
5、params传参,在路由路径中配置占位符
错误回答:
存放在vuex里,在 Vue 应用中,刷新页面会导致 Vuex 中的数据丢失。当页面刷新时,Vuex 的状态会被重置,所有之前存储的数据都会丢失。
vue跳转传参的区别
路由参数和 props 属性
1、传参方式不同:路由参数是通过 URL 上的参数传递的,而 props 属性是通过组件之间的属性传递的。
2、传参类型不同:路由参数只能传递字符串类型的参数,而 props 属性可以传递任意类型的参数。
3、使用场景不同:路由参数适用于传递简单的参数,如 ID、页面类型等,而 props 属性适用于传递复杂的数据结构,如对象、数组等。
4、组件耦合度不同:路由参数传递的参数可以在任意组件中获取,而 props 属性传递的参数只能在父组件和子组件之间传递,增加了组件之间的耦合度。
5、安全性不同:路由参数传递的参数可以被用户轻易地修改,而 props 属性传递的参数只能被组件内部的逻辑所修改,安全性更高。
路由参数又分:
query传参:
1.可以使用name ,path , 字符串拼接方式传参
2.每次刷新不会丢失数据
3.不能使用props接收数据
params传参:
1.路由中不写占位符,只能使用name 传参
2.不使用占位符,刷新会丢失数据,使用占位符则不丢失数据 所以需要在规则中配置属性名
3.可以使用props接收数据
provide与inject传参:
优点:孙子组件可以接收,主打的就是一个方便。
缺点:不好维护,官网都说了,怕你 “ 把握不住 ”。
监听子组件
1、v-on,$emit
2、ref
template在vue里是什么?为什么用它?会编译成什么标签?
面试简洁回答:1、字符串模板。2、定义组件的结构和行为,用于形成最终的HTML。易于维护,同时实现组件动态化。3、不会被渲染成任何实际HTML标签。
在Vue中,template标签用于定义组件的结构和行为,Vue会将template中的代码编译成可运行的JavaScript渲染函数,用于生成最终的HTML。使用template可以将组件的代码更加清晰和易于维护,同时实现组件的动态化。在编译时,template会被编译成一个render函数,该函数返回一个虚拟DOM节点,然后将该节点渲染到页面上,因此在运行时,template标签最终不会被渲染成任何实际的HTML标签。
VUEX
Vuex包含了以下几个部分:
state:用于存储应用中需要共享的状态,即定义数据的地方。
getters:类似于计算属性,用于从 store 中获取 state 中的派生状态,即对数据的一些操作。
mutations:用于修改 state 中的状态,但是只能进行同步操作。
actions:用于处理异步操作,最终还是需要通过提交 mutation 来改变 state 中的状态。
modules:将 store 分割成多个模块,每个模块都有自己的 state、mutation、action、getter,方便进行代码的管理和维护。
vue传参有几种
在Vue中,组件之间传参的方式有以下几种:
props:父组件向子组件传递数据。在父组件中通过props属性声明需要传递的数据,然后在子组件中通过props选项接收数据。
$emit:子组件向父组件传递数据。在子组件中通过$emit方法触发自定义事件,并传递需要传递的数据,然后在父组件中通过v-on监听该事件,接收子组件传递的数据。
$attrs/$listeners:在父组件中向子组件传递所有的属性和事件。在父组件中通过v-bind=“$attrs"和v-on=”$listeners"将所有属性和事件传递给子组件,然后在子组件中通过inheritAttrs选项和$attrs/$listeners来访问这些属性和事件。
provide/inject:在父组件中向子孙组件传递数据。在父组件中通过provide提供需要共享的数据或方法,然后在子组件中通过inject注入需要的数据或方法,从而实现跨层级传递数据。
Vuex:在组件之间共享状态。通过Vuex中的state、getters、mutations和actions等实现组件之间的数据共享。
$nextTick
在Vue中,$nextTick是一个用于在下次 DOM 更新循环结束之后执行延迟回调的方法。它的作用是在当前数据变化已经完成,并且对应的DOM已经重新渲染之后,再执行回调函数。
JavaScript
变量名 | 区别 |
---|---|
var | 有变量提升,可重复声明 ,有初始提升 |
let | 有变量提升,没有初始化提升,值可变,存在暂时性死区所以有变量提升,但是没有提升 |
const | 有变量提升,没有初始化提升,值不可变,但如果是定义对象,则属性可变 ,存在暂时性死区 |
总结:三种声明变量 都是拥有变量提升的 只不过是 let 跟 const 存在暂时性死区 所以表面上没有变量提升,理论上拥有变量提升的
JS类型
基本类型:number string boolean undefined null symbol bigInt
引用类型:Object Array Function 等
为什么会有变量提升
简答:因为js的“预编译”所以导致变量提升,js在解析代码时会先对整个作用域进行扫描和解析,找出其中的变量声明和函数声明,并将它们提前到作用域的顶部。所以在声明前调用不会报错。
变量提升是JavaScript中的一种特性,指的是在代码执行之前,变量的声明部分会被提前到作用域的顶部。
变量提升的原因是因为JavaScript的解释器在解析代码时,会先对整个作用域进行扫描和解析,找出其中的变量声明和函数声明,并将它们提前到作用域的顶部,这个过程被称为“预编译”
三种缓存方法
简单描述:session,local,cookie,三种存储方法,session是临时存储只要浏览器不关闭就不会丢失,local是永久存储除非手动删除,否则不会丢失。两种Storage只能存储字符串。Cookie存在跨域,浪费带宽,存储量小(最大4kb)。
1.sessionStorage:临时的会话存储
只要当前的会话未关闭,存储信息就不会丢失,即便页面刷新或在编辑器中更改了代码,存储的会话信息也不会丢失。反则只要页面关闭了存储的信息都会消失。一般用来放一些临时的数据。
2.localStorage:永久存储
会一直将数据存储在客户端的存储方式,即使关闭了浏览器,下次打开的时候仍然可以看到之前存储的未主动清除的数据(即便是杀毒软件或者是浏览器自带的清除功能,也不能将localStorage存储的数据清除掉)。题外话:uni-app里存储就是使用的local存储方法。
两种Storage存储方法只能存储字符串数据,对于JS中常用的数组或对象却不能直接存储,它能保存更大的数据(IE8上是10MB,Chrome是5MB),同时保存的数据不会再发送给服务器,避免带宽浪费
3.Cookie
缺点比较明显: 跨域问题,无法保存太大数据(最大4KB),保存的数据会发送给服务器,不管服务器是否需要,每一次HTTP请求都会携带存储的数据传输到服务器端,非常浪费带宽。
闭包
闭包的定义:闭包是指有权访问另一个函数作用域中的变量的函数。——《JavaScript高级程序设计》
我的理解是:暴漏一个能访问(或修改)内部变量的函数,这都属于闭包。
this指向
普通函数:关于this,谁调用就指向谁,没有调用者,就指向全局对象window。
箭头函数:箭头函数的this指向于函数作用域所用的对象。
apply()、call()、bind() 区别
1、共同点 : 都是用来改变 this 指向的
2、区别:
(1)call 、apply 可以立即执行;
bind 不会立即执行,因为bind返回的是一个函数,执行的时候需要在后边加上();
(2)call和bind有多个参数 逗号分隔 就可以了,apply 有多个参数的时候需要传入一个数组进行传参
let callStr = "这是拉拉";
let callObj = {
callStr: "这是obj对象的str"
};
function callFun(name, age) {
this.name = name;
this.age = age;
console.log(this, this.callStr);
}
callFun.call(callObj);
callFun.apply(callObj);
callFun.bind(callObj)();
// 以上三条都输出: {callStr: "这是obj对象的str", name: undefined, age: undefined} "这是obj对象的str"
callFun.call(callObj, "李四", "22");
callFun.apply(callObj, ["李四", "22"]);
callFun.bind(callObj, "李四", "22")();
// 以上三条都输出 {callStr: "这是obj对象的str", name: "张三", age: 23} "这是obj对象的str"
函数声明和函数表达式有什么区别
// 函数声明
let add = sum(1,2)
function sum(num1,num2){
return num1 + num2;
}
//函数表达式 (匿名函数)
let add = function (num1,num2){
return num1 + num2;
}
console.log( add(1,2) )
// 函数声明 是有提升的,调用的时候可以在声明函数之前使用。
// 匿名函数 没有提升,须在声明(赋值)之后调用。
浅拷贝 深拷贝
浅拷贝:共同一个内存,新旧一个改变都改变。
深拷贝:复制一个一模一样的对象,不共享内存,新旧改变不关联。
原型链
具体看这里 (参考文献)看完原型链和es6中的class概念也就明白了
原型与原型层层相链接的过程即为原型链。
防抖与节流
防抖:是把多次执行变为最后一次执行
节流:是将多次执行变成每隔一段时间执行
回流(重排) 重绘
个人理解:
1.回流(重排):涉及到尺寸大小导致页面需要从新排版。
2.重绘:不涉及到兄弟(父级)排版问题,只是单纯改变字体颜色背景颜色一类或类似操作或小型操作。
TCP三次握手四次挥手
全网最简洁易懂 三次握手 四次挥手 解析
TCP三次握手是建立TCP连接时,客户端向服务器发送SYN,服务器向客户端回复SYN+ACK,客户端再回复ACK,连接建立。四次挥手是终止TCP连接时,客户端向服务器发送FIN,服务器回复ACK,然后服务器向客户端发送FIN,客户端回复 ACK,连接终止。
SYN:表示同步,用于在TCP连接建立是,客户端向服务器端发送一个SYN标志的信息,表示要建立连接。
ACK:表示确认,用于在TCP连接建立和终止时,双方进行确认,确保信息的可靠传输。
FIN:表示结束,用于在TCP连接终止时,客户端或服务器端向对方发送FIN标志的信息,表示要关闭连接。
判断数据类型
typeof // console.log( typeOf ‘123456’ )
instanceof // console.log( ‘123456’ instanceof String )
// typeOf 会直接返回变量类型
// instanceof 是比对 是否是 某某某 类型
栈、堆
堆:引入类型 (如:对象、function、数组)
栈:数据类型 (如:数字、字符串、布尔值、null和undefined)
HTML
盒子模型
1、w3c:宽高 只算内容的宽高
2、IE怪异模型:宽高算上了 border(边框) + padding(内边距) + 内容宽(高)
扩展:
当设置为box-sizing:content-box时,将采用标准模式解析计算,也是默认模式。
当设置为box-sizing:border-box时,将采用怪异模式解析计算,这时padding将不会向内压缩内容。
前端优化代码
可以采用第三方 CDN加速