2023前端面试问题总结(vue)

1.js闭包

什么是闭包:闭包就是能够读取其他函数内部变量的函数

function a() {
        let a1 = 1;
        return function() {
                return a1
        }
}

闭包存在意义:

可以延长变量的生命周期4可以创建私有的环境

闭包好处:

可以读取其他函数的内部变量

将变量始终保存在内存中

可以封装对象的私有属性和方法

坏处:消耗内存、使用不当会造成内存溢出问题

2.vue中的data为什么是一个函数?(面试常问)

Vue 中的 data 必须是个函数,因为当 data 是函数时,组件实例化的时候这个函数将会被调用,返回一个对象,计算机会给这个对象分配一个内存地址,实例化几次就分配几个内存地址,他们的地址都不一样,所以每个组件中的数据不会相互干扰,改变其中一个组件的状态,其它组件不变。
简单来说,就是为了保证组件的独立性和可复用性,如果 data 是个函数的话,每复用一次组件就会返回新的 data,类似于给每个组件实例创建一个私有的数据空间,保护各自的数据互不影响.

实际上就是一个闭包,因为vue是单页面应用,是由很多组件构成,每一个组件中都有一个data,所以通过闭包给每一个组件创建了一个私有的作用域,这样就不会相互影响。

3.var let const 区别

var: 存在变量提升;存在变量覆盖,已经被定义且赋值的变量,如果再次被赋值,则以后一次值为准;没有块级作用域;

const:定义的是常量,声明之后必须赋值;定义的值不能去修改,否则报错;有块级作用域;不存在变量提升和变量覆盖;对于数组和对象的元素修改,不算做对常量的修改,不会报错。

let: 有块级作用域;不存在变量提升和变量覆盖;let不允许在相同的作用域中重复声明,注意是相同作用域,不同作用域重复声明不会报错

 4.解构赋值

let a = 1; let b = 2;  如果在不声明第三个变量的前提下,使a=2, b=1?

答案:[a, b] = [b, a]

5.如何利用es6快速的去重? 

let arr = [23, 12, 13, 33, 22, 12, 21]

let item = [...new Set(arr)]

6.Promise 面试题 以下代码的执行结果是?

const promise = new Promise((resolve, reject) => {
        console.log(1)
        resolve()
        console.log(2)
})
promise.then(() => {
        console.log(3)
})
console.log(4)

答案:1,2,4,3

解释:以上考察的是关于promise的原理,promise的构造函数是同步执行的,当new Promise的一瞬间,1,2 就立刻被执行,而 .then方法是异步执行的,当执行完1和2之后,会执行输出4,最后执行输出3

 7.MVC和MVVM的区别

MVC:M(model数据)、V(view视图),C(controlle控制器)缺点是前后端无法独立开发,必须等后端接口做好了才可以往下走;前端没有自己的数据中心,太过依赖后台

MVVM:M(model数据)、V(view视图)、VM(viewModel控制数据的改变和控制视图)
html部分相当于View层,可以看到这里的View通过通过模板语法来声明式的将数据渲染进DOM元素,当ViewModel对Model进行更新时,通过数据绑定更新到View。 Vue实例中的data相当于Model层,而ViewModel层的核心是Vue中的双向数据绑定,即Model变化时VIew可以实时更新,View变化也能让Model发生变化

MVVM与MVC最大的区别就是:它实现了View和Model的自动同步,也就是当Model的属性改变时,我们不用再自己手动操作Dom元素,来改变View的显示,而是改变属性后该属性对应View层显示会自动改变

 8.v-model 原理

是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调从而达到数据和视图同步。 

9. v-if 和 v-show的区别

v-if是通过添加和删除元素来进行显示或者隐藏

v-show是通过操作DOM修改display样式来修改元素的显示和隐藏

如果需要频繁的进行元素的显示和隐藏使用v-show性能更好

10.v-for中为什么要有key

key 可以提高虚拟DOM的更新效率。

