1.一个页面从输入URL 到页面显示加载完成都经历了什么?
- 浏览器查询域名对应的IP地址
- 浏览器向web服务器发送一个http的请求
- 服务器301重定向
- 浏览器跟踪重定向地址,请求另一个带www的网址
- 服务器处理请求
- 服务器返回一个http的响应
- 浏览器进DOM树构建
- 浏览器发送请求获取嵌在HTML中的资源
- 浏览器显示完成页面
- 浏览器发送异步请求
2.Ajax原理
- 通过
XMLHTTPRequest对象来向服务器发送异步请求,从服务器获取数据,然后用JavaScript来操作DOM更新页面。
3.Ajax底层封装原理/Ajax实现流程
- 先封装一个XMLHTTPRequest函数,也就是用来发送异步请求的函数
- 创建一个新http请求,设置请求方式,URL路径,以及验证信息
- 设置响应http请求状态变化的函数
- 发送http请求
- 获取异步调用返回的数据
- JavaScript操作DOM刷新页面
4.vue实现双向绑定的流程
- new vue( ) 首先执行初始化,对data执行响应化处理,observer开始监听所有数据的属性,这步发生在(
observer中)- 同时
compile对模板进行编译,找到动态绑定的数据,在data中获取数据并且初始化视图,这步在(compile中)- 同时定义一个更新函数一个watcher函数,当数据发生变化时,watcher函数调用更新函数处理
- data中的某个key,可能在页面上使用多次,所以每个key都需要一个管家
Dep来管理所有的watcher- 当数据发生变化时,首先找到其对应的Dep,Dep通知所有的watcher执行更新函数
5.vue的响应式原理
原理
vue的响应式原理主要是通过Es5中的Object.defineProperty来进行数据的劫持,然后利用get和set来进行获取和设置,在data中所有的属性都被添加到get跟set中,当读取data里面的数据时自动调用get方法,当修改data中的数据时,自动调用set方法,检测到数据发生改变,自动触发watcher函数,watcher函数自动触发重新reader当前组件,生成新的虚拟DOM,vue框架会遍历新DOM数和旧DOM树之间的区别,并记录下来,最后加载操作,将记录下来不同的点,局部修改到真实DOM数上
6.vue的响应式原理深度理解
数据发生改变自动触发watcher函数,watcher函数通过依赖收集在管家Deps中,通过对Deps数组的去重,确保不会反复reader组件,提高性能
7.vue2和vue3的区别:
- 重新构建了响应式,使用 proxy 替换了Object.defineProperty
- 使用reactive就可以直接监听数组和对象类型的变化
- 采用了组合式API,而vue2是选项式API
- 重构了虚拟DOM
- 直接实现对象属性的增加和删除
- 模板编译时会把一些静态的节点转换为常量
- 监听的目标为对象本身,不需要像vue2采用Object.definePriperty遍历每一个属性,有一定的性能优化
8.vue2.0 与 vue3.0响应式区别
- Object.defineProperty
- 用于监听对象数据的变化
- 无法监听数组的变化(下标,长度),其他七种改变数组的方法可以监听到
- 只能劫持对象的自身属性,动态添加的劫持不到
- Proxy
-
Proxy返回的是一个新对象,可以通过操作返回的新对象达到目标
-
可以监听到数组的变化,也可以监听带动态添加的数据
-
9.深拷贝
1.常见的深拷贝方式
- _.cloneDeep() -------lodash里面封装好的方法
- jQuery.extend()
- JSON.stringify() -------但是这种方式存在弊端,会忽略 undefined 、 symbol 和 函数
const obj2=JSON.parse(JSON.stringify(obj1));
手写循环递归
原生的 WeakMap 持有的是每个键对象的“弱引用”,这意味着在没有其他引用存在时垃圾回收能正确进行。原生 WeakMap 的结构是特殊且有效的,其用于映射的 key 只有在其没有被回收时才是有效的。
正由于这样的弱引用,
WeakMap的 key 是不可枚举的 (没有方法能给出所有的 key)。如果key 是可枚举的话,其列表将会受垃圾回收机制的影响,从而得到不确定的结果。因此,如果你想要这种类型对象的 key 值的列表,你应该使用Map。基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。
function deepClone(obj, hash = new weakMap()) {
if (obj === null) return obj // 如果是null或者undefined就不需要进行拷贝操作
if (obj instanceof Date) return new Date(obj) // 时间格式化数据
if (obj instanceof RegExp) return new RegExp(obj) // 正则表达式
// 可能是对象或者普通的值,如果是函数的话是不需要深拷贝
if(typeof obj !== "object") return obj
// 是对象的话就需要进行深拷贝
if (hash.get(obj)) return hash.get(obj) //判断该对象是否已经被拷贝了,如果已经被拷贝则取出该对象并返回
let cloneObj = new obj.constructor()
// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
hash.set(obj, cloneObj)
for (let key in obj){
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key],hash)
}
}
return cloneObj
}
作用域
什么是作用域
- 简单理解就是变量和函数能被访问(或生效)的范围区域
作用域分为几种
- 全局作用域
- 函数作用域(局部作用域)
- 块级作用域 ---ES6引入let 跟const 导致出现块级作用域
什么是作用域链
- 在JavaScript中使用一个变量的时候,首先JavaScript会尝试在当前作用域下去寻找,如果没找到,会再到他上一级的作用域中去找,以此类推,一层一层寻找变量的过程俗称作用域链
关于 cookie 、 sessionStorage 、 localStorage 三者的区别主要如下:
存储大小: cookie 数据大小不能超过 4k , sessionStorage 和 localStorage 虽然也有存储大小的限制,但比 cookie 大得多,可以达到5M或更大
有效时间: localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;sessionStorage 数据在当前浏览器窗口关闭后自动删除; cookie 设置的 cookie 过期时间之前
一直有效,即使窗口或浏览器关闭
- 数据与服务器之间的交互方式, cookie 的数据会自动的传递到服务器,服务器端也可以写cookie 到客户端; sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存
应用场景
标记用户与跟踪用户行为的情况,推荐使用 cookie
适合长期保存在本地的数据(令牌),推荐使用 localStorage
敏感账号一次性登录,推荐使用 sessionStorage
存储大量数据的情况、在线文档(富文本编辑器)保存编辑历史的情况,推荐使用 indexedDB
回流
布局引擎根据各种样式来计算每个盒子在页面上的大小与位置, 当盒子发生大小位置的变化,导致页面布局发生改变一定会触发回流,比如dom节点的删除与增加,浏览器的页面视口发生变化化,盒子的尺寸,内容等发生变化的都会一定几率触发回流。回流一定重绘
重绘
确定好每个盒子的大小与位置后,根据每个盒子的其他属性进行绘制,当盒子的某些属性发生改变,比如颜色,阴影的修改,这些不会改变盒子大小与位置的改变会触发重绘
浏览器如何优化回流与重绘
由于每次重排都会造成浏览器的计算属性浪费,因此,浏览器会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。
当你获取布局信息的操作的时候,会强制队列刷新,包括前面讲到的 offsetTop 等方法都会返回最新
的数据
因此浏览器不得不清空队列,触发回流重绘来返回正确的值
10.你的项目中是如何实现登录功能的?
通过下面五方面回答
- token的获取
- token的存储
- token的持久化
- token的使用
- token的时效
具体实现步骤
- 首先我们调用登录的api接口,把用户填的表单信息通过校验后提交给后端
- 后端处理用户的登录信息,校验通过后,返回一个token字符串,里面记录的用户的基本信息,由于token字符串是base64格式的,很容易逆向还原泄露用户信息,所以token中不会携带敏感的用户信息
- 在项目中可能其他请求会要求携带token,所以为了方便使用和获取token,我们会把token存储在Vuex中。
- 由于vuex的数据是存储在内存中的,页面刷新就会消失,所以我们通过js-cookie这个模块来存储token,实现token的持久化保存在本地。
- 以后用户在调用接口api时,我们通过axios的请求拦截器来判断该请求是否需要携带token,如果需要我们通过config.headers对象,来为请求添加Authorization的请求头,数据就是来着vuex中的token,这样就成功的完成了这次请求。
- 如果token过期,会触发axios中的响应拦截器,通过err.response.status状态来判断,如果状态为401,那就是token过期,需要清除vuex中的token,通过路由跳转到首页,退出重新登录存储token
11.如何在项目中使用axios?
三个方面:
- axios的作用
- 封装axios
- 使用axios
- axios在项目中主要用来发起Ajax请求的,实现前后端数据交互的
- 为了方便使用与维护,我们会在项目中对axios进行封装,在src/utils/request.js文件中调用axios.create()函数创建axios的实例对象,在函数中配置baseURL为请求根路径,针对token配置请求拦截器(判断哪些接口需要携带token进行请求,自动添加token)与响应拦截器(token过期,或者判断请求状态来是页面跳转到登录页面并且清除vuex中的token),如果要中断请求可以手动抛出一个错误
- 对于一些功能性的api,统一在src/api文件下进行情求封装接口,提高了api接口的复用性
12.说说事件循环机制(满分回答)
- JavaScript代码执行过程中,除了依靠函数调用栈来搞定函数执行顺序外,还需要任务队列来搞定其他一些代码的执行,整个执行过程我们称为事件循环过程。一个线程中,事件循环是唯一的,但是任务队列可以有很多个。任务队列又分为宏任务与微任务,在最新标准中又被称为task和objs。
- 宏任务大概包括:Script(整体代码),settimeout,setinterval ,setimmediate, I/O, UI render
- 微任务大概包括: Promise, process.nextTick, MutationObserver(html5新特性), Async/Await(实际就是promise)
- 所以先执行宏任务,然后执行该宏任务下产生的微任务,如果在其微任务的执行过程中又产生了微任务,则继续执行微任务,微任务执行完毕后,再回到宏任务中进行下一轮循环。
- 同步任务与异步任务执行,在主线程上先执行第一个同步任务,只有同步任务执行完毕才会执行后面的代码,执行过程中遇到异步任务时,将其放入任务队列,继续接着往下执行别的代码,执行完同步代码,去看任务队列里面有没有要执行的异步代码,有的话取出来执行,
- 宏任务与微任务的循环执行,同步任务与异步任务的循环执行构成了事件循环机制
13.ES6有哪些新增
-
新增了声明命令
let和const(说明let和const的使用与优点) -
新增了模板字符串,简化了变量的拼接
-
新增了一些函数的扩展
- 允许函数有默认参数
- 出现了箭头函数,扩展了this的指向问题
-
新增了对象的扩展
- 属性的简写,允许直接在对象中写变量
- 增加object.keys() 获取对象的属性名或者方法名,返回一个数组
- 增加Object.value() 获取对象的属性值
- 增加Object.assign() 合并多个对象的属性方法在源对象上
-
新增 for... of 循环,多用于数组的循环
-
新增import 和 export
ES6支持将js代码模块化,通过模块的导入导出大大增加了代码的复用性,减少了代码的臃肿
-
新增了Promise对象
-
Promise是异步编程的一种解决方案,使异步代码跟同步代码一样同步执行,避免了层层嵌套,解决了回调地狱
-
Promise构造函数中包含一个参数和一个带有resolve(成功)reject(失败)两个参数的回调,在回调中执行一些异步操作,如果执行成功则调用resolve,否则调用reject。对于已经实例化过的Promise对象可以调用Prmise.then()方法,传递resolve,reject方法作为回调。then()方法接受两个参数:onResolve和OnReject,分别代表当Promise对象成功和失败
-
Promise有三种状态:Fulfiled---成功的状态,Rejected----失败的状态,Pending----既不是成功也不是失败,理解为Promise的初始化状态
-
-
新增了解构赋值
- 数组的解构赋值
- 对象的解构赋值
-
新增
Set数据结构- Size() 数据的长度
- Add() 添加某个值,返回Set结构本身
- Delete() 删除某个值,返回一个布尔值,表示是否删除成功
- Has() 查找某条数据,返回一个布尔值
- Clear() 清除所有成员,没有返回值
-
class
class 类的继承 ES6 中不再像 ES5 一样使用原型链实现继承,而是引入 Class 这个概念
14.什么是前后端分离项目?
-
所有的程序都是以数据为基础,所有的操作都是围绕数据进行增删改查
-
前后端分离就是把数据操作与显示分离出来。前端专注做数据的显示,通过文字,图片,图标等方式让数据形象直观的显示出来。后端专注做数据的操作。前端把数据发给后端,后端去修改数据
-
后端来进行对数据库的链接,并对数据进行操作
-
后端提供接口给前端调用,来触发后端对数据的修改
15.请说一下封装Vue组件的过程?
-
在项目中为了为了提高项目的开发效率会选择去做组件的封装,做成相对独立的模块,提高项目的开发效率,提高代码的复用性
-
分析需求
根据业务需求,把页面中可以复用的结构,样式和功能抽离成单独的文件,方便其他模块的复用
-
具体步骤
- 使用Vue.compeonent方法注册组件,子组件需要数据可以在props里面接受父组件传来的值,子组件修改后的数据想传给父组件可以通过$emit通知父组件去修改数据
- 如果需要给组件传入模板,可以定义slot插槽实现
- 如果需要父组件主动调用子组件的方法,可以在methods里面开放方法
-
Vue.cli中如何使用自定义组件
-
在components文件夹下定义组件文件(indexPage.Vue),script中使用 export default {}
-
在需要使用的页面导入 import 组件,在component中注册组件,然后在页面上使用组件标签
16.如何使用自定义指令
- 全局定义指令,在Vue.directive方法里有两个参数,一个是指令名称,一个是函数。组件内定义指令用directives
- 有三个钩子函数
- bind(绑定事件触发)
- inserted(节点插入时触发)
- updata(组件内相关更新时触发)
- 钩子函数的参数(el,binding)
17.Vue中如何定义过滤器?
全局过滤方法:Vue.filter()注册一个自定义过滤器,接受两个参数,第一个参数为过滤器名称,第二个参数为过滤器函数,过滤器函数以传入的值为参数,返回过滤后的值
18.简述vuex中数据传递流程
在页面上通过store.dispath来调用action中的属性方法,action中又通过store.commit来执行mutation中方法,mutation中每个方法又有state参数,通过state来修改state里面的数据,当数据修改完毕后,传输给页面进行显示
19.vue项目优化的解决方案有哪些?
- 使用插件抽离css
- 配置optimization把公共的js代码抽离
- 通过webpack处理文件压缩
- 不打包框,库文件,通过cdn方式引入
- 小图片采用base64
- 配置项目文件懒加载
- UI库按需导入
- 使用Gzip压缩
20.vue项目如何做首屏加载优化?
- 把不常用的库,或者体积比较大的放在index.html中通过cdn来引入
- Vue路由的懒加载
- 不生成map文件
- Vue组件尽量不要全部引入,最好按需加载
- 使用更加轻量级的组件库
- 使用Gzip压缩
- 使用SSR搜索引擎优化
- 首页单独做服务端渲染
21.vue.$nextTick()的原理?
$nextTick就是把其回调函数延迟到下次DOM更新才去执行,也就是js的代码执行顺序,事件循环机制问题,牵扯到宏任务与微任务执行问题
22.前端如何进行性能优化?
- 减少http请求
- 减少对DOM的操作
- 使用JSON格式来进行数据交换
- 高效使用HTML和CSS样式
- 使用CDN加速
- 将js,css放在外部文件进行引用,css放在头,js放在尾
- 精简css和js代码
- 压缩图片和使用雪碧图
- 注意控制cookie大小与污染
23.一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验?
- 图片懒加载 - 在页面上添加一个滚动条事件,计算图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者则优先加载
- 图片预加载 - 在轮播图和幻灯片中,可以使用图片的预加载,将当前展示的图片的前一张与后一张优先加载
- 图片压缩 - 如果图片为 css 图片,可以使用 CSSsprite,SVGsprite,Iconfont、Base64 等技术处理再使用。如果图片特别大,可以在页面显示上先显示一个压缩特别小的图片,提高用户体验。
24.手写一个Ajax请求
// 创建一个xhr 请求
var xhr = new XMLHTTPRequest()
// 调用open函数,第一个参数为请求方式GET/POST,第二个参数请求的地址,第三个参数true表示异步请求,false表示同步请求,默认true
xhr.open('GET','http://www.baidu.com/html',true)
// 调用send函数发送请求
xhr.send()
// 通过onreadystatechange来判断请求是否成功,是否返回
xhr.onreadystatechange = function(){
//当readystate=4代表请求回来了
if(xhr.readystate === 4){
// 判断状态码
if(xhr.status>=200 && xhr.status<300){
console.log(xhr.respoonse)
}
}
}
25.系统如何进行权限控制和实现?
- 权限控制一般分为:接口权限,路由权限,菜单权限,按钮权限
- 接口权限:部分接口只有用户登录后才可以访问,一般通过jwt进行验证,用户登录拿到token,将token存储起来,每次请求的时候在Ajax请求拦截器中拦截,在请求头部进行携带,如果有token放行访问,如果没有token则返回401,跳转到登录页面
- 路由权限: 部分页面只有用户登录后才可以访问,在路由前置守卫里面进行判断,如果访问的是登录页面或404页面则直接跳转,如果访问的其他页面,需要判断是否有token,如果有则允许访问跳转,如果没有则返会登录页面
- 菜单权限:不同的角色可以看到不同的页面。通过给角色配置不同的路由来实现,在路由前置守卫中,获取角色的登录权限信息,然后筛选用户有权限访问的路由页面,最后通过addRouters动态添加路由
- 按钮权限:不同的角色在页面上可以看到不同的按钮,一般通过定义全局方法,要么在vue的原型链上,要么使用全局混入方法,在页面按钮上通过v-if来使用该方法,通过判断用户的权限信息来判断用户是否有该按钮的权限
25.1如何处理路由实例混淆
-
利用
刷新网页 -
- 采用
window.reload(),或者router.go(0)刷新时,整个浏览器进行了重新加载,闪烁,体验不好 - 运用
this.$forceUpdate()强制刷新 - 通过调用全局的 location.refresh 方法来实现应用
刷新来实现前端路由的重置。
- 采用
-
初始化路由
-
1.replace对路由重新赋值
this.$router.replace({path: '/login'}); // 对路由进行重新赋值 location.reload(); // 刷新页面双重保证2.通过替换当前
vue-router的matcher属性对象来实现在不刷新页面的情况下重置当前路由实例。
26.讲讲上传组件的实现思路
- 我们项目中使用组件上传主要是上传图片,用来显示用户的头像信息
- 核心思路是通过第三方云服务器来实现,将文件上传到第三方云服务器,将云服务器储存的URL存储在公司的自由服务器上
- 然后创建公共组件,使用饿了么upload组件,通过样式穿透来修改上传组件的默认样式,通过http来覆盖默认的上传方法
- 最后增加一些细节和功能,在上传文件之前判断文件的类型大小与文件上传数量的限制,增加上传进度条,上传成功后保存文件地址,通过组件实现预览与删除
27.扁平化数据如何转为树形数据?
- 我们项目中后端返回的扁平化数据里面一般会存在id跟pid属性,子级的pid等于父级的id,通过这两个字段就可以作为条件来转换为树形数据
- 在项目utile工具文件夹index下封装一个处理数据的函数,该函数接受两个参数,第一个参数为要转化的数据,第二个数据是用来判断的pid值(具体传什么看后端数据返回什么pid值,通常传入0或'')
- 定义一个空数组来接受最后转换完的数据,开始对传入的数据进行遍历,首先判断传入数据的pid是否跟第二个pid参数相等,如果相等继续调用该函数,传入两个参数,第二个参数变为父级的id,判断子级id是否跟父级pid相同,如果相同,就把该子级添加为父级数据的children的属性值。最后把每次循环遍历复合数据的对象push到空数组里面
- 最后在组件上使用该函数
27.1数据扁平化实现方法有哪些
- 使用基础的递归遍
- 使用reduce函数递归遍历
- 数组强制类型转换 return arr.toString().split(',').map((item) => Number(item));
- while循环结合findIndex与concat
- 直接使用ES6的flat方法
- 使用JSON的函数和正则表达式
- 使用堆栈stack
- 使用Generator 函数与递归结合
28.H5的新特性有哪些
- 拖拽释放
- 自定义data-id
- 语义化更好的标签(header,nav,footer,aside, article, section)
- 视频音频标签,添加autoplay自动播放
- 新增画布canvas
- 地理api
- 新增本地离线缓存localStorage,sessionStorage
- 表单控件 calendar , date , time , email , url , search , tel , file , number
- 新的技术 webworker, websocket , Geolocation
29.vue2生命周期中父子组件的加载顺序
加载渲染过程
父beforeCreate—>父created—>父beforeMount—>子beforeCreate—>子created—>子beforeMount—>子mounted—>父mounted
更新过程
父beforeUpdate—> 子beforeUpdate—>子updated—>父updated
销毁过程
父beforeDestroy—> 子beforeDestroy—>子destroyed—>父destroyed
30.常见的web攻击方式
- xss 跨站脚本攻击
- CSRF 跨站请求伪造
- SQL 注入攻击
31.箭头函数的区别
this始终指向window,箭头函数中的this,永远指向外层作用域中最接近自己的普通函数的thisbind、call、apply等方法无法改变箭头函数的this指向。- 箭头函数不能当做构造函数来使用
- 箭头函数没有
arguments - 箭头函数没有
prototype属性 - 箭头函数不能当做
Generator函数,不能使用yield关键字 - 箭头函数不能被
new关键字调用,不具有new.target
32.对promise的理解
- Promise是异步编程的一种解决方案,使异步代码跟同步代码一样同步执行,避免了层层嵌套,解决了回调地狱
- Promise构造函数中包含一个参数(回调函数),一个带有resolve(成功)reject(失败)两个参数的回调,在回调中执行一些异步操作,如果执行成功则调用resolve,否则调用reject。对于已经实例化过的Promise对象可以调用Prmise.then()方法,传递resolve,reject方法作为回调。then()方法接受两个参数:onResolve和OnReject的回调,分别代表当Promise对象成功和失败
- Promise有三种状态:Fulfiled---成功的状态,Rejected----失败的状态,Pending----既不是成功也不是失败,理解为Promise的初始化状态
- 如何捕获promise的错误
- 在catch中捕获
- 抛出一个错误 throw new Error('terminate now');
- async/await 搭配 try catch 进行捕获异步错误
- 对于同步错误,可以定义
window.onerror进行兜底处理,或者使用window.addEventListener('error', errHandler)来定义兜底函数。 - 对于Promise异常,则可以同步使用
window.onunhandledrejection或者window.addEventListener('unhandledrejection', errHandler)来定义兜底函数。 - then的第二个参数和catch方法都存在的情况下,只有then的第二个参数能捕获到,如果then的第二个参数不存在,则catch方法会被捕获到。
33.ES6的map跟set区别
区别
应用场景 Set 用于数据重组,Map 用于数据储存
Set:
成员不能重复
只有键值没有键名,类似数组
可以遍历,方法有 add, delete,has
- Size() 数据的长度
- Add() 添加某个值,返回Set结构本身
- Delete() 删除某个值,返回一个布尔值,表示是否删除成功
- Has() 查找某条数据,返回一个布尔值
- Clear() 清除所有成员,没有返回值
Map:
本质上是健值对的集合,类似集合
可以遍历,可以跟各种数据格式转换
34、js的继承:
- 原型链继承:让新实例的原型等于父实例
- 可继承:实例的构造函数的属性,父类构造函数属性,以及父类原型的属性
- 不可继承:父类实例的属性
- 借用构造函数继承:使用 apply()和 call()方法将父类构造函数引入子类函数
- 可继承:父类构造函数的属性
- 不可继承父类原型的属性
- 组合继承:将原型链和借用构造函数的技术组合在一块,从而发挥两者之长的一种继承模式
- 原型式继承:借助原型可以基于已有的对象创建新对象,类似复制了一个对象
- 寄生式继承:就是给原型式继承外面套个壳子,没用到原型
- 寄生组合式继承:通过借用函数来继承属性,通过原型链的混成形式来继承方法(常用)
35.vuex的辅助函数
36.覆盖elementui样式的几种办法
-
用 /deep/ 标签
例如 /deep/ .class{ 要覆盖的样式 } 。
-
重新写一个style标签可以在这个写scope的style标签下面再写一个style标签,专门写一个要覆盖的样式就好了 。类似下面图。

