总结

88 阅读19分钟

VUE总结

1.vue的组件通信有几种方式

通信方向通信方式建议
1、父向子通信通过props传递数据单向传递、不要修改数据
2、子向父通信通过$emit()自定义一个回传事件父组件绑定事件
3、父子间通信通过this.$parentthis.$children指向父子组件数据容易混乱数据流向,后期溯源不易,且用且珍惜
4、父子通信通过this.$refs指向组件的实例对象
5、父王通信父组件通过provide声明,子组件谁要谁通过inject获取provide玉玺,inject抢玉玺,一对多,无论后代嵌套多深都能获取
6、全局事件总线eventbus常量;eventbus.$emit()传递数据、on()获取数据、on()获取数据、off()移除事件
7、attrsattrs和listeners通过$attrs可以获取到非props的属性(父组件中传递:value传递的数据,没在prop中接收的属性,通过inheritAttrs为false的配置之后,能通过attrs获取到父组件非prop数据vue3有更新

vue中8种组件通信方式, 值得收藏! - 掘金 (juejin.cn)

2.VUE的nextTick用法和底层原理

3.vue-router的使用和原理

1.引入 import VueRouter from 'vue-router'

2.声明使用 Vue.use(VueRouter);

3.new 一个路由对象 export default new VueRouter({ mode: 'history', routes: getRouter(), });

4.路由懒加载

   使用resolve 异步加载 页面,加载首页之后,只会按需加载。减少资源的占用。
   因为 使用resolve 加载组件,打包后 每个component 都会生成一个JS ,这样就能实现按需引入。

5.axios总结

标题
1、基于promise的网络请求库,多请求可以用 promise.all(a,b)
2、需要使用 要先引入资源 npm/yar/bar i axios 或者单独url引入网络资源
3、可以使用 axios({config}).then().catch 的方式使用,也可以使用api axios.get()/axios.post()
4、支持在请求、响应、报错配置拦截器,在响应前做操作
请求拦截:axios.interceptors.request.use(confit=>{},error=>{})
响应拦截:axios.interceptors.response.use(config=>{},error=>{})
5、引入后 可直接使用 axios命令,也可以创建一个axios实例,let a = axios.create()
6、可以给axios配置默认 的baseurl,url ,method

请求配置 | Axios 中文文档 | Axios 中文网 (axios-http.cn)

6.flex布局总结

  • Flex布局以后,子元素的float、clear和vertical-align属性将失效

flex布局=> display:flex

布局方向: flex-direction : column/row/row-reverse/column-reverse

换行方式: flex-wrap:nowrap/wrap/wrap-reverse

主轴对齐方式:justify-content:flex-start/flex-end/center/space-between/

交叉轴对齐方式:align-items:flex-start/flex-end/center [Flex 布局语法教程 | 菜鸟教程 (runoob.com)]

(www.runoob.com/w3cnote/fle…)

7.vue项目结构中assets和static的分别

不同点

  • 使用 npm run build 走webpack 打包时,会将assets中的静态文件和样式进行打包,而static中文件则直接复制到 dist文件中。 【所以打包后assets 文件更小】
  • 引用assets 目录下文件,需要用 关键字 require引用图片,因为webpack使用的是 commonJS 规范。

相同点

  • assets目录和static目录都是 存放 静态文件和css 样式文件

8、vue中watch和computed的区别

  • watch能够支持异步方法,数据有改变就会调用一次
  • computed不支持异步,且数据计算一次之后会缓存,而后在其他地方调用不需要重新计算

详解Vue中的computed和watch - 掘金 (juejin.cn)

9、vue中各个生命周期

生命周期操作数据
beforeCreated实例还未初始化
created实例初始化,可以访问到data数据和methods方法
beforeMounted页面未渲染,dom结构还未创建
mouteddom结构已经创建完成,还没有挂载
beforeUpdated数据还未更新,可以获取所有的状态
updated数据已更新
beforeDestroy可以取消订阅和定时器
destroy组件销毁
  • 数据请求在created和mounted中有什么区别
    • 在created和mounted中都能访问到数据
    • 在mounted中执行异步操作请求数据,这时的dom结构已经渲染完成,有可能会导致页面闪动

10、vue中的data为什么是一个函数而不是一个对象?

  • 在根实例中可以是一个函数也可以是一个对象
  • 在组件中的data只能够是一个函数,因为引入多个组件的情况下,vue会使用extend()方法构造组件实例,如果是一个对象,就会导致每声明一个组件data数据指向的地址都是同一个,污染组件间的数据。所以需要写成函数的形式,每次返回都是一个新的内存地址

11、vue中数据更新但是页面不刷新是什么情况?

  • 响应式的原理
    • vue2中是使用了object.definePropety方法来设置setter和getter方法来实现数据响应的
  • 为什么会这样呢
    • 因为vue2中绑定响应式数据,在数据初始化时就已经绑定了,所有后面新增的方法如果没有经过object.definePropted设置响应式,就会出现数据更新,页面不刷新的情况
  • 解决办法
    • Vue.$set 修改数据
    • 使用Object.asset或者数组带的方法
    • $forceUpdated进行强制刷新

12、vue中mixin的理解

  • mixin是将vue组件中,可以进行复用的代码抽离,单独写成一个mixin.js的混入文件。方便复用到多个组件中,提高开发效率,降低后期维护成本
  • mixin具备实例的所有的生命周期,当mixin中的生命周期或者数据方法与组件实例中的重复时,这个时候会先执行mixin中的方法和数据,再取实例中的方法和数据进行覆盖
  • 单个组件可以局部混入,全局js可以全局引入

13、什么是跨域?怎么解决跨域问题

  • 是什么呢?

    • 跨域也叫同源限制,是浏览器的对不同主机、不同端口、不同协议信息的一种限制。
    • 所以会出现使用postman或者抓包工具,能够获取到数据。但是通过浏览器拿不到数据的情况
  • 怎么解决跨域问题?

    • 后端解决,在HTTP头中添加信息。允许访问
    • Proxy代理
      • 用脚手架搭建的项目,可以使用webpack在项目本地起一个服务代理请
              devServer: {
      host: '127.0.0.1',
      port: 8084,
      open: true,// vue项目启动时自动打开浏览器
      proxy: {
          '/api': { // '/api'是代理标识,用于告诉node,url前面是/api的就是使用代理的
              target: "http://xxx.xxx.xx.xx:8080", //目标地址,一般是指后台服务器地址
              changeOrigin: true, //是否跨域
              pathRewrite: { // pathRewrite 的作用是把实际Request Url中的'/api'用""代替
                  '^/api': "" 
              }
          }
      }
          }
              }
      
      • 使用express搭建一个本地服务代理转发请求
          const proxy = require('http-proxy-middleware')
          const app = express()
          app.use(express.static(__dirname + '/'))
          app.use('/api', proxy({ target: 'http://localhost:4000', changeOrigin: false
                    }));
          module.exports = app
      
      • 使用nginx代理转发
          listen    80;
          # server_name www.josephxia.com;
          location / {
              root  /var/www/html;
              index  index.html index.htm;
              try_files $uri $uri/ /index.html;
          }
          location /api {
              proxy_pass  http://127.0.0.1:3000;
              proxy_redirect   off;
              proxy_set_header  Host       $host;
              proxy_set_header  X-Real-IP     $remote_addr;
              proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
          }
      }
      