在vue中,默认“就地复用”的策略,在DOM操作的时候,如果没有key 就会造成选项错乱

key 只能是字符串或者number,其他类型不可以

1. 虚拟DOM中key的作用:

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新的虚拟DOM】与【旧的虚拟DOM】差异比较比较规则如下:

2. 比较规则:

1)旧虚拟DOM找到了与新虚拟DOM相同的key:

若虚拟DOM中内容没变,直接使用之前的真实DOM

若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM

3. 用index作为key可能会引发的问题:

1)若对数据进行:逆序添加、逆序删除等破坏顺序的操作,会产生没有必要的真实DOM更新==>界面效果没问题,但效率低

2)如果结构中还包含输入类的DOM,会产生错误的DOM更新 ==> 界面有问题

11. 打包后 dist 目录过大,解决办法?

1. dist打包生成的文件中有 .map 文件,可以删除。在 vue.config.js文件中配置:productionSourceMap: false

2. 组价和路由使用懒加载、按需引入等

3. 对于文件和图片进行压缩。 安装压缩组件: compression-webpack-plugin

安装后进行导入配置: 

最小化代码 minisize: true

分割代码: splitChunksl

超过限定值的文件进行压缩,threshold: 文件大小(字节为单位)

12. watch和computed的区别 

computed能完成的功能,watch都可以完成

watch能完成的小功能,computed不一定能完成。例如:watch可以进行异步操作

两个重要小原则:

1.所有被vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象

2. 所有不被vue管理的函数(定时器的回调、ajax的回调、promise的回调等),最好写成箭头函数,这样this的指向才是vm或组件实例对象

13. 跨域的解决方法

跨域:只要协议、域名和端口号有一个不相同就会产生跨域问题。同源策略是一个安全策略。同源,指的是协议,域名,端口相同。浏览器处于安全方面的考虑,只允许本域名下的接口交互,不同源的客户端脚本,在没有明确授权的情况下,不能读写对方的资源。 

 解决办法:

1.webpack 里的proxy

devServer: {
    proxy: {  //配置跨域
      '/api': {
        target: 'http://121.121.67.254:8185/',  //这里后台的地址模拟的;应该填写你们真实的后台接口
        changOrigin: true,  //用于控制请求头中的post值,默认开启
        pathRewrite: {
          /* 重写路径,当我们在浏览器中看到请求的地址为:http://localhost:8080/api/core/getData/userInfo 时
            实际上访问的地址是:http://121.121.67.254:8185/core/getData/userInfo,因为重写了 /api
           */
          '^/api': '' 
        }
      },
    }
  }

2. jsonp (需要后端支持 ) 

方案1 *:通配符,全部允许,存在安全隐患(不推荐)。

一旦启用本方法,表示任何域名皆可直接跨域请求:
  1     server {
  2         ...
  3         location / {
  4             # 允许 所有头部 所有域 所有方法
  5             add_header 'Access-Control-Allow-Origin' '*';
  6             add_header 'Access-Control-Allow-Headers' '*';
  7             add_header 'Access-Control-Allow-Methods' '*';
  8             # OPTIONS 直接返回204
  9             if ($request_method = 'OPTIONS') {
 10                 return 204;
 11             }
 12         }
 13         ...
 14     }

方案2:多域名配置(推荐)

配置多个域名在map中 只有配置过的允许跨域:

map $http_origin $corsHost {
  2         default 0;
  3         "~https://zzzmh.cn" https://zzzmh.cn;
  4         "~https://chrome.zzzmh.cn" https://chrome.zzzmh.cn;
  5         "~https://bz.zzzmh.cn" https://bz.zzzmh.cn;
  6     }
  7     server {
  8         ...
  9         location / {
 10             # 允许 所有头部 所有$corsHost域 所有方法
 11             add_header 'Access-Control-Allow-Origin' $corsHost;
 12             add_header 'Access-Control-Allow-Headers' '*';
 13             add_header 'Access-Control-Allow-Methods' '*';
 14             # OPTIONS 直接返回204
 15             if ($request_method = 'OPTIONS') {
 16                 return 204;
 17             }
 18         }
 19         ...
 20     }

