复习
1.sass/scss和less区别?
sass是一种动态样式语言,又称为缩排语法,比css多出好些功能(比如变量、嵌套、运算、混入Mixin、继承、函数、颜色处理等)。但由于sass的缩排语法对于开发者来说并不直观,就对sass进行了改进变为scss,用{}取代原来的缩进。
less也是一种动态样式语言,对css赋予了动态样式特性,比如变量、继承、函数、运算等,less既可以在客户端上运行(支持IE 6+, Webkit, Firefox)也可以在服务端上运行(借助 Node.js)。
区别:
1.编译环境不一样:Less在JS上运行,Sass在Ruby上使用
2.变量符不一样,Less是@,而Scss是$。
3.输出设置,Less没有输出设置,Sass提供4中输出选项:nested, compact, compressed 和 expanded。
4.Sass支持条件语句,可以使用if{}else{},for{}循环等等。而Less不支持。5. 引用外部CSS文件
6.Sass和Less的工具库不同
2.响应式布局的实现方式有哪些?
媒体查询
百分比
自适应场景下的rem解决方案(设置viewport、rem2px和px2rem、postcss-loader)
参考:前端响应式布局原理与方案(详细版)
响应式布局的常用解决方案对比(媒体查询、百分比、rem和vw/vh)
3.ES6、ES7、ES8分别增加了哪些新特性?
ES6-10
es6:模块化(export/import)、let和const、解构赋值、扩展运算符、箭头函数、Array和Object的新增方法、promise、Set和Map、symbol
es7:Array.include() (类型与)、**(指数运算符,类似于Math.pow(2,10))
es8:async/awite、String pading(padStart(目标长度,占位内容),padEnd)
4.vue弹窗后如何禁止滚动条滚动?
vue自带修饰符解决:@touchmove.prevent绑定到弹窗模块
.stop:阻止事件冒泡
.prevent:阻止默认事件的发生
.capture:事件捕获
.self:只有事件自身可以触发
.once:事件只能触发一次
.navtive:某个组件的根元素上监听一个原生事件
5.函数的继承有哪些?
a.原型链继承:会导致引用值共享的问题
b.构造函数继承:解决引用值共享问题,但无法获取原型上的方法
c.组合式继承(伪金典继承):解决引用值共享问题和无法获取原型上方法的问题,但是又出现构造函数复用的问题
d.寄生组合式继承(金典继承):通过Object.create()创建父类原型副本,与父类原型完全隔离,解决了构造函数复用的问题
f:class(类)的extend关键字继承:
6.未登录前如何阻止手动修改url里的路由信息进行路由跳转?
利用全局前置守卫beforeEach做拦截判断,首先判断本地缓存中是否有token,如果没有就重定向到"/login",如果有token还需要排除用户输入的是"/login"(防止嵌套卡死),如果用户输入的不是"/login",就需要处理用户的所处角色的权限问题,判断vuex中保存的角色路由变量roles是否为[],如果是[]就需要通过接口调用用户信息,如果不为[]就直接进入"/home"
7.vue中发生数据更新页面没更新的情况要怎么处理?
a.Vue.set( target, propertyName/index, value )
b.Object.assign()
直接使用Object.assign()添加到对象的新属性不会触发更新
应创建一个新的对象,合并原对象和混入对象的属性
c.this.$forceUpdate迫使Vue 实例重新渲染
8.encodeURIComponent()和decodeURIComponent()
如果你使用的get方法提交肯定要考虑到输入项目的编码解码问题。
解决这个问题大家一般都使用encodeURI或者encodeURIComponent方法
encodeURIComponent:对字符进行编码
decodeURIComponent:对相应编码过的字符进行解码//传递 uni.navigateTo({ url: `/pagesJZ/receipt/applyReceipt?dataJson=` + >encodeURIComponent(JSON.stringify(item)) }); //接收 onLoad(option) { // #ifdef MP-WEIXIN || MP-TOUTIAO 只在微信和抖音编译器显示 let invoiceBasics = JSON.parse(decodeURIComponent(option.dataJson)); // #endif // #ifndef MP-WEIXIN || MP-TOUTIAO 除去微信和抖音编译器显示 let invoiceBasics = JSON.parse(option.dataJson); // #endif }
9.application/x-www-form-urlencoded与application/json的区别?
说明:这两个都是发送请求的格式说明
content-type:application/x-www-form-urlencoded。提交的数据是键值对:key-value格式
content-type:application/json。提交的数据是json格式
10.对uni.request()进行二次封装
/** * 封装请求(async await 封装uni.request) 对应portal 项目 * method post/get * endpoint 接口方法名 * data 所需传递参数 * load 是否需要loading */ async apiCall(method, endpoint, data, load) { if (load) { uni.showLoading({ title: '请稍候', mask: true }); } let token = uni.getStorageSync('token') || ''; let fullurl = this.BASEURI + endpoint; var contentType = 'application/x-www-form-urlencoded'; //var contentType = 'application/json;charset=UTF-8'; // data.authorization = token; let [error, res] = await uni.request({ url: fullurl, data: data, method: method, header: { 'content-type': contentType, 'authorization': token }, }); uni.hideLoading(); ...分情况判断接口返回的状态 }
11.ajax axios fetch的区别?
ajax
实现了 局部数据刷新
本身是针对MVC的编程,多用于jquery项目,不符合现在前端MVVM的浪潮axios
通过promise实现对ajax技术的一种封装
为MVVM框架而生 (vue react)
支持 Promise API
支持并发请求fetch
AJAX在ES6的替代品
fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。
兼容性差axios本身具有以下特征:
1.从浏览器中创建 XMLHttpRequest
2.支持 Promise API
3.客户端支持防止CSRF
4.提供了一些并发请求的接口(重要,方便了很多的操作)
5.从 node.js 创建 http 请求
6.拦截请求和响应
7.转换请求和响应数据
8.取消请求
9.自动转换JSON数据
PS:防止CSRF:就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略(协议、域名、端口号三者都相同),假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。
来源:ajax和axios、fetch的区别
浅谈CSRF攻击方式
Vue axios接口封装和api管理
12.sessionStorage、localStorage和cookie的区别?
相同点:都保存在浏览器上,且是同源的
区别:
13.css选择器优先级和权重
总结排序:!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
内联样式表的权值为 1000
ID 选择器的权值为 100
Class 类选择器的权值为 10
HTML 标签选择器的权值为 1
我们可以把选择器中规则对应做加法,比较权值,如果权值相同那就后面的覆盖前面的了,div.class的权值是1+10=11,而.test1 .test2的权值是10+10=20
14.css水平垂直居中有几种实现方式?
1.单行文本水平垂直居中:text-align:center;+line-height
2.绝对定位:子绝父相,子元素设置宽高并且top/left/right/bottom都为0 + margin:auto;
3.绝对定位:子绝父相,子元素top:50%+left:50%+translate(-50%,-50%)
4.flex:伸缩容器上设置dispaly:flex,伸缩项上设置margin:auto;
5.flex:伸缩容器上设置diaplay:flex;justify-content(主轴对齐方式):center;align-items(侧轴对齐方式):center;
css实现水平垂直居中的几种方式
15.冒泡排序
let arr = [5,4,3,2,1]; 轮数 5 4 3 2 1 比较的次数 每一轮比较的次数 第一轮 4 3 2 1 5 4次 arr.length-1-0 第二轮 3 2 1 4 5 3次 arr.length-1-1 第三轮 2 1 3 4 5 2次 arr.length-1-2 第四轮 1 2 3 4 5 1次 arr.length-1-3 数组一共5个数(arr.length) 一共经历轮数:arr.length-1 //先循环轮数,在每轮循环中对元素进行多次比较 for(let i = 0;i < arr.length-1;i++){ for(let j = 0; j < arr.length-1-i; j++){ if(arr[j] > arr[j+1]){ let temp = arr[j] arr[j] = arr[j+1] arr[j+1] = temp } } } console.log(arr); //[1,2,3,4,5]
16.翻转数组
let arr = [1,2,3,4,5,6,7,8] 交换次数 1 2 3 4 5 6 7 8 交换的两个数分别索引 交换1次 8 2 3 4 5 6 7 1 arr[0] arr[arr.length-1-0] 交换2次 8 7 3 4 5 6 2 1 arr[1] arr[arr.length-1-1] 交换3次 8 7 6 4 5 3 2 1 arr[2] arr[arr.length-1-2] 交换4次 8 7 6 5 4 3 2 1 arr[3] arr[arr.length-1-3] 数组总数:arr.length 对折交换次数:arr.length/2 //先循环交换的次数,返回借助第三方变量交换两个变量的值 for(let i = 0; i < arr.length/2;i++){ let temp = arr[i] arr[i] = arr[arr.length-1-i] arr[arr.length-1-i] = temp } console.log(arr); //[8,7,6,5,4,3,2,1]
17.数组的去重
let arr = [8,11,5,20,0,20,5,1,5,9,4,5] //1.创建一个新数组,将原数组的第一个元素添加到新数组 //2.循环遍历原数组,将数组中的元素和新数组中的元素进行比较,不相同时加入新数组 let temp = []; temp[0] = arr[0]; //循环原数组 for(let i = 0; i < arr.length;i++){ //遍历新数组 for(let j = 0; j < temp.length;j++){ if(temp[j] == arr[i]){ break; } //一直循环对比到新数组的最后一个元素还不相同时,将原数组中元素添加到新数组 if(j == temp.length-1){ temp.push(arr[i]) } } } console.log(temp) //[8, 11, 5, 20, 0, 1, 9, 4]
18.route和router的区别
$router :代表的是路由实例对象, 是路由操作对象(包含了路由的跳转方法),只写对象 $route :代表当前路由信息对象,只读对象(获取当前路由的参数) 传参可以使用params和query两种方式: 1.使用query传参使用path来引入路由 this.$router.push(path:'XXX',query:{key:vlaue}) 2.使用params传参只能用name来引入路由,即push里面只能是name:’xxxx’,不能是path:’/xxx’,因为params只能用name来引入路由,如果这里写成了path,接收参数页面会是undefined!!!this.$router.push(name:'XXX',params:{key:value}) 3.二者还有点区别,直白的来说query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会再地址栏中显示
19.请给出输出结果
async function async1(){ await async2(); console.log(2); } async function async2(){ console.log(3) } console.log(1) async1() setTimeout(()=>{ console.log(4) },0); new Promise((resolve)=>{ console.log(5); resolve(); }).then(function(){ console.log(6) }).then(function(){ console.log(7) }); console.log(8); 输出结果:1 3 2 5 8 6 7 4
20.JavaScript判断对象是否为空对象或空数组
1.判断是对象还是数组?
Object.prototype.toString.call(obj) === '[object Array]'
Object.prototype.toString.call(obj) === '[object Object]'
2.判断一个对象是否是空对象
JSON.stringify(obj) === '{}'
Object.keys(obj).length === 0
3.判断一个数组是否是空数组
length属性
21.vue3.0的6大亮点
1.性能比vue2.x快
2.按需编译,体积比2.x更小
3.新增组合API(类似于React Hooks)
4.更好的TS支持
5.暴露了自定义渲染API
6.具有更先进的组件vue3.0是如何变快的?
1.优化了diff算法,vur2.x是全量比较,3.0新增了静态标记,与上次虚拟节点进行对比的时候只比较带有静态标记的
2.静态提升:vue2.x中无论元素是否参与更新,都需要重新创建然后在渲染,但vue3.0中对不参与更新的元素做静态提升,元素只会创建一次,渲染的时候直接复用
3.事件监听缓存:vue2.x在默认情况下将onclick视为动态绑定(绑定静态标记),所以每次都会追踪它的变化去比较,但3.0中没有追踪它的变化,而是直接缓存起来复用
22.flex
6个设置在容器上的属性:
flex-direction:决定主轴的方向
flex-wrap:一条轴线排不下是否换行
flex-flow:是flex-direction和flex-wrap的简写,默认值:row nowrap
justify-content:定义项目在主轴上的对齐方式
align-items:定义项目在侧轴上的对齐方式
align-content:定义了多根轴线的对齐方式,如果项目还有一根轴线就不起作用6个设置在项目上的属性:
order:定义项目的排列顺序,越小的越靠前,默认值0
flex-grow:定义项目的放大比例,默认值0,即为存在剩余空间也不放大
flex-shrink:定义了项目的缩小比例,默认值1,即为空间不足该项目将缩小
flex-bases:定义了在分配多余空间之前,项目占据主轴的空间,默认值auto,即项目本来的大小
flex:是flex-grow,flex-shrink,flex-basis的简写,默认值0 1 auto
align-self:允许单个项目和其他项目不同的排雷方式
23.云打印业务流程
WebSocket
1.创建websocket对象 //url为指定连接的URL, [protocol]为可选的子协议 var websocket = new Websocket(url, [protocol]); 3)常用事件 websocket.open:连接建立时候触发 websocket.message:客户端接收服务端数据时触发 websocket.error:通信发生错误时触发 websocket.close:连接关闭时触发 websocket.send():使用连接发送数据
24.vue中hash和history区别?
- hash模式url带#号,history模式不带#号
- hash:#之前的内容会被包含在请求中,所以对于后端来说既是没有做到路由的全面覆盖也不会返回404
- history:前端的url必须和后端请求一致,否则就会报404
25.uniapp用过的api
应用生命周期:只能写在App.vue里监听页面生命周期
- onLaunch 当uni-app 初始化完成时触发(全局只触发一次)
- onShow 当 uni-app 启动,或从后台进入前台显示
- onHide 当 uni-app 从前台进入后台
- onError 当 uni-app 报错时触发
页面生命周期:
- onLoad:只加载一次,监听页面加载,其参数为上个页面传递的数据,参数类型为Object.
- onShow:监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面。
注意点:
从二级页面返回该页面时,onLoad不会再次加载,而onshow会重新加载。
onLoad先于onShow执行
onLoad页面的整个生命周期里,只执行一次
onShow页面的整个生命周期里,可执行多次,即每次显示都会执行
获取参数并且只请求一次的事件放在 onLoad 里。
当前页面需要时时刷数据的请求多次的事件放在 onShow 里。- onPullDownRefresh:下拉刷新
注意点:
需要在 pages.json 里,找到的当前页面的pages节点,并在 style 选项中开启enablePullDownRefresh。
当处理完数据刷新后,uni.stopPullDownRefresh 可以停止当前页面的下拉刷新。- stopPullDownRefresh:停止当前页面的下拉刷新
- onReachBottom:加载更多(上拉加载),页面滚动到底部拉去下一页数据
注意点:
需要在pages.json里定义某个页面底部的触发距离onReachBottomDistance。
如果用 scroll-view 组件时,这个方法不起作用,请按照 scroll-view 组件的页面触底加载更多的方法处理。- onShareAppMessage:用户点击右上角分享
- onShareTimeline:监听用户点击右上角转发到朋友圈
- onReady:监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发
26.js中的截取字符串的是哪个方法substring()、substr()、slice()
相同点:三个方法都是对字符串的截取,返回一个新的字符串,也不会对原字符串进行修改
不同点:
- substring(start,end):通过下标的方式截取,包头不包尾,start比end大会交换位置,参数存在负数会自动转为0(不支持负数)
- substr(start,length):通过下标和指定长度截取,start为负数就从右→左执行(-1是字符串的最后一个元素),length是负数,直接当0处理返回“”
- slice(start,end):通过下标截取,包头不包尾,支持负数
//当start或者end为负值时,定位方式和substr一直,从右往左数,从1开始 var a = '0123456789' a.slice(1,-1)//起始点从第1(包括)开始,结束点为从右往左数第1个(不包括) "12345678" //start到end的顺序始终是从左到右,如果最终start的位置在end的右边,那么返回''" a.slice(-2,1)//-2所在的位置是'8',1所在的位置是'1',从8=>1,方向相反,返回为空 "" a.slice(-2,-1)//-2所在的位置是'8',-1所在的位置是'9',从8=>9,方向正常,返回为'8' "8"
27.vue双向绑定的原理(Vue 响应式原理)
vue.js 采用数据劫持结合发布-订阅模式,通过 Object.defineproperty 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发响应的监听回调
28.理解MVVM
MVVM是View-Model-ViewModel的缩写,View代表用户视图层,Model代表数据模型,ViewModel:相当于业务逻辑层,作为连接View和Model的桥梁。
当数据变化的时,ViewModel监听到数据的变化,自动更新视图,当用户操作视图,ViewModel也能监听到视图的变化,通知数据改动,实现双向绑定。
29.Vue 组件 data 为什么必须是函数?
因为组件是复用,js的对象的引用类型,如果组件的data是一个对象,那么子组件中data就会相互污染
30.js的执行机制,宏任务与微任务
JS的执行是单线程的,它基于事件循环。事件循环分为以下几个步骤:
1.所有同步事件都在主线程上执行,形成一个“执行栈”
2.主线程之外还存在一个“任务队列”,只要异步任务有了执行结果就会加入到“任务队列”中
3.一旦“执行栈”中的所有同步任务执行完成后,系统就会读取“任务队列”,将“任务队列”中的事件加入“执行栈”开始执行
4.主线程不断重复以上三个过程
宏任务:主代码块,setTimeout,setInterval等
微任务:Promise,process.nextTick等