14、vue部署服务器后刷新页面变成404的原因

  • 原因

    • 因为使用的是history模式来做路由跳转,在重新部署服务器之后,在nginx配置中没有配置重定向页面,这就导致可能是在子页面,但重新刷新去服务器获取index页面的时候指向的资源不存在。
  • 知识点

    • 需要明确的就是,配置路由有两种方式 history模式和hash模式
    • history模式下,没有#号,更美观
    • hash模式下,带有#号,在获取页面时只会向服务器发送#号前的地址,所以在刷新的时候不会404
  • 解决办法

    • 需要在配置nginx代理的时候,多配置重定向的访问路径
    • 同时也需要在前端代码中配置重定向的访问路径

15、vue中要做权限管理需要怎么做

  • 权限管理分成
    • 接口管理
      • 需要结合axios进行控制,在请求拦截器中添加token信息;让后台判断是否具有权限,没有权限在响应拦截器中跳转登录页,重新登录
    • 路由管理
      • 需要结合全局路由守卫实现,需要把用户权限信息和配对路由都配置在前端文件中,在Router.beforeEach 中获取用户信息与配置信息比对,具备权限的用户通过addRows添加最新路由,跳转
    • 菜单管理
      • 需要结合全局路由守卫和后端配合实现,需要后端将当前用户具备的权限返回,再通过addRows添加最新路由
    • 按钮权限管理
      • 需要自定义指令,在需要权限控制的按钮上添加指令。用户信息可以存在vuex或本地缓存中