3. webpack plugin (插件)

npm i -S webpack-dev-middleware  安装中间键,把前端和后端的服务绑在一起

中间件

let webpack = require('webpack')

let middle = require('webpack-dev-middleware')

let compiler = webpack(require('./webpack.config.js'))

app.use(middle(compiler))

4. cors (后端解决) 

var allowCrossDomain = function(req,res,next) {

        // 请求源

        res.header("Access-Control-Allow-Origin", "*")

        // 请求头 token

        res.header("Access-Control-Allow-Headers", "*")

        // 请求方法 get post put del

        res.header("Access-Control-Allow-Methods", "*")

        next();

}

app.use(allowCrossDomain )

14.git命令

1. git init 初始化git仓库 (mac中Command+Shift+. 可以显示隐藏文件)

2. git status 查看文件状态

3. git add 文件列表 追踪文件

4. git commit -m 提交信息 向仓库中提交代码

5. git log 查看提交记录

14.1.分支明细

(1)主分支(master):第一次向 git 仓库中提交更新记录时自动产生的一个分支。

(2)开发分支(develop):作为开发的分支,基于 master 分支创建。

(3)功能分支(feature):作为开发具体功能的分支,基于开发分支创建

14.2.分支命令

(1)git branch 查看分支

(2)git branch 分支名称 创建分支

(3)git checkout 分支名称 切换分支

(4)git merge 来源分支 合并分支 (备注:必须在master分支上才能合并develop分支)

(5)git branch -d 分支名称 删除分支(分支被合并后才允许删除)(-D 强制删除)

14.3.暂时保存更改

(1)存储临时改动:git stash

(2)恢复改动:git stash pop

 15.get与post请求有什么区别

get是从服务器上获取数据,post是向服务器传送数据。

POST比GET安全,因为数据在地址栏上不可见。

get方式提交的数据最多只能有1024字节,而post则没有此限制。

GET使用URL或Cookie传参。而POST将数据放在request BODY中。

GET与POST都有自己的语义,不能随便混用。

据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基,本可以无视。而在网 络环境差的情况下,两次包的TCP在验证数据包完整 性上,有非常大的优点。post 发送两次,get 只发送一次。

16. cookie、localStorage、sessionStorage的区别 

共同点: 都是保存在浏览器端、且同源的

不同点:

cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。

存储大小限制也不同:

cookie数据不能超过4K,sessionStorage和localStorage可以达到5M

sessionStorage:仅在当前浏览器窗口关闭之前有效;

localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;

cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭

作用域不同

sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;

localstorage:在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在

cookie: 也是在所有同源窗口中都是共享的.也就是说只要浏览器不关闭,数据仍然存在 

17.async 和 await 的区别 

区别:

async是来定义函数的,定义异步函数,打印函数名可以得到一个promise对象,言外之意可以通过这个   函数名称.then 这个方法

await 后面跟的是任意表达式,一般使用promise的表达式

async 内部实现,又返回值 成功返回promise.resolve() ,出错返回promise.reject() 返回值用catch捕获

await 等待后面的promise对象执行完毕,拿到了promise.resolve()的值之后,执行后面的代码。await后面的表达式,能是promise.reject(),所以建议await放在try....catch语句中

优点:async和await 属于es7语法。编写方便,提高程序效率,避免了回调地狱

补充:promise和async和await的区别

promise es6语法,promise中包含catch,async需要自己定义catch

promise 提供的方法会多一些,all、race等方法,aync中是没有的。 

18. 数组去重  

const removeEqual = (arr) => {
        const result = arr.filter((item, index, self) => {
                return self.indexof(item) === index
        })
        return result
} 
removeEqual([1,2,3,4,5,6,1,2,3,42,1])

 19. js的数据类型

js 数据类型分为基本数据类型和复杂数据类型

