VUE总结
1.vue的组件通信有几种方式
| 通信方向 | 通信方式 | 建议 |
|---|---|---|
| 1、父向子通信 | 通过props传递数据 | 单向传递、不要修改数据 |
| 2、子向父通信 | 通过$emit()自定义一个回传事件 | 父组件绑定事件 |
| 3、父子间通信 | 通过this.$parent和this.$children指向父子组件数据 | 容易混乱数据流向,后期溯源不易,且用且珍惜 |
| 4、父子通信 | 通过this.$refs指向组件的实例对象 | |
| 5、父王通信 | 父组件通过provide声明,子组件谁要谁通过inject获取 | provide玉玺,inject抢玉玺,一对多,无论后代嵌套多深都能获取 |
| 6、全局事件总线 | eventbus常量;eventbus.$emit()传递数据、off()移除事件 | |
| 7、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)]
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结构还未创建 |
| mouted | dom结构已经创建完成,还没有挂载 |
| 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将合成帧渲染到浏览器页面上
-
-
服务端渲染过程
- 1、浏览器请求页面
- 2、服务器向后端服务请求从数据库获取数据,组装成HTML文本,返回给浏览器
- 3、浏览器根据HTML渲染页面,再请求js脚本,服务器返回js脚本
- 4、浏览器执行js脚本,绑定页面事件,同时向后端请求接口数据
- 5、拿到后端返回数据,浏览器动态渲染页面
-
客户端渲染对比服务器渲染
- 白屏时间:客户端渲染请求页面得到的只是一个空的HTML文档,还需要执行js脚本向后台服务请求数据之后,才能动态渲染页面,这就会加大白屏时间
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 ,宏任务为定时任务和输入输出事件
- 执行顺序
- 先执行主线程中的同步任务,执行完后查看任务队列执行 异步任务。在异步任务中先执行微任务,最后查看事件队列是否有宏任务,执行宏任务
- 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触发事件
- 节流:同一时间内多次调用,每到指定时间就执行一次。输入框联想功能,滚动条触底事件
7、大文件上传和断点续传的实现
- 实现方法有两种
- 分片上传:利用blob的slice方法,切分文件,将大文件按照一定大小,切割成相同大小的数据块,将数据块发送到服务器,每个切片包含切片最大数量,在服务器合并成一个文件。
- 断点续传:在上传或下载时,将文件分为几个部分。每个部分分一个线程进行或下载,如果遇到网络故障,下次上传下载时从中断位置开始。节省时间提高速度。二次上传可以获取临时文件大小,作为客户端读取文件的偏移量,从当前位置开始上传。
- 使用场景
- 大文件加速上传,切片后并行上传,提高速度
- 网络环境较差:分片上传。出现上传失败,只需重传失败分片
- 流式上传:文件大小还不确定时就开始上传。监控画面
- 实现
8、什么是单点登录?怎么实现
- 是什么呢?
- 单点登录能够整合企业业务方案,只需要登录一次就能够访问所有互相信任的应用系统,简称SSO
- 需要一个单独的认证中心,所有的系统登录操作,都从认证中心通过。应用系统不再参与登录操作
- 一个应用系统登录成功后,sso会颁发令牌给各个子系统,在一定时间内不需要再次认证
- 实现过程
- 同域名下的单点登录
- 同域名下会简单一些,将cookie的domain设置为主域名,path设置为根路径,然后将token等身份信息保存在主域名下。这样所有的子域名就都能访问到cookie信息。例如,
tieba.baidu.com和map.baidu.com,它们都建立在baidu.com这个主域名之下,那么它们就可以通过这种方式来实现单点登录。
- 同域名下会简单一些,将cookie的domain设置为主域名,path设置为根路径,然后将token等身份信息保存在主域名下。这样所有的子域名就都能访问到cookie信息。例如,
- 不同域名下单点登录---标准做法
- 应用系统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是否出现在实例对象原型链上,可以准确的判断引用数据类型。