16、 什么是虚拟DOM

  • 是什么
    • 用js来对真实DOM结构的一个抽象,可以理解成js描绘的DOM结构树
  • 为什么需要一个虚拟DOM
    • 首先需要明确的是,真实的dom包含有许多的属性和元素,内容是非常多的。这个时候如果单纯的直接操作dom结构,对性能会有很大的影响,容易造成页面的卡顿
    • 有了虚拟dom在操作dom节点的时候,不会直接一次又一次的向dom节点树增加或者删除节点,而是使用diff算法判断出一个差异的js对象,一次性更新到dom树上,减少对dom的操作,节约性能,增强用户体验

17、说说vue中的diff算法

  • 是什么
    • diff其实是用来做dom节点变化对比的一个算法
  • diff的对比机制
    • 首指针下标对比法:同层节点进行对比,新旧节点首尾都有一个下标index,用旧的首下标和新的首尾比较,有相同的复制使用,没有就使用旧尾下标比较。

18、使用过axios吗?一般都做一些什么操作

  • 是什么

    • 是一个轻量级的http客户端,内部封装了常用的请求方法和配置方法。
    • 封装axios来进行接口调用,能够更好管理接口,可以封装一些通用的信息,减少后期维护成本
  • 一般封装都做什么

    • 首先可以根据node环境变量来替换不同的请求地址,就不需要再手动维护了
    • 然后还可以配置通用的请求头信息、超时时间等
    • 可以在请求拦截器中添加token和其他需要的信息
    • 在响应拦截器中对返回的状态码判断跳转不同的页面

19、用过自定义指令吗?使用场景有哪些

  • 是什么

    • vue提供了directive方法能够自己把常用的方法封装出来做成一个指令,像v-show和v-if就是内置指令,自定义指令使用方法和内置指令一样
    • 可以分成全局声明的自定义指令和局部注册的指令
    • 自定义指令也有自己的钩子函数:
      • bind:第一次调用时执行的方法
      • inserted:绑定元素插入到父节点时调用
      • update:虚拟dom更新时调用
      • unbind:卸载时调用
      • componentUpdated:所有组件虚拟dom更新时调用
    • 钩子函数中的参数
      • el:dom节点
      • binding:可以获取到name,传的值等
  • 使用场景

    • 节抖指令
    • 拖拽指令
    • 聚焦指令
    • 拷贝指令

Vue实现自定义指令(directive)及应用场景 - 掘金 (juejin.cn)

20、说说v-for中key的作用

  • 为什么需要key呢
    • 在渲染dom之后可能会对dom结构有增删改的场景,这个时候如果能够判断新旧虚拟dom改变的最小差量,尽可能复用原有的dom,可以减少渲染需要的性能。所以key值的作用就是作为一个唯一id标识值,来判断新旧虚拟dom的变化情况
    • 且key值最好是取唯一标识,不要给index下标值,如果是给下标值,一个数据的变动会影响到整个结构的key值。

21、vue中首屏渲染过慢怎么优化?

  • 过慢的原因

    • 访问的资源过大
    • 发送的请求太多
    • 网络延迟
    • 加载脚本时渲染内容堵塞
  • 解决办法

    • 主要是分成两方面:1、资源加载优化 2、页面渲染优化

    • 资源加载优化

      • 压缩图片
      • 使用路由懒加载减小入口文件大小
      • 对一些访问资源可以使用本地缓存
      • 一些ui资源按需引入
    • 页面渲染优化

22、服务器渲染和客户端渲染的了解和实现

  • 浏览器页面渲染的过程
    • 1、浏览器请求的得到一个HTML文本

    • 2、进渲染程对得到的文本解析,生成DOM树

    • 3、同时对需要用到的CSS样式解析,生成需要的样式规则;如果遇到js脚本,下载执行脚本

    • 4、将DOM树和样式表合并,生成渲染树

    • 5、渲染进程将渲染树进行布局,生成布局树

    • 6、得到布局树后,进行绘制得到绘制记录,再栅格化分层得到合成帧,通过GPU将合成帧渲染到浏览器页面上

image.png

  • 服务端渲染过程

    • 1、浏览器请求页面
    • 2、服务器向后端服务请求从数据库获取数据,组装成HTML文本,返回给浏览器
    • 3、浏览器根据HTML渲染页面,再请求js脚本,服务器返回js脚本
    • 4、浏览器执行js脚本,绑定页面事件,同时向后端请求接口数据
    • 5、拿到后端返回数据,浏览器动态渲染页面
  • 客户端渲染对比服务器渲染

    • 白屏时间:客户端渲染请求页面得到的只是一个空的HTML文档,还需要执行js脚本向后台服务请求数据之后,才能动态渲染页面,这就会加大白屏时间