基本数据类型:Boolean、Number、String、Null、Undefined

复杂数据类型: Object、Array、Function、Date

20. js的变量提升 

在js中,变量和函数的声明会被提升到最顶部执行

函数提升高于变量的提升

函数内部如果用var声明了相同名称的外部变量,函数将不再向上寻找

匿名函数不会提升

 21. this指向

this总是指向函数的直接调用者。

如果有new关键字,this指向new出来的对象

在事件中,this指向触发这个事件的对象

22. map和forEach的区别 

forEach方法,是最基本的方法,遍历和循环。默认有3个参数:分别是遍历的每一个元素item,遍历的索引index,遍历的数组array

map方法,和foreach一致,不同的是会返回一个新的数组,所以callback需要有return返回值,如果没有会返回undefined

23. 箭头函数和普通函数的区别? 

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象

不可以当作构造函数,也就是说不可以使用new命令,否则会报错

不可以使用arguments对象,该对象在函数体内不存在,如果要用可以使用Rest参数代替

不可以使用yield命令,因此箭头函数不能用作Generator函数

24. es6新增 

新增模版字符串

箭头函数

增加let、const来声明变量

for-of用来遍历数据-例如数组中的值

解构赋值

新增简单数据类型Symbol,独一无二的,不会与其他属性名冲突

将Promise对象纳入规范,提供了原生的Promise对象

25. 数组方法汇总 

map 循环遍历数组、返回一个新的数组

forEach 循环遍历数组,不改变原数组

push/pop 在数组的末尾添加/删除元素  改变原数组

unshift/ shift 在数组的头部添加/删除元素,改变原数组

join  把数组转化为字符串

some  有一项返回为true,则整体为true

every  有一项返回为true,则整体为false

filter 数组过滤

slice(start, end)  数组截取,包括开头,不包括截取,返回一个新的数组

splice(start, number, value)  删除数组元素,改变原数组

indexof/lastindexof: 查找数组项,返回对应的下标

concat:数组的拼接,不影响原数组,浅拷贝

sort:数组排序 改变原数组

reverse: 数组反转,改变原数组

26. 项目性能优化方案 

减少http请求

减少DNS查询

使用CDN

避免重定向

图片懒加载

路由懒加载

减少DOM元素操作

使用外部js和css

压缩js、css、字体、图片等

使用iconfont字体图标、雪碧图等

避免图片的src为空

把样式表放在link中

把js放在页面的底部 

27.flex布局 

1、flex-direction 属性,决定主轴的方向(即项目的排列方向)
取值:row(默认) | row-reverse | column | column-reverse
2、flex-wrap属性,决定容器内项目是否可换行。
取值:nowrap(默认) | wrap | wrap-reverse
3、justify-content属性,定义了项目在主轴的对齐方式。
取值:flex-start(默认) | flex-end | center | space-between | space-around | space-evenly;
4、align-items属性,定义了项目在交叉轴上的对齐方式。
取值:flex-start | flex-end | center | baseline | stretch(默认)
5、flex-flow: flex-direction 和 f’lex-wrap 的简写形式。
取值:flex-flow: || ;默认值为row nowrap,没什么卵用。
6、align-content: 定义了多根轴线的对齐方式,如果项目只有一根轴线,那么该属性将不起作用。
取值: align-content: flex-start | flex-end | center | space-between | space-around | stretch; 

27. scoped的作用 

  • 当style标签拥有scoped属性时,它的CSS样式就只作用于当前的组件。也就是说,scoped可以使得组件之间的样式互相隔离,互不影响。如果一个项目中的所有style标签全部加上了scoped,就相当于实现了样式的模块化。
  • 【原理】添加scoped编译后,会给组件内所有标签元素添加一个唯一标识,这个唯一标识就是自定义属性
    data-v-xxxxxx(8个随机数)这样的字眼,同时,对应的样式选择器也会添加上这个唯一的属性选择器,由于每个组件的标识都是唯一的,意味着不会有重复的属性选择器出现,所以能够实现组件间的样式隔离。
  • 对于data-v-xxxxxx这个唯一标识,可以运行一个vue项目,f12后元素检索就能看到每个元素都带了一个这样的标识。