-
可以在vue项目中public文件夹下的index.html中引入一个外部样式,进行覆盖
37.vue2和vue3的生命周期
vue3的生命周期
beforeCreate: 在实例初始化之后、进行数据侦听和事件/侦听器的配置之前同步调用created:在实例创建完成后被立即同步调用beforeMount:在挂载开始之前被调用mounted:在实例挂载完成后被调用beforeUpdate:在数据发生改变后,DOM 被更新之前被调用updated:在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用beforeUnmount(在Vue2中是:beforeDestroy):在卸载组件实例之前调用unmounted(在Vue2中是:destroyed):卸载组件实例后调用
38.如何实现大屏功能
-
借助rem
-
使用postcss-pxtorem(postcss-pxtorem会将px转换为rem)
39.C3新特性
- 边框圆角
- box-sizing
- rgba颜色
- 渐变
- 过渡
- 动画
- 2D转换
- 3D转换
- flex布局
- 字体图标等
40.vue3.0之setup函数的理解
- 新的组件选项,作为组件中使用组合API的起点
它的执行在组件实例创建之前即vue2.x的beforeCreate执行
由第二点得知,setup函数中this还不是组件实例,即this就是undefined
在模板中使用的数据和函数,都需要setup将其return出来
setup只能是同步不能是异步
-
setup函数的形参,第一个参数,props是一个对象,包含了父组件传递给子组件所有的所有数据,在子组件中通过props属性配置进行接收,包含了配置并且声明的所有属性的对象。
-
setup函数的形参,第二个参数,context是一个对象,里面包含了以下三个属性
-
attrs:获取当前标签上的所有属性的对象,attrs是接收props没有声明的属性,如果子组件用props已经进行声明,那么子组件我们需要使用setup函数的props去接收,不能使用attrs
-
emit:事件分发,应用于子传父,如果将子组件的数传递给父级就需要使用该方法。
-
slots:插槽,带有dom属性,如果想把一段html或者一个组件当作属性传入到子组件中就使用slots,接收父级传递下来的html内容
41.如果后端传过来的数据列表过多怎么处理
-
通过 setTimeout 进行分页渲染
-
在渲染页面的时候,我们可以使用requestAnimationFrame来代替setTimeout,这样可以减少reflow次数,提高性能。
-
文档片段
-
延迟加载,懒加载
虽然后端一次返回这么多数据,但用户的屏幕只能同时显示有限的数据。所以我们可以采用延迟加载的策略,根据用户的滚动位置动态渲染数据。
-
跟后端进行协商
42.BFC
BFC (Block Formatting Context),即块级格式化上下文,它是页面中的一块渲染区域,并且有一套
属于自己的渲染规则:
- 内部的盒子会在垂直方向上一个接一个的放置
- 对于同一个BFC的俩个相邻的盒子的margin会发生重叠,与方向无关。
- 每个元素的左外边距与包含块的左边界相接触(从左到右),即使浮动元素也是如此
- BFC的区域不会与float的元素区域重叠
- 计算BFC的高度时,浮动子元素也参与计算
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然
- BFC 目的是形成一个相对于外界完全独立的空间,让内部的子元素不会影响到外部的元素
- 触发BFC的条件包含不限于: 根元素,即HTML元素 浮动元素:float值为left、right overflow值不为 visible,为 auto、scroll、hidden display的值为inline-block、inltable-cell、table-caption、table、inline-table、flex、inline-flex、grid、inline-grid position的值为absolute或fixed
43.清除浮动的方式
- 使用 CSS 中的 clear:both;(放一个空的标签,并设置上述 css,注意该标签必须是块
- 对于问题 1,添加如下样式,给父元素添加 clearfix 样式
- 给父级元素设置双伪元素
- 给父级元素设置 overflow:hidden;或 overflow:auto;本质是构建一个 BFC
44.flex:1
- flex-basis: 90px; 理解为
width为父容器的宽度。 - flex-grow: 1; 决定容器剩余空间的分配方式
- flex-shrink: 1; 决定容器超出空间的分配方式
45.跨域
- 定义:浏览器执行脚本时会检查是否同源,只有同源才会执行,不同源即为跨域
- 这里的同源是指访问的协议、域名、端口都相同
- 解决方法:
- jsonp:利用script标签不受同源策略的限制,但是只能是get请求,且有安全漏洞
- CORS跨域资源共享:通过服务器设置响应头实现跨域
- 代理:基于webpack中的webpack.config.js文件中在devServer对象中配置通过proxy
46、三次握手和四次挥手:
- 三次挥手:
- 发送端首先发送一个带有SYN标志地数据包给接收方
- 接收方接收后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了
- 发送方再回传一个带有ACK标志的数据包,代表我知道了,表示‘握手’结束
- 四次挥手:
- Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态
- Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态
- Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态
- Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手
47.简单描述下微信小程序的相关文件类型?
- WXML 是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。内 部主要是微信自己定义的一套组件
- WXSS 是一套样式语言,用于描述 WXML 的组件样式
- js 逻辑处理,网络请求
- json 小程序页面配置,如页面注册,页面标题及 tabBar
- app.json 必须要有这个文件,如果没有这个文件,项目无法运行,因为微信框架把这个作为 配置文件入口,整个小程序的全局配置。包括页面注册,网络设置,以及小程序的 window 背景色,配置导航条样式,配置默认标题
- app.js 必须要有这个文件,没有也是会报错!但是这个文件创建一下就行 ,什么都不需要写, 以后我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量
48.app.json 全局配置文件描述下?
pages : 用于存放当前小程序的所有页面路径
window : 小程序所有页面的顶部背景颜色,文字颜色配置。
tabBar : 小程序底部的Tab ,最多5个,最少2个。
49.简述微信小程序原理?
- 微信小程序采用 JavaScript、WXML、WXSS 三种技术进行开发,从技术讲和现有的前端开发差不多,但深入挖掘的话却又有所不同
- JavaScript:首先 JavaScript 的代码是运行在微信 App 中的,并不是运行在浏览器中,因此一 些 H5 技术的应用,需要微信 App 提供对应的 API 支持,而这限制住了 H5 技术的应用,且 其不能称为严格的 H5,可以称其伪 H5,同理,微信提供的独有的某些 API,H5 也不支持
- WXML:WXML 微信自己基于 XML 语法开发的,因此开发时,只能使用微信提供的现有标 签,HTML 的标签是无法使用的
- WXSS:WXSS 具有 CSS 的大部分特性,但并不是所有的都支持,而且支持哪些,不支持哪 些并没有详细的文档
- 微信的架构,是数据驱动的架构模式,它的 UI 和数据是分离的,所有的页面更新,都需要 通过对数据的更改来实现
- 小程序分为两个部分 webview 和 appService。其中 webview 主要用来展现 UI,appService 用来处理业务逻辑、数据及接口调用。它们在两个进程中运行,通过系统层 JSBridge 实现通信, 实现 UI 的渲染、事件的处理
50.分析下微信小程序的优劣势?
优势:
- 无需下载,通过搜索和扫一扫就可以打开
- 良好的用户体验:打开速度快
- 开发成本要比 App 要低
- 安卓上可以添加到桌面,与原生 App 差不多
- 为用户提供良好的安全保障。小程序的发布,微信拥有一套严格的审查流程,不能通过 审查的小程序是无法发布到线上的
劣势:
- 限制较多。页面大小不能超过 1M。不能打开超过 5 个层级的页面
- 样式单一。小程序的部分组件已经是成型的了,样式很难修改。例如:幻灯片、导航
- 推广面窄,不能分享朋友圈,只能通过分享给朋友,附近小程序推广。其中附近小程序也受到微信的限制
51.小程序选择器有哪些?
52.小程序常用组件?
view、swiper、scroll-view、text、button、input、image 等
53.Cookie跟Session区别
- 存储位置不同,Cookie数据保存在客户端里面,Session数据存储在服务器中,服务器存储相对于客户端会更为安全
- 存储的数据类型不同,两者都是key-value的数据结构,但是Cookie的value只能是字符串类型,Session的value可以是object的类型
- 存储的数据大小不同,Cookie受到浏览器的限制一般在4k左右,Session理论上来说只受内存的限制
- 生命周期的区别,Cookie一般是过期时间内生效,过期清除,Session取决于服务端的设定,
- 两者之间的联系,Session是Cookie的一种应用