什么是服务端渲染 - 知乎 (zhihu.com)

JS总结

1、ajax的原理和实现

  • 是什么?
    • 利用XMLHttpRequest对象,发送异步请求HttpRequest到服务器,再返回请求数据给浏览器更新DOM。
  • 怎么实现?
    • 创建xmlHttpRequest对象
    • 使用open()方法建立连接后,使用send()方法发送携带报文
    • 绑定onreadystatechange事件,监听服务器返回报文
  • 封装
//封装一个ajax请求
function ajax(options) {
    //创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()


    //初始化参数的内容
    options = options || {}
    options.type = (options.type || 'GET').toUpperCase()
    options.dataType = options.dataType || 'json'
    const params = options.data

    //发送请求
    if (options.type === 'GET') {
        xhr.open('GET', options.url + '?' + params, true)
        xhr.send(null)
    } else if (options.type === 'POST') {
        xhr.open('POST', options.url, true)
        xhr.send(params)

    //接收请求
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            let status = xhr.status
            if (status >= 200 && status < 300) {
                options.success && options.success(xhr.responseText, xhr.responseXML)
            } else {
                options.fail && options.fail(status)
            }
        }
    }
}

2、apply、bind、call方法的区别?

  • 相同点
    • 都能够通过绑定当前this改变函数的指向
    • 第一个入参都是this,当不传时该参数默认为undefined或null,则默认指向全局window
  • 不同点
    • apply 接收参数为数组形式、bind 接收参数列表、call也接收参数列表
    • apply和call是立即执行,而bind会返回一个绑定this之后的函数
  • 手写bind

3、事件循环机制的理解

  • 为什么需要事件循环?
    • js是一个单线程的脚本语言,面对多线程的操作时,可能会报错,由此引入事件循环机制。
  • 任务分类
    • 按任务分为 同步任务和异步任务
    • 异步任务又细分 宏任务和微任务。常见微任务为 promise.then 和 nextTick ,宏任务为定时任务和输入输出事件
  • 执行顺序
    • 先执行主线程中的同步任务,执行完后查看任务队列执行 异步任务。在异步任务中先执行微任务,最后查看事件队列是否有宏任务,执行宏任务

image.png

  • aysnc 和 await
    • aysnc声明一个异步方法,await等待异步执行,阻塞后面代码,会加入微任务队列中

4、js中内存泄漏的几种情况

  • 是什么?
    • 开辟的内存空间没有得到释放,导致内存堆积。由此提出垃圾回收机制,自动回收开辟内存
  • 垃圾回收机制
    • 标记清除:将所有标记清除的变量从内存销毁
    • 引用计数:计数为零的会回收
  • 常见内存泄漏
    • 定时器不清理
    • 闭包引用外部变量
    • 事件监听addeventlistenr,在不监听时需要取消对监听
    • 没有清理对dom元素的引用

5、js本地缓存方式有哪些?区别和场景

  • 主要包含
    • cookie:主要支持用户身份信息的存储。支持小数据量,每次发送请求会携带cookie信息。如果不使用HTTPS加密,保存的信息容易被窃取后伪装身份。配置项:expires、max-age、domain、path。到达过期时间,浏览器会自动删除,在有效时间内,窗口关闭也会保存信息
    • sessionStorage:持久化本地缓存,基本限制5M,关闭会话内容就删除。同个域名下会话信息会拷贝一份,但不会同步修改。
    • localStorage:持久化的本地缓存,只要不手动删除都会存储在浏览器。基本限制5M,同一域下信息共享,受同源策略限制。
    • indexedDB:支持大数据量存储

6、防抖和节流的区别和实现

  • 防抖:在同一时间内多次调用但是只执行最后一次。输入框输入数据检索,resize触发事件
  • 节流:同一时间内多次调用,每到指定时间就执行一次。输入框联想功能,滚动条触底事件

image.png

7、大文件上传和断点续传的实现

  • 实现方法有两种
    • 分片上传:利用blob的slice方法,切分文件,将大文件按照一定大小,切割成相同大小的数据块,将数据块发送到服务器,每个切片包含切片最大数量,在服务器合并成一个文件。
    • 断点续传:在上传或下载时,将文件分为几个部分。每个部分分一个线程进行或下载,如果遇到网络故障,下次上传下载时从中断位置开始。节省时间提高速度。二次上传可以获取临时文件大小,作为客户端读取文件的偏移量,从当前位置开始上传。
  • 使用场景
    • 大文件加速上传,切片后并行上传,提高速度
    • 网络环境较差:分片上传。出现上传失败,只需重传失败分片
    • 流式上传:文件大小还不确定时就开始上传。监控画面
  • 实现