28. 节流和防抖? 

  • 防抖,就是在连续的操作中,无论进行了多长时间,只有某一次的操作后,在指定的时间内没有再操作,这一次才被判定为有效。(事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。)
  • 防抖的应用场景:搜索框输入关键字的过程中,实时请求服务器匹配搜索结果,如果不进行处理,输入框内容一直发生变化,导致一直发送请求。如果进行防抖处理,结果就是,当我们输入内容完成后,一定时间内(比如500ms),没有再输入内容,这时再触发请求。
  • 节流的意思是,在频繁的操作中,在规定时间内,只触发一次。比如我们设定500ms,在这个时间内,无论点击按钮多少次,它都只会触发一次。
  • 节流的应用场景:1.抢购的时候,无数人快速的点击按钮,如果每次点击都发送请求,就会给服务器造成巨大的压力,但是我们进行节流后,就会大大减少请求的次数。2.防止表单提交按钮被多次触发,我们应该选择使用节流而不是防抖。3. 滚动加载,加载更多或滚到底部监听。

 29. 内存泄漏如何处理?

  1. 内存泄漏就是指由于疏忽或者程序的某些错误造成未能释放已经不再使用的内存的情况。简单来讲就是假设某个变量占用100M的内存,而你又用不到这个变量,但是这个变量没有被手动的回收或自动回收,仍然占100M的内存空间,这就是一种内存的浪费,就是内存泄漏。(内存泄漏是指在程序运行时,申请的内存空间没有被及时释放,导致程序占用的内存不断增加,最终可能导致系统崩溃或变得非常缓慢。)
  2. 在前端开发中,内存泄漏可能会发生在 js代码中。例如,在使用闭包时,如果闭包中引用了外部函数的变量,而这个外部函数已经执行完毕,但是闭包依然存在,那么这个外部函数占用的内存就无法被释放,可能导致内存泄漏。
  3. 为了避免内存泄漏,开发人员应该及时释放不再使用的变量和资源,避免出现循环引用等情况,并使用一些工具和技术来检测和解决内存泄漏问题。
    (1) 绑在 EventBus 的事件没有解绑
    (2)全局变量造成的内存泄露,声明的全局变量在切换页面的时候没有清空。
    (3)遗忘的定时器
    (4)控制台的打印
    (5)闭包使用不当引起内存泄漏
    (6)v-if 指令产生的内存泄露

 30. 谈谈你对浅拷贝和深拷贝的理解?

  1. 浅拷贝就是通过赋值的方式进行拷贝,只拷贝对象的引用,是对指针的拷贝,拷贝后两个指针指向同一个内存,同一份数据,意味着当原对象发生变化的时候,拷贝对象也跟着变化。
  2. 深拷贝:不但对指针进行拷贝,而且还对指针指向的内容进行拷贝,也就是另外申请了一块空间内存,内容和原对象一致,但是是两份独立的数据,更改原对象,拷贝对象不会发生变化。

 深拷贝的实现方式:

(1) js内置对象的JSON对象的序列化和反对象化方法:JSON.parse + JSON.stringify;

(2) 使用递归实现深拷贝。a. 传入的原对象,遍历其属性,每个属性需要判断它的值是否是object类,如果不是,说明是基本数据类型,可以直接赋值;b. 如果是object类,那么需要再具体判断这个数据是对象还是数组,是数组创建一个空数组[],是对象则创建一个空对象{},继续递归。

(3) loadash是一个很热门的函数库,我们引入这个库后,就可以直接使用这个方法了,但是如果项目本身没有引入这个库,就不要为了使用深拷贝专门引入整个库,这样有点得不偿失。

(4) Object.assign(target,…sources) ES6新增的方法可以实现深拷贝,target: 拷贝给谁。 sources: 拷贝的对象。

(5) ...展开运算符。拷贝一层是深拷贝,但是修改对象里数组的某一项就会受影响,说明是浅拷贝;

(6) arr.concat() 方法。只深拷贝最外层,修改数组里的对象就会受影响,是浅拷贝。

(7) arr.slice() 方法。只深拷贝最外层。

31. get请求和post请求的区别 

  1. get请求的参数是拼接在地址栏中,隐私性和安全性都比较差,请求的数据长度是有限制的,
    不同的浏览器和服务器不同,一般限制在 2~8K 之间,更加常见的是 1k 以内;post请求是没有的长度限制的,请求数据是放在body中。
  2. get请求一般是去取获取数据(也可以提交,但常见的是获取数据);post请求一般是去提交数据。
  3. get请求刷新服务器或者回退没有影响,post请求回退时会重新提交数据请求。
  4. get请求可以被缓存,post请求不会被缓存。
  5. get请求会被保存在浏览器历史记录当中,post不会。get请求可以被收藏为书签,因为参数就在url中,但post不能。post请求的参数不在url中。
  6. get请求只能进行url编码(appliacation-x-www-form-urlencoded),post请求支持多种(multipart/form-data等)。

32. js的数据类型 

  1. is中数据类型分为基本数据类型和引用数据类型。
  2. 基本数据类型有Number,String,Boolean,Null,Undefined,es6新增的Symbol以及es10新增的Biglnt(任意精度整数)七类。
  3. 引用数据类型即obiect类,比如对象数组,以及函数。
  • 存储位置:基本类型存储在栈内存中而引用数据类型在栈内存中存的是对象指针,这个指针指向堆内存中的值,也就是说实际值是存在堆内存中,栈中存的是对象在堆内存中的引用地址,通过这个引用地址可以找到保存在堆内存中的对象。如果两个变量保存的是同一个地址值,说明指向的是同一份数据,当一个变量修改属性时,另一个也必然会受到影响。

33. TCP的三次握手、四次挥手?

  • 首先我们要知道建立连接的目的是什么,我们是为了可靠的传输数据。那既然是可靠的传输数据,我们必须保证客户端和服务端都能正常的发送和接收数据,如果某一方不能正常的发送或者接收数据,那整个数据的传输就不能成功,也就不可靠。

三次握手

  1. 第一次握手:第一次握手是客户端发送同步报文到服务端,这个时候客户端是知道自己具备发送数据的能力的,但是不知道服务端是否有接收和发送数据的能力;
  2. 第二次握手:当服务端接收到同步报文后,回复确认同步报文,此时服务端是知道客户端具有发送报文的能力,并且知道自己具有接收和发送数据的能力,但是并不知道客户端是否有接收数据的能力;
  3. 第三次握手:当客户端收到服务端的确认报文后,知道服务端具备接收和发送数据的能力,但是此时服务端并不知道自己具有接收的能力,所以还需要发送一个确认报文,告知服务端自己是具有接收能力的。

 四次挥手

  1. 第一次挥手客户端发起关闭连接的请求给服务端;
  2. 第二次挥手:服务端收到关闭请求的时候可能这个时候数据还没发送完,所以服务端会先回复一个确认报文,表示自己知道客户端想要关闭连接了,但是因为数据还没传输完,所以还需要等待;
  3. 第三次挥手:当数据传输完了,服务端会主动发送一个 FIN 报文,告诉客户端,表示数据已经发送完了,服务端这边准备关闭连接了。
  4. 第四次挥手:当客户端收到服务端的 FIN 报文过后,会回复一个 ACK 报文,告诉服务端自己知道了,再等待一会就关闭连接。

为什么握手要三次,挥手却要四次?

  1. 因为握手的时候并没有数据传输,所以服务端的 SYN 和 ACK 报文可以一起发送,但是挥手的时候有数据在传输,所以 ACK 和 FIN 报文不能同时发送,需要分两步,所以会比握手多一步。

为什么客户端在第四次挥手后还会等待 2MSL?

  1. 等待 2MSL 是因为保证服务端接收到了 ACK 报文,因为网络是复杂了,很有可能 ACK 报文丢失了,如果服务端没接收到 ACK 报文的话,会重新发送 FIN 报文,只有当客户端等待了 2MSL 都没有收到重发的 FIN 报文时就表示服务端是正常收到了 ACK 报文,那么这个时候客户端就可以关闭了。

 34. localStorage、sessionStorage、cookie?

共同点

  1. SessionStorage, LocalStorage, Cookie三者都可以被用来在浏览器端存储数据,而且都是字符串类型的键值对。 区别在于,前两者属于WebStorage,创建它们的目的便于客户端存储数据。 而Cookie早在网景公司的浏览器中就开始支持,最初目的是为了保持HTTP的状态。

区别

  1. 存储大小上的区别
    cookie:一般不超过4K(因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识)
    localStorage和sessionStorage:5M或者更大
  2. 数据的有效时间不同
    cookie : 设置的cookie过期时间之前一直有效,存放在硬盘里,过期才失效即使窗口或浏览器关闭;
    localStorage : 永久存储,浏览器关闭后数据不丢失,除非手动永久清除,因此用作持久数据;
    sessionStorage :生命周期是数据在当前浏览器窗口关闭后自动删除。
  3. 数据与服务器之间的交互方式不同
    cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端;
    sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存;
  4. 易用性上的差别
    cookie :源生的cookie接口不友好 ,需要程序员自己封装。
    sessionStorage和localStorage源生接口可以接受也可再次封装来对Object和Array有更好的支持。
  5. 应用场景
    cookie:判断用户是否登录过网站,以便实现下次自动登录或记住密码;保存事件信息等
    localStorage:常用于长期登录(判断用户是否已登录),适合长期保存在本地的数据

35.vue2和vue3的区别?

  1. vue2和vue3双向数据绑定原理发生了改变。
    vue2 的双向数据绑定是利用ES5 的一个 API Object.definePropert()对数据进行劫持 ,结合发布订阅模式的方式来实现的。vue3 中使用了 es6 的 ProxyAPI 对数据代理。
  2. Vue3支持碎片(Fragments),就是说在组件中可以拥有多个根节点。
  3. Vue2与Vue3 最大的区别 — Vue2使用选项类型API,Vue3合成型API。旧的选项型API在代码里分割了不同的属性: data,computed属性,methods,等等。新的合成型API能让我们用方法(function)stup(){}来分割,相比于旧的API使用属性来分组,这样代码会更加简便和整洁。
  4. 建立数据 data。Vue2把数据放在data中,在Vue3中,我们就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。
  5. 使用以下三步来建立反应性数据:
    1. 从vue引入reactive
    2. 使用reactive()方法来声名我们的数据为响应性数据
    3. 使用setup()方法来返回我们的响应性数据,从而我们的template可以获取这些响应性数据

36. 什么是虚拟DOM?

  1. 在Vue中,虚拟DOM(Virtual DOM)是一个轻量级的JavaScript对象,用于描述真实DOM的层次结构和属性。每当Vue组件的数据发生变化时,Vue会先对虚拟DOM进行操作,然后再将变化的部分同步到真实DOM中,从而避免了直接操作真实DOM时的性能问题。
  2. 虚拟DOM的出现是为了解决传统前端开发中频繁操作真实DOM的问题。由于真实DOM的操作往往非常消耗性能,因此频繁操作会导致页面的性能问题。而虚拟DOM可以在内存中对DOM进行操作,只有在必要的时候才将变化同步到真实DOM,从而避免了频繁操作真实DOM的性能问题。
  3. 具体来说,当Vue组件的数据发生变化时,Vue会通过比较新旧虚拟DOM树的差异来确定需要更新的部分,并将这些部分同步到真实DOM中。这样就避免了不必要的DOM操作,从而提高了页面的性能和响应速度。
  4. 此外,虚拟DOM还可以方便地实现一些高级特性,例如组件的复用和动画效果。虚拟DOM使得Vue可以在不操作真实DOM的情况下实现这些功能,从而提高了开发效率。

37. vue 组件之间的通信

 1、父传子:父组件通过自定义属性传递给子组件,子组件中通过props接收父组件中的绑定的属性
2、子传父:子组件通过广播的方式 e m i t 发送自定义事件,将值传递给父组件,父组件监听事件,触发一个函数去接收子组件中传递过来的值。

3 、兄弟间传值:

         ( 1 ) 通过父组件中转来传值,即 A 和 B 是兄弟组件,可以 A 传给父组件,由父组件再传给 B

        ( 2 ) n e w 一个 B u s 实例,在需要发送数据的组件中自定义方法,通过 emit发送自定义事件,将值传递给父组件,父组件监听事件,触发一个函数去接收子组件中传递过来的值。

3、兄弟间传值:

        (1)通过父组件中转来传值,即A和B是兄弟组件,可以A传给父组件,由父组件再传给B

        (2) new一个Bus实例,在需要发送数据的组件中自定义方法,通过 emit发送自定义事件,将值传递给父组件,父组件监听事件,触发一个函数去接收子组件中传递过来的值。

3、兄弟间传值:

        (1)通过父组件中转来传值,即A和B是兄弟组件,可以A传给父组件,由父组件再传给B

        (2)new一个Bus实例,在需要发送数据的组件中自定义方法,通过emit传递数据,在需要接收数据的组件生命周期created中,通过$on监听获取数据。

        (3) 使用vuex状态管理,可以实现数据的随意存储和获取。

38.  vuex状态管理工具的五个核心属性? 

  • state: 用来存储公共数据的(变量),类似于组件中的data。
  • mutations:数据修改的逻辑,也是唯一修改state数据的地方。(提交更新数据的方法),它必须是同步操作,如果有异步操作的话,那么就需要actions。
  • actions:它也是用来改变数据的,但是它无法直接修改数据,actions提交的是mutations,在mutations里面更改数据,actions支持异步操作。
  • getters:从基本数据,派生过来的数据,相当于组件里的计算属性computed。
  • modules:是用来模块化vuex的,可以让每一个模块拥有自己的state、mutation、actions、getters使得结构更加清晰,方便管理。

39. vue生命周期有哪些?

创建阶段: 只执行一次。
    beforeCreate(开始进行一些数据和方法的初始化的操作, data 中的数据和 methods 中的方法还不能用)。
    created(已经完成数据和方法的初始化, data 中的数据和 methods 中的方法可以使用了)。
挂载阶段:
    beforeMount(开始渲染虚拟 DOM)。
    mounted(已经完成了虚拟 DOM 的渲染, 可以操作 DOM 了, 只执行一次)。
更新阶段: 执行多次
    beforeUpdate(data 中的数据即将被更新, 会执行多次)。
    updated(data 中的数据已经更新完毕, 会执行多次)。
销毁阶段: 只执行一次
    beforeDestroy(vue 实例即将销毁, 此时 data 中的数据和 methods 中的方法依然处于可用状态)。
    destroyed(vue 实例已经销毁, 此时 data 中的数据和 methods 中的方法已经不可用)。

40. 说三种刷新页面的方式?

  1. 原生js方式:location.reload(),我们只需要在需要刷新的地方加这么一行代码即可做到刷新。
  2. 借助Vue中的路由跳转方式:如果需要刷新,则写入 this.$router.go(0),这个方法解释一下,就是我们要跳转路由,而需要跳转的页面就是本页面,所以是go(0),这样就可以做到页面的重新加载。
  3. provide / inject 组合方式。前两种方法都是强制刷新,页面会出现短暂空白,而provide/iniect 是普通刷新,不会使页面出现空白。这个方法,允许一个祖先组件通过provide向其所有子孙后代提供数据,不论组件层次有多深,子组件都可以通过inject来注入,接收这个数据。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值