1.前端加密的方式有哪些?
JShaman加密(不可逆,加密代码和数据) 直接到JShaman(www.jshaman.com)平台提交代码,得到加密后的js代码。这个方法很好用。 MD5加密(不可逆,加密数据) MD5.js是通过前台js加密的方式对用户信息,密码等私密信息进行加密处理的工具,也可称为插件。 base64加密(可逆,加密数据)
2.说一哈 $nextTick?使用场景?
$nextTick 是在DOM更新完成之后执行回调函数的方法 修改data中的数据,会引起视图的更新,而vue更新dom是异步的,不能立马获取更新后的dom,这时候就需要使用$nextTick 怎么才能获取: 1.)在updated钩子函数中可以获取更新后的dom,但是不推荐,会造成代码的分离 2.)使用vue中的$nextTick方法:有延迟回调的作用,可以获取更新后的dom 在我以前做过的项目中,有一个需求,在员工页面点击员工的头像时,展示一个二维码,这个二维码弹框是由el-dialog组件和canvas画布组成的,它本来是隐藏的,点击之后弹出,想要把地址转化为二维码,需要先获取画布的DOM,才能进行地址转化为二维码的操作,但是Vue中页面的更新是异步的,此时就要用到$nextTick了
在vue中如何获取DOM? (1)通过原生获取DOM的方式 (2)通过ref 第一步:在标签中添加ref属性 第二步:通过this. $refs.属性名获取DOM
3.transition和animate的区别?
1. transition是一个过渡的效果,没有中间状态,需要设置触发事件(如hover等)才能执行; 2. animation是一个动画的效果,有多个中间帧,可以在任意一个中间帧设置状态,不需要设置触发事件就能执行。
4.介绍一下插槽?
插槽的使用是为了解决组件中内容不确定时,使用slot进行占位。父组件传递什么内容,slot对应的子组件就显示什么内容。 插槽分为具名插槽和作用域插槽 具名插槽:当一个组件里,出现了两个及以上标签内容不确定需要slot占位时,这时就需要用到具名插槽,用name属性来区分不同标签。 作用域插槽:数据在子组件中,但父组件要用子组件中的数据。子组件通过row属性传递数据,父组件通过s1ot-scope=“scope”来接收数据
5.promise作用?
promise是一个对象,可以从对象获取异步操作的消息 它主要解决地狱回调的问题 为什么多个回调函数嵌套:下一个接口的参数依赖于上一个接口返回的结果 promise语法: 方法中有两个参数 new Promise( function(resolve.reject){ } ).then(( ) =>{ }).catch(( ) =>{ }) resolve代表调用成功,会走then reject代表调用失败,会走catch
6.什么是地狱回调?
多层回调函数的嵌套,使代码结构看起来很乱,难维护 使用场景:1.延时器的嵌套 2.下一个接口的参数依赖于上一个接口返回的结果 如何解决回调地狱:通过promise的链式调用来解决
7.介绍一下async和await?
1.await修饰的是promise,会强制等待promise中resolve执行成功后的结果; 2.await必须搭配async使用,在await的父级方法中加async,不加的话会强制等待,阻塞其他代码的执行,加上async后,async修饰的方法会变成一个异步方法; 3.async修饰的方法会返回一个promise,因此可以用promise修饰; 4.async和await捕获错误是通过try{}和catch(error){}进行的
8.token的持久化存储
1.什么是token? token是登录接口调用成功之后.后台返回的一个值,它是一个凭证,在调用有权限的接口时要传递过去,接口才能调通,因此token需要做一个存储 2.token如何进行存储? 人资项目在token存储在vue中的同时,又顺便在cookie缓存里面存储一份,达到持久化存储的一个目的,由于在vuex中存储的数据,在刷新浏览器时会丢失,因此需要在缓存中存储一份
9.call apply bind三种方式的区别?
共同点: 1、都是用来改变函数的 this 指向 2、第一个参数都是 this 要指向的对象。 3、都可以利用后续参数传参。 区别: call和apply 都是Function对象的方法,它们的主要作用是改变函数的运行环境。 call和apply方法都是接受两个参数,第一个参数是需要改变上下文的对象,而call的第二个参数是参数列表,apply第二个参数是参数数组。 bind方法也是Function的方法,bind 主要是返回一个函数的副本并指定参数,并不会立即运行函数。
10.vue中的$set方法有什么作用?
vue2中修改数据视图不能及时重新渲染,因此要用$set,$set是为了解决数据没有被双向绑定。 $set有3个参数,参数1是需要更新的对象和数组,参数2是要更新的数组的下标,或者对象的属性名,参数3是要更新的内容
11.v-mode双向绑定:
数据驱动视图,视图驱动数据改变 v-model双向绑定的原理:v-model是一个语法糖,他是动态属性value和@input事件的结合体 v-model实际是通过v-bind绑定value然后通过v-on定义input事件去更新绑定的值,这样就实现了双向绑定,可以说是一种语法糖 v-model主要是给表单元素使⽤,获取的是value的值,有时候封装组件也可以进⾏v-model绑定数据,⽐如定义⼀个组件,⽤props接收value,再⽤$emit给 input传值,这个组件就可以被绑定v-model了
12.Vue 数据双向绑定的原理是什么?
Vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。 1、需要 observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter,这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化 2、compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图 3、Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要做的事情是: 3.1)在自身实例化时往属性订阅器(dep)里面添加自己 自身必须有一个 update()方法 3.3)待属性变动 dep.notice()通知时,能调用自身的 update()方法,并触发 Compile 中绑定的回调,则功成身退。 4、MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通 Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model变更的双向绑定效果
------------------------
13.什么是路由懒加载?
项目性能优化的方案之一,当跳转到这个页面时,才去加载这个页面所对应的组件,而不是一次性引入,减少了项目打包之后的提交,提升了页面的渲染性能,尤其是首页的渲染性能
14.人资项目中为什么要有路由模块的划分?
是因为项目中牵扯到静态路由和动态路由 1.)什么是静态路由? 任何用户都可以去访问这个页面 2.)什么是动态路由? 有权限的用户才能访问某个页面,没有权限访问不了,是根据用户权限去分配的 3.)为什么每个路由模块都引入了layout布局? 因为要做动态路由管理,每个路由模块都应该属于自己的完整布局
15.路由跳转方式有哪些?
第一种: 通过a标签的href属性 (不常用) 第二种: 声明式导航的router-link进行跳转 第三种: 编程式导航的push,replace,go,back等 如This$router.push('/') 1、<router-link to="需要跳转到⻚⾯的路径"> 2、this.$router.push()跳转到指定的 url,并在 history 中添加记录,点击回退返回到上⼀个 ⻚⾯ 3、this.$router.go(n)向前或者后跳转 n 个⻚⾯,n 可以是正数也可以是负数 4、this.$router.replace()跳转到指定的 url,但是 history 中不会添加记录 5、this.$router.back()回退到上⼀个⻚⾯ (1) 通过path匹配路由的编程式导航形式 通过this.$router.push 用$route.params/query.传递的参数 (2)通过name匹配路由的编程式导航形式 this.$router.push 用$route.query/params.传递的参数 (3)在跳转时通过path搭配query进行跳转(不能用path搭配params进行传参)
1X.路由传参的⽅式有哪些?
两大方式: 声明式的导航和编程式的导航 router.push (1)编程式: 第一种: 在跳转时通过name搭配params进行传参 第二种: 在跳转时通过name搭配query的方式传参 第三种: 在跳转时通过path搭配query进行跳转 备注:不能用path搭配params进行传参 name 和 params的搭配传参 this.$router.push({name:"news",params:{userId:123}) path 和 query的搭配传参 this.$router.push({path:"/news',query:{uersId:123}) (2)声明式导航: 命名路由: <router-link :to:"{name:'news',params:{userid:1111}}"></route-link> 查询参数: <router-link :to="{path:'/news',query:{userId:1111}}"></router-link>
16.路由中携带的参数接收方式有哪几种?
1、?形式的参数使用this.$route.query接收参数,结果是一个对象 2、:形式的参数使用this.$route.params接收参数,结果也是一个对象
17.$route和$router 的区别是什么
(1) $router里面存 放的是所有的路由信息,可以通过this. $router.options.routes获取 (2) $router可以操作路由, 例如: this. $router.push('/") (3) $route存放的是单个路由地址信息; 例如:可以在里面可以获取到路由地址携带的参数 this.$route.palms.参数名称
18.路由 (什么是路由?)(为什么学路由)
1.什么是路由: 路径和组件(或者页面 )一一对应的映射关系 2.为什么要学路由? 通过路由实现的项目是一个单页面应用,路由地址发生变化,页内容局部更新,用户体验良好 3.什么是单页面应用(应为缩写SPA) 项目中只有一个html文件,所有的业务功能都是在这一个页面切换 4.如何在项目中使用路由: 安装一个包:vue-router 5.什么是组件的分类 组件分类是开发者,人为的去进行划分的,一般分为页面组件、复用组件(公共组件), 为了项目管理和维护 一般情况下,页面组件放在views文件夹,公共组件放在component文件夹 6.vue-route的基础使用 1.安装插件vue.route 2.准备要切换的页面,在views文件夹下创建 3.在App.vue中准备了跳转按钮 4.配置路由 1.)在main.js中引入路由 2.)注册路由模块包 Vue.use() 3.)配置路由规则 4.)创建路由实例 5.)将路由实例添加到vue实例配置项中 6.) 在跟组件中配置路由挂载点,也叫容器
19.路由的跳转方式
第一种:通过a标签的href属性 <a href="#/find">发现音乐</a> (不常用) 第二种:通过vue内置的组件router-link进行跳转,又叫声明式导航 声明式导航的特点:底层还是a标签,但是多了激活的class类名,可以实现高亮功能 第三种:编程式导航跳转(也叫js的跳转方式,最常用) 1.)通过path跳转 this.$router.push(path:路由地址) 2.) 通过name跳转 this.$router.push({name: 路由名称}) 通过name跳转的前提是在路由规则里面配置name属性
20.编程式导航的传参方式:
第一种: 在跳转时通过name搭配params进行传参 第二种:在跳转时通过name搭配query的方式传参 第三种:在跳转时通过path搭配query进行跳转 备注:不能用path搭配params进行传参
21.声明式导航的传参方式:
1.)路由地址后面通过?拼接的方式进行传参,在页面中接受是采用:$route.query.参数名称接受 2.)采用动态路由传参的方式,首先得在路由规则中配置要传递的参数 path: '/part/:username', //username是要传递的参数 <router-link to="/part/username">朋友2</router-link> 通过$route.params.username接收
22.路由重定向
使用场景:网页一打开的时候,一般默认都是一个空路径,就不会显示页面内容 怎么能默认一个页面内容进行显示? 采用路由重定向的方式默认一个页面进行展示
23.路由模式的分类
1.)hash模式:特点 路由地址里面有# 默认就是hash模式 2.)history模式,特点时路由地址没有#,在上线之后需要服务端的支持,需要去配置 mode:history
24.路由模式:哈希模式和history模式的区别
1.路径表现的外观上: 在vue的路由配置中有mode选项 最直观的区别就是在url中 hash 带了一个很丑的 # 而history是没有#的 2.本质上: hash-----虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。 history -----利用了 HTML5 History Interface 中新增的 history.pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
25.vue-router的实现原理是什么? (是不是浏览器对象的封装)
1.hash ---- 利用URL中的hash(“#”),hash,只会替换掉url中#以后的路径,而不会管前面的,hash不能对完全相同的url产生变化,所以说Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据
2.利用History interface在 HTML5中新增的方法,history会改变整个url就算一样的url还是会产生路由记录(history.pushState API)
---------------------------
26.在vue中如何获取DOM?
(1)通过原生获取DOM的方式 (2)通过ref 第一步:在标签中添加ref属性 第二步:通过this. $refs.属性名获取DOM
什么是虚拟dom?(面试题)
本质是一个js对象,里面存放的是真实dom的重要信息,虚拟dom是通过template模板标签转化而来的; 虚拟dom最终的作用:新旧虚拟dom做对比,只更新变化了的部分,类似于打补丁,最终减少了操作真实 dom的次数,提高了页面的渲染性能
27.new操作符做了什么?
1.创建一个空的对象 2.将空对象的proto属性指向构造函数原型 3.将this的指向这个原型 4.返回这个对象
28.描述一下js中的事件流?
事件流就是事件的流向,分为事件捕获阶段,目标阶段,事件冒泡阶段
29.组件缓存如何实现?
使用Keep-alive内置组件将动态组件包真起来,就可以实现组件的缓存
30.keep-alive的实际应该场景 (组件缓存或页面状态的缓存)
keep-alive主要⽤于动态组件和路由,进⾏组件或者⻚⾯状态的缓存,常⽤于列表⻚和列表详 情⻚之间切换的场景,优点是可以保留进⼊详情⻚之前列表的滚动位置,缺点是不会更新列 表,当然也可以在activated⽣命周期重新发起ajax获取数据
31.vue之间的组件通信
1.父传子 通过父组件,在子组件标签上,绑定一个属性:users="users",子组件通过props接收 2.子传父 子传父: 1.在子组件中通过$emit()方法定义事件,参数1:'自定义事件名',参数2:要传给父组建的参数 2.在父组件中通过v-on指令监听自定义事件,然后在监听的回调中取得数据 子组件:<button v-for="item in categroies" :key="item.id" @click="getData(item)">{{item.name}}</button> getData(item){ //子传父:1.通过自定义事件 this.$emit('itemclick',item); } 父组件: <cpn @itemclick="getChild"></cpn> //2.在父组件中取得数据 getChild(item){ console.log(item); } 3.兄弟相传(有吗?) vuex 4.父访问子 //通过$refs:需要在子组件上加上ref属性值为子组件名字(例如:cpn),然后通过$refs.设置的名字获取到相应的子组件 this.$refs.cpn.showMessage(); 5.子访问父 //通过$parent访问父组件 console.log(this.$parent); 6.访问root组件 //访问根组件:通过$root console.log(this.$root);
32.vuex持久化的实现
要想实现vuex刷新后数据不丢失,一般使用localStorage来完成,也可以使用vuex-persist插件来完成,它不需要你手动存取storage状态保存至localStorage中
33.es6的新特性
1.箭头函数 2.解构赋值 3.模板字符串 4.拓展运算符 5.let,const
34.项目优化
基础的 Web 技术层面的优化: 1.合理使用v-if和v-show 2.computed 和 watch 区分使用场景 3.v-for 遍历必须为 item 添加 key,且避免同时使用 v-if 4.图片资源懒加载 5.路由懒加载 6.浏览器缓存 7.CDN的使用 8.前后端开启gzip压缩,前后端只需要简单配置 - 减少http请求 - 减少对DOM的操作 - 使用JSON格式来进行数据交换 - 高效使用HTML标签和CSS样式 - 将CSS和JS放到外部文件中引用,CSS方头部,JS放尾部 - 精简CSS和JS文件 - 压缩图片和使用图片Sprite(精灵图)技术,图片懒加载 - 注意控制Cookie大小和污染 webpac配置优化: 1.Webpack 对图片进行压缩 2.减少 ES6 转为 ES5 的冗余代码 3.提取公共代码
35. 在浏览器里面输入一个URL地址,敲回车键经历了什么?
第一步:首先会在浏览器缓存里面检测有没有自己查找的资源,如果有,直接从缓存里面取; 如果缓存里面没有这个资源,会通过DNS域名解析服务器寻找url域名所对应的ip地址 第二步:建立TCP连接,经历了3次握手 第三步:连接成功之后向服务器发起http请求 第四步:服务器处理请求,作出响应 第五步:拿到响应结果之后,断开TCP连接(经历了四次挥手) 第六步:解析HTML生成DOM树,解析CSS生成规则树 第七步: DOM树和规则树完成了最终的页面渲染
36.Tcp三次握手
tcp的握手其实就是客户端与服务器端建立可靠连接的过程,首先客户端向服务器发送一段tcp报文,服务器端接收并返回一短报文告诉客户端服务器已经收到,随后客户端再发送一段报文表示连接已经建立,三次发送报文的过程就是三次握手,四次挥手是断开连接的过程,原理大同小异.
37.为什么避免v-if 和 v-for ⽤在⼀起?如何解决?
当 Vue 处理指令时,v-for ⽐ v-if 具有更⾼的优先级,通过 v-if 移动到容器元素,不会再 重复遍历列表中的每个值。取⽽代之的是,我们只检查它⼀次,且不会在 v-if 为否的时候运 算 v-for。如果真的需要⼀起使⽤,可以先写if,再使⽤标签包裹需要循环的内容,讲循环写 在template标签上。
38.v-if和v-for的优先级
在vue2中,v-for的优先级是⾼于v-if,在vue3中则完全相反,v-if的优先级⾼于v-for,所 以v-if执⾏时,它调⽤的变量还不存在,就会导致异常
39.pc端图片上传功能:
1.封装一个图片上传的组件,利用el-upload组件 2.选择完要上传的图片之后,会触发组件的on-change钩子函数,这个函数可以获取选择文件的图片信息 3.获取图片信息之后,赋值给upload组件的filelist属性所绑定的数组,待触发上传动作之后,本地图片 就可以 展示在展示区,此时的图片的地址还是本地图片地址, 4.通过http-request触发上传,在这里获取文件的信息,调用后台接口,将图片信息作为参数,传给后 台,存放到后台服务器 5.加了一些图片上传的补充功能:图片的预览,调用on-preview钩子函数,实现了图片的删除,调用了 on-remove钩子函数,还做了图片上传之间的检查功能,调用了before- upload钩子函数 备注: 由于人资项目是上传到腾讯云服务器,所以在http- request钩子函数中利用插件的方法和腾讯云 服务器进行了交互,上传成功之后,腾讯云服务器返回了一个图片的线上地址
40.为什么要使用组件缓存?
在动态组件进行频繁切换的时候,会频繁的创建和销毁组件,影响性能
41.cookie、sessionStorage和localStorage的区别?
-
- cookie是网站为了标示用户身份而储存在用户本地终端上的数据(通常经过加密) - cookie数据始终在同源的http请求中携带 - 存储大小: cookie数据大小不能4K sessionStorage和LocalStorage虽然也有存储大小的限制,但是比cookie大得多,可以达到5M或更大 - 有期时间: LocalStorage存储持久数据,浏览器关闭后数据不丢失除非主动删除数据 sessionStorage数据在当前浏览器窗口关闭后自动删除 cookie设置的cookie过期时间之前一直有效,即使窗口或者浏览器关闭
42.如何实例化一个echars(在vue中使用echars步骤)
1.安装echars yarn install ecahrts --save 2.导入ecahrs插件,在main.js文件下配置(挂载到vue原型上): import ecahrs from 'ecahrs' Vue.prototype.$echars = echars 3.在组件页面中,建立一个容器,放入echars,并引入 import echarts from 'echarts' 4.初始化eachrs,建立mounted生命周期钩子函数 初始化: var myChart = echars.init(document.querySelector('#list')) 拿到echars图表需要的数据库: var option = option: { 图表数据 } 5.最后优化代码格式
43.computed和watch有什么区别?
computed:计算属性
支持缓存,计算属性对应的函数执行后,会把返回值缓存起来 当依赖项不变时 多次调用函数都是从缓存里取值,赖项变化时 函数会自动重新执行并缓存新的值
watch:侦听属性
不支持缓存,数据变,直接会触发相应的操作,监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值
44.js 防抖和节流
防抖
当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时
节流
当持续触发事件时,保证一定时间段内只调用一次事件处理函数
区别:
节流 不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,防抖 只是在最后一次事件后才触发一次函数。
45.=== 和 ==的区别?
===:等同符,等号两边值与类型都相等时,才会返回true
==:等值符,等号两边的值为相同类型时比较值是否相同,类型不同时转换为相同的类型后再作比较。也就是说两个等号只要值相等就可以
46.获取对象中的属性
for in
object.keys
object.value 获取对象属性的值
47.文件上传是如何实现的?(即项目中的文件上传步骤)
1、使用 input 标签<input type="file">拾取本地要上传文件
文件上传按钮绑定点击事件
选择文件信息 files的判断 是否小于等于0
选择了发起接口请求,传递fromdata类型
new fromdata对象
2、前端使用http传送文件,文件以FormData为载体,Content-Type 选择为multipart/form-data
3、后端接收并解析FormData
48.什么是跨域?怎么解决跨域?
是由于浏览器的同源策略限制的,只要两个页面的协议、域名、端口号,其中一个不一致,就是非同源,就会产生跨域问题
出现跨域的根本原因:浏览器的同源策略不允许非同源的URL之间进行资源的交互。
1.后端解决方案:
根本的解决方案
CORS:出现的较晚,它是W3C标准,属于跨域Ajax请求的根本解决方案。支持GET和POST请求。缺点是不兼容某些低版本的浏览器。
前端解决方案:
2.JSONP实现原理:主要就是利用了script 标签的src,不受跨域的限制
3.反向代理:
在vue中,脚手架在启动项目时,顺便启动了一个本地后台服务,这个本地后台服务地址和前端服务地址是一致的,在发起请求时,本地的前端服务先去请求本地的后台服务,本地的后台服务再去请求真实的服务,服务和服务之间不存在跨域问题,从而解决了跨域