8、什么是单点登录?怎么实现

  • 是什么呢?
    • 单点登录能够整合企业业务方案,只需要登录一次就能够访问所有互相信任的应用系统,简称SSO
    • 需要一个单独的认证中心,所有的系统登录操作,都从认证中心通过。应用系统不再参与登录操作
    • 一个应用系统登录成功后,sso会颁发令牌给各个子系统,在一定时间内不需要再次认证
  • 实现过程
    • 同域名下的单点登录
      • 同域名下会简单一些,将cookie的domain设置为主域名,path设置为根路径,然后将token等身份信息保存在主域名下。这样所有的子域名就都能访问到cookie信息。例如,tieba.baidu.com 和 map.baidu.com,它们都建立在 baidu.com 这个主域名之下,那么它们就可以通过这种方式来实现单点登录。
    • 不同域名下单点登录---标准做法
      • 应用系统1未登录时,请求URL中不带token参数,会重定向到认证中心的登录页面
      • 登录成功后生成token,写入cookie,在URL中携带token重定向到应用系统页面
      • 在应用系统1中登录,想要打开应用系统2的页面,会带着token信息向认证中心确认是否登录,通过就跳转到应用系统2页面
    • 不同域名单点登录 二----前端实现
      • 前端将后端返回的token信息存储到localStorage中,之后的请求都带上localStorage的信息做验证
      • 当跨不同页面,涉及多个域时,通过iframe和postMessage()方式,将同一份token写入多个域名下的localstorage,从而完成身份验证,实现单点登录

面试官:什么是单点登录?如何实现? · Issue #91 · febobo/web-interview · GitHub

9、如何判断元素是否在可视区域

  • 区分offset、client、scroll三个属性
    • offsetWidth:外边距+内边距+内容
    • clientWidth:内边距+内容
    • scrollWidth:内边距+内容
  • 设置滚动状态
    • 通过scrollLeft和scrollTop确定和设置当前滚动状态
    • 垂直滚动 scrollTop >0 ,水平 scrollLeft > 0。都设置为0,可以重置元素的滚动位置
  • 判断是否在视图窗口内,getBoundingClientRect
    • top大于等于0,left大于等于0,buttom小于等于视图高度,right小于等于视图宽度
    • 可以利用getBoundingClientRect()方法,获取元素的left,top,right,bottom,x,y,width,height八大属性。
  • 判断元素是否重叠 interSectionObserve
    • 使用步骤主要分为两步:创建观察者和传入被观察者

JavaScript的offset、client、scroll三大系列总结 - 清风编程 (qingfengedu.com)

10、深拷贝和浅拷贝的区别?如何实现深拷贝

  • 区别
    • 深拷贝:对于基础数据会拷贝一份数据,引用数据类型会开辟新内存地址存储数据。
    • 浅拷贝:基础类型数据会拷贝一份,引用数据类型会使用相同的指针指向同一个内存地址
    • 基本数据类型都是一样的,引用数据类型浅拷贝拷贝内存地址指针,深拷贝拷贝一份数据
  • 浅拷贝现象
    • Object.assign()
    • array.prototype.slice , array.prototype.concat()
    • 拓展运算符 [...]
  • 深拷贝现象
    • _.cloneDeep()
    • jq.extend()
    • json.stringify() ,会自动胡烈undefined,symbol和function
    • 手写循环递归

11、js的数据类型?

  • 七种数据类型
    • 基础数据:string、number、boolean、undefined、null、symbol
    • 引用数据类型:object

12、js数组常用的方法有哪些?

  • 增 是否影响原数组
    • push() √
    • unshift() √
    • concat() × 返回新数组
    • slice() √
    • pop() √
    • shift() √
    • slice() √
    • slice() × 创建一个新数组
    • splice() √
    • indexOf() 返回下标,没有返回-1
    • includes() 返回true/false
    • find() 返回找到的元素
  • 排序
    • reverse() 反转数组
    • sort()
  • 迭代方法
    • some() ---返回true/false
    • every() ----true、false
    • filter() ----返回符合条件数组
    • Map() ---返回调用结果数组
    • forEach() --- 没有返回值

13、typeof和instanof的区别

  • typeof返回的是数据类型的字符串,除了对null判断为object之外,能够对基本数据类型进行准确判断,对引用数据类型返回都是object,对函数返回function
  • instanof返回布尔值,是在检测构造函数的prototype是否出现在实例对象原型链上,可以准确的判断引用数据类型。