1.如何改变this指向?
-
call
-
apply
-
bind()
- apply():需要封装为数组[ ],传递实参值
- call():不需要数组,直接传递实参值
2.如何实现三个盒子同行三等分显示?
- flex(弹性盒子)
- float(浮动)
- 三个盒子都定位
- 左右两个盒子定位中间的盒子居中
- ??
3.如何实现一个旋转动画停留在最后一帧?
- ???
4.说说你了解的数组遍历的方法?
-
for循环
-
for in
-
for of
-
forEach
-
map
-
通过指定的函数处理数组中的每一个元素,并返回处理后的新数组
需要传递自定义函数
map调用自定义函数的次数等于元素的的个数
核心:遍历数组中的每一个元素,根据逻辑加工后返回
-
-
*filter
-
方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
根据自定义函数,过滤数组中的元素
返回新的数组,原数组不变
条件为true元素返回,为false元素过滤
-
-
*reduce
-
参数:
- total:初始值为数组中的第一个元素,其余为每次return返回的值
- value: 每执行一次,放入非第一个元素的所有值
- reduce返回return返回的值
-
5.如何实现循环未结束前找到自己想要的数据并跳出循环?
- if判断
- *filter
- *replace
- ???
6.Vue中父子如何让传值?
- 父传子:props
- 子传父:$emit
- .sync
- prived/inject
- 事件总线
- vuex
7.vuex中mutations与actions的区别?
- mutations:只能实行同步操作
- actions可以执行异步操作
- actions实质上还是执行了mutations操作
- 由于mutations的机制实际上是快照机制,所以mutations只能是同步不可以异步
8.说一说await/async
- 异步的语法糖
- await:等待异步执行完成
- pormise:???
9.举例一下你项目中的业务的代码思路
- ???
10.说一下git有哪些命令操作?
- 原理:??
- git init
- git push
- git pull
- git add 文件名
- git commit -m ‘叙述内容’
11.一个本地仓库如何对应多个远程仓库
\1. 克隆某个远程仓库的代码到本地
git clone http://......
// 或者
git clone git@....
\2. 查看当前远程仓库地址
// 查看需要添加的远程仓库的地址
git remote -v
\3. 给本地仓库添加远程仓库地址
git remote add 新远程仓库名 新远程仓库地址
4.将本地代码推动到新的远程仓库对应的分支
// 在新远程仓库,创建了一个同名分支
git push 新仓库名 本地分支名
12.vue的生命周期?
13.MongDB与mySQL的区别,什么情况下使用mongDB?
- mySQL:关系型数据库
- mongDB:非关系型数据库,结构与非结构之间的产物
- mongDB:不是主数据库
- 制作分布式数据库的时候用mongDB
14.vue如果需要同时并发3个请求,并同时拿到数据进行处理,如何处理?(未理解)
-
1.Promise
Promise.then.then… 有点反反复复
Promise.all() 这个可以 但是自身API占了不少 所以对逻辑反而不太明确
2.Generator
类似一个容器,里面保存着某个未来才会结束的事情(一个异步事件)。 从语法上来看,是一个对象,可以获取异步操作的消息、 稍微有点打脑壳(菜鸟表示不会用)
3.async 这个很棒棒
//使用async await后跟的是Promise 需要 return
async function getDatas(){
return await Promise.all([allschoolList(), roleList()])
}getDatas().then(res => {//如果上面的请求都是resolve的时候就可以…
console.log(res) //{[…],[…]} 拿到结果
})//不使用时 …
//先请求两个 getData
this.getData()
this.getsubjecttree(data[0].school_id);
//然后在请求 拿到数据处理之后 再继续
querySubject(data[0].id).then(res => {
if (res && res.data) {
//.....省略N行代码
//处理完上面之后 再继续请求 最后才绑定表单
getOrganListTree({organization_id:or_id}).then(res => {
if(res.data.success){
this.revisingForm = Object.assign({}, data[0]);
this.revisingForm.organization_id = res.data.data.organization_ids
this.revisingForm.subjects = _subjects;
if(this.roleList && this.roleList.length) {
this.revisingForm.duty_ids = duty_ids;
}
}
})
}
});
上面的是 完全无关的请求 需要同时请求的 可以Promise.all
如果是有关联的,就这样
//阮一峰老师教程里的例子
async function getStockPriceByName(name) {
const symbol = await getStockSymbol(name);
const stockPrice = await getStockPrice(symbol);
return stockPrice;
}
getStockPriceByName('goog').then(function (result) {
console.log(result);
});
15.防抖,节流
函数防抖
<script>
let ms = null;
window.onscroll = play; // 当全局的滚动条移动时,触发play属性。(思考:如果调用的不是play对象而是play对象的返回值,那么值就会在开始确认下来,并且再也不会变化。)
function play(){
clearTimeout(ms); // 滚动条滚动的时候不停的触发关闭定时器事件
ms = setTimeout(function(){
console.log(document.documentElement.scrollTop || document.body.scrollTop)
},1); // 当滚动条在该位置路过200ms后触发,但是由于上方有关闭定时器,所以只有滚动条停止后才触发
};
</script>
函数防抖-优化
<script>
window.onscroll = play(); // 当全局的滚动条移动时,触发play属性
function play() {
let ms = null;
return function () {
clearTimeout(ms);
ms = setTimeout(function () {
console.log(
document.documentElement.scrollTop || document.body.scrollTop
);
}, 200);
};
}
</script>
函数节流
<script>
let old_date = Date.now(); // 获取程序运行时的时间
window.onscroll = play;
function play() {
let new_date = Date.now(); // 执行这句程序时的时间
if (new_date - old_date >= 400) {
console.log(
document.documentElement.scrollTop || document.body.scrollTop
);
old_date = Date.now(); // 更新程序运行时的时间
}
}
</script>
函数节流-优化
<script>
window.onscroll = play();
function play(){
let lod_date = Date.now() // 获取程序运行时的时间
return function(){
let new_date = Date.now(); // 执行这句程序时的时间
if((new_date - old_date) == 400){
console.log(document.documentElement.scrollTop || document.body.scrollTop);
old_date = Date.now(); // 更新程序运行时的时间
}
}
}
</script>
16.localStorage、sessionStorage、cookie区别?
一、cookie和session
cookie和session都是用来跟踪浏览器用户身份的会话方式。
区别:
1、保持状态:cookie保存在浏览器端,session保存在服务器端
2、使用方式:
(1)cookie机制:如果不在浏览器中设置过期时间,cookie被保存在内存中,生命周期随浏览器的关闭而结束,这种cookie简称会话cookie。如果在浏览器中设置了cookie的过期时间,cookie被保存在硬盘中,关闭浏览器后,cookie数据仍然存在,直到过期时间结束才消失。
Cookie是服务器发给客户端的特殊信息,cookie是以文本的方式保存在客户端,每次请求时都带上它
(2)session机制:当服务器收到请求需要创建session对象时,首先会检查客户端请求中是否包含sessionid。如果有sessionid,服务器将根据该id返回对应session对象。如果客户端请求中没有sessionid,服务器会创建新的session对象,并把sessionid在本次响应中返回给客户端。通常使用cookie方式存储sessionid到客户端,在交互中浏览器按照规则将sessionid发送给服务器。如果用户禁用cookie,则要使用URL重写,可以通过response.encodeURL(url) 进行实现;API对encodeURL的结束为,当浏览器支持Cookie时,url不做任何处理;当浏览器不支持Cookie的时候,将会重写URL将SessionID拼接到访问地址后。
3、存储内容:cookie只能保存字符串类型,以文本的方式;session通过类似与Hashtable的数据结构来保存,能支持任何类型的对象(session中可含有多个对象)
4、存储的大小:cookie:单个cookie保存的数据不能超过4kb;session大小没有限制。
5、安全性:cookie:针对cookie所存在的攻击:Cookie欺骗,Cookie截获;session的安全性大于cookie。
原因如下:(1)sessionID存储在cookie中,若要攻破session首先要攻破cookie;
(2)sessionID是要有人登录,或者启动session_start才会有,所以攻破cookie也不一定能得到sessionID;
(3)第二次启动session_start后,前一次的sessionID就是失效了,session过期后,sessionID也随之失效。
(4)sessionID是加密的
(5)综上所述,攻击者必须在短时间内攻破加密的sessionID,这很难。
6、应用场景:
cookie:(1)判断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码)。如果我们删除cookie,则每次登录必须从新填写登录的相关信息。
(2)保存上次登录的时间等信息。
(3)保存上次查看的页面
(4)浏览计数
session:Session用于保存每个用户的专用信息,变量的值保存在服务器端,通过SessionID来区分不同的客户。
(1)网上商城中的购物车
(2)保存用户登录信息
(3)将某些数据放入session中,供同一用户的不同页面使用
(4)防止用户非法登录
7、缺点:cookie:(1)大小受限
(2)用户可以操作(禁用)cookie,使功能受限
(3)安全性较低
(4)有些状态不可能保存在客户端。
(5)每次访问都要传送cookie给服务器,浪费带宽。
(6)cookie数据有路径(path)的概念,可以限制cookie只属于某个路径下。
session:(1)Session保存的东西越多,就越占用服务器内存,对于用户在线人数较多的网站,服务器的内存压力会比较大。
(2)依赖于cookie(sessionID保存在cookie),如果禁用cookie,则要使用URL重写,不安全
(3)创建Session变量有很大的随意性,可随时调用,不需要开发者做精确地处理,所以,过度使用session变量将会导致代码不可读而且不好维护。
二、WebStorage
WebStorage的目的是克服由cookie所带来的一些限制,当数据需要被严格控制在客户端时,不需要持续的将数据发回服务器。
WebStorage两个主要目标:(1)提供一种在cookie之外存储会话数据的路径。(2)提供一种存储大量可以跨会话存在的数据的机制。
HTML5的WebStorage提供了两种API:localStorage(本地存储)和sessionStorage(会话存储)。
1、生命周期:localStorage:localStorage的生命周期是永久的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。
sessionStorage的生命周期是在仅在当前会话下有效。sessionStorage引入了一个“浏览器窗口”的概念,sessionStorage是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。但是sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage也是不一样的。
2、存储大小:localStorage和sessionStorage的存储数据大小一般都是:5MB
3、存储位置:localStorage和sessionStorage都保存在客户端,不与服务器进行交互通信。
4、存储内容类型:localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理
5、获取方式:localStorage:window.localStorage;;sessionStorage:window.sessionStorage;。
6、应用场景:localStoragese:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。sessionStorage:敏感账号一次性登录;
WebStorage的优点:
(1)存储空间更大:cookie为4KB,而WebStorage是5MB;
(2)节省网络流量:WebStorage不会传送到服务器,存储在本地的数据可以直接获取,也不会像cookie一样美词请求都会传送到服务器,所以减少了客户端和服务器端的交互,节省了网络流量;
(3)对于那种只需要在用户浏览一组页面期间保存而关闭浏览器后就可以丢弃的数据,sessionStorage会非常方便;
(4)快速显示:有的数据存储在WebStorage上,再加上浏览器本身的缓存。获取数据时可以从本地获取会比从服务器端获取快得多,所以速度更快;
(5)安全性:WebStorage不会随着HTTP header发送到服务器端,所以安全性相对于cookie来说比较高一些,不会担心截获,但是仍然存在伪造问题;
(6)WebStorage提供了一些方法,数据操作比cookie方便;
setItem (key, value) —— 保存数据,以键值对的方式储存信息。
getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。
removeItem (key) —— 删除单个数据,根据键值移除对应的信息。
clear () —— 删除所有的数据
key (index) —— 获取某个索引的key
16.原型链继承?
- 优点:
- 子类的实例是他本身,也是他的父类
- 可以继承父类的所有实例
- 缺点:
- 单继承
- 子类的实例不能给父类传参
17.js中有多少在继承方法?
- 原型链继承
- 构造继承
- 原型 + 构造继承
- 寄生继承
- 寄生式组合继承
18.uni-app如何打包?
- 在微信小程序上点击提交按钮
19.关于nginx你了解多少?
- 正向反向服务器代理
20.web前端安全?
- XSS(跨域脚本攻击)
- md5加密
- CSRF(跨站请求伪造)
21.怎么加快前端的响应速度?
- 懒加载
- 本地保存
- 所有的组件、代码,能公用的公用
22.网络协议问题?
- ??
23.js的垃圾回收机制?
- 检测那些变量已经不存在引用了
24.vue图片懒加载
第一步: 安装
npm install vue-lazyload --save
第二步: 全局注册
main.js 文件
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
// 配置项
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'dist/error.png',
loading: 'dist/loading.gif',
attempt: 1
})
键 | 描述 | 默认 | 选项 |
---|---|---|---|
preLoad | 表示lazyload的元素,距离页面底部距离的百分比.计算值为(preload - 1) | 1.3 | Number |
error | 加载失败后图片地址 | ‘data-src’ | String |
loading | 加载时图片地址 | ‘data-src’ | String |
attempt | 图片加载失败后的重试次数 | 3 | Number |
listenEvents | 触发懒加载的事件 | [‘scroll’,‘wheel’,‘mousewheel’,‘resize’,‘animationend’,‘transitionend’,‘touchmove’] | 无 |
adapter | 注册img 的loading,loaded,error三个状态的回调函数,参数会暴露懒加载的img元素,可以对其进行作. | { } | 无 |
filter | img未加载之前,解析到src 的时候注册的回调函数.可以在加载图片之前,对src进行修改.注册在filter下的所有的函数都会执行 | {} | 无 |
lazyComponent | 是否启用懒加载组件.组件中的内容只有在出现在preload的位置中才会加载组件.这个lazyloadComponent组件有个缺点就是,组件在加载前是什么都不渲染的,这样子的话,有可能会影响布局,以及加载前到加载后的切换不好,有点突兀和生硬. | false | Boolean |
dispatchEvent | 触发dom事件 | false | Number |
throttleWait | 等待时长 | 200 | Number |
observer | 等待时长 | 是否启用IntersectionObserver,这个api有兼容问题 | Number |
observerOptions | IntersectionObserver选项 | { rootMargin: ‘0px’,threshold: 0.1 } | 无 |
silent | 不打印调试信息 | true | Boolean |
因为src中的文件会被webpack编译,assets文件夹中的图片地址,会在编译过程中重命名。vue-lazyload是在main.js文件中引入,不会被webpack进行编译,因此vue-lazyload无法获得正确的图片地址,所以直接写相对地址就无法获取到图片正确地址
第三步: 写loading图片的样式(不是必须, 视情况而定)
img[lazy="loading"]{
display:block;
width:50px !important;
height:50px !important;
margin:0 auto;
}
第四步: 使用 ( :src—>v-lazy )
<div class="lazyLoad">
<ul id="container">
<li v-for="img in arr">
<img v-lazy="img.thumbnail_pic_s">
</li>
</ul>
</div>
这里有个坑需要注意
如设置了翻页功能,且每一页都是请求的数据进行渲染。
会发现其他的数据都变了,唯独图片还是原来的图片。
由于使用的数据是父组件传过来的,第一个想到父组件axios异步请求的数据导致子组件可能数据没有动态更新。但监听了下数据,发现确实是改变了 .
解决办法只要加个key就行, 如下代码
<ul>
<li v-for="img in list">
<img v-lazy="img.src" :key="img.src" >
</li>
</ul>
25.虚拟DOM
纯js对象
优点:
- 减少对原生Dom的调用
- 解决真实Dom频繁重绘与回流的问题
缺点:
1. 性能到此为止
一、真实DOM和其解析流程?
浏览器渲染引擎工作流程都差不多,大致分为5步,创建DOM树——创建StyleRules——创建Render树——布局Layout——绘制Painting
第一步,用HTML分析器,分析HTML元素,构建一颗DOM树(标记化和树构建)。
第二步,用CSS分析器,分析CSS文件和元素上的inline样式,生成页面的样式表。
第三步,将DOM树和样式表,关联起来,构建一颗Render树(这一过程又称为Attachment)。每个DOM节点都有attach方法,接受样式信息,返回一个render对象(又名renderer)。这些render对象最终会被构建成一颗Render树。
第四步,有了Render树,浏览器开始布局,为每个Render树上的节点确定一个在显示屏上出现的精确坐标。
第五步,Render树和节点显示坐标都有了,就调用每个节点paint方法,把它们绘制出来。
**DOM树的构建是文档加载完成开始的?**构建DOM数是一个渐进过程,为达到更好用户体验,渲染引擎会尽快将内容显示在屏幕上。它不必等到整个HTML文档解析完毕之后才开始构建render数和布局。
**Render树是DOM树和CSSOM树构建完毕才开始构建的吗?**这三个过程在实际进行的时候又不是完全独立,而是会有交叉。会造成一边加载,一遍解析,一遍渲染的工作现象。
CSS的解析是从右往左逆向解析的(从DOM树的下-上解析比上-下解析效率高),嵌套标签越多,解析越慢。
webkit渲染引擎工作流程
二、JS操作真实DOM的代价!
用我们传统的开发模式,原生JS或JQ操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。在一次操作中,我需要更新10个DOM节点,浏览器收到第一个DOM请求后并不知道还有9次更新操作,因此会马上执行流程,最终执行10次。例如,第一次计算完,紧接着下一个DOM更新请求,这个节点的坐标值就变了,前一次计算为无用功。计算DOM节点坐标值等都是白白浪费的性能。即使计算机硬件一直在迭代更新,操作DOM的代价仍旧是昂贵的,频繁操作还是会出现页面卡顿,影响用户体验。
三、为什么需要虚拟DOM,它有什么好处?
Web界面由DOM树(树的意思是数据结构)来构建,当其中一部分发生变化时,其实就是对应某个DOM节点发生了变化,
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。如前,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。**所以,**用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。
四、实现虚拟DOM
例如一个真实的DOM节点。
真实DOM
我们用JS来模拟DOM节点实现虚拟DOM。
虚拟DOM
其中的Element方法具体怎么实现的呢?
Element方法实现
第一个参数是节点名(如div),第二个参数是节点的属性(如class),第三个参数是子节点(如ul的li)。除了这三个参数会被保存在对象上外,还保存了key和count。其相当于形成了虚拟DOM树。
虚拟DOM树
有了JS对象后,最终还需要将其映射成真实DOM
虚拟DOM对象映射成真实DOM
我们已经完成了创建虚拟DOM并将其映射成真实DOM,这样所有的更新都可以先反应到虚拟DOM上,如何反应?需要用到Diff算法。
两棵树如果完全比较时间复杂度是O(n^3),但参照《深入浅出React和Redux》一书中的介绍,React的Diff算法的时间复杂度是O(n)。要实现这么低的时间复杂度,意味着只能平层的比较两棵树的节点,放弃了深度遍历。这样做,似乎牺牲掉了一定的精确性来换取速度,但考虑到现实中前端页面通常也不会跨层移动DOM元素,这样做是最优的。
深度优先遍历,记录差异
。。。。
Diff操作
在实际代码中,会对新旧两棵树进行一个深度的遍历,每个节点都会有一个标记。每遍历到一个节点就把该节点和新的树进行对比,如果有差异就记录到一个对象中。
下面我们创建一棵新树,用于和之前的树进行比较,来看看Diff算法是怎么操作的。
old Tree
new Tree
平层Diff,只有以下4种情况:
1、节点类型变了,例如下图中的P变成了H3。我们将这个过程称之为REPLACE。直接将旧节点卸载并装载新节点。旧节点包括下面的子节点都将被卸载,如果新节点和旧节点仅仅是类型不同,但下面的所有子节点都一样时,这样做效率不高。但为了避免O(n^3)的时间复杂度,这样是值得的。这也提醒了开发者,应该避免无谓的节点类型的变化,例如运行时将div变成p没有意义。
2、节点类型一样,仅仅属性或属性值变了。我们将这个过程称之为PROPS。此时不会触发节点卸载和装载,而是节点更新。
查找不同属性方法
3、文本变了,文本对也是一个Text Node,也比较简单,直接修改文字内容就行了,我们将这个过程称之为TEXT。
4、移动/增加/删除 子节点,我们将这个过程称之为REORDER。看一个例子,在A、B、C、D、E五个节点的B和C中的BC两个节点中间加入一个F节点。
例子
我们简单粗暴的做法是遍历每一个新虚拟DOM的节点,与旧虚拟DOM对比相应节点对比,在旧DOM中是否存在,不同就卸载原来的按上新的。这样会对F后边每一个节点进行操作。卸载C,装载F,卸载D,装载C,卸载E,装载D,装载E。效率太低。
粗暴做法
如果我们在JSX里为数组或枚举型元素增加上key后,它能够根据key,直接找到具体位置进行操作,效率比较高。常见的最小编辑距离问题,可以用Levenshtein Distance算法来实现,时间复杂度是O(M*N),但通常我们只要一些简单的移动就能满足需要,降低精确性,将时间复杂度降低到O(max(M,N))即可。
最终Diff出来的结果
映射成真实DOM
虚拟DOM有了,Diff也有了,现在就可以将Diff应用到真实DOM上了。深度遍历DOM将Diff的内容更新进去。
根据Diff更新DOM
根据Diff更新DOM
我们会有两个虚拟DOM(js对象,new/old进行比较diff),用户交互我们操作数据变化new虚拟DOM,old虚拟DOM会映射成实际DOM(js对象生成的DOM文档)通过DOM fragment操作给浏览器渲染。当修改new虚拟DOM,会把newDOM和oldDOM通过diff算法比较,得出diff结果数据表(用4种变换情况表示)。再把diff结果表通过DOM fragment更新到浏览器DOM中。
虚拟DOM的存在的意义?vdom 的真正意义是为了实现跨平台,服务端渲染,以及提供一个性能还算不错 Dom 更新策略。vdom 让整个 mvvm 框架灵活了起来
Diff算法只是为了虚拟DOM比较替换效率更高,通过Diff算法得到diff算法结果数据表(需要进行哪些操作记录表)。原本要操作的DOM在vue这边还是要操作的,只不过用到了js的DOM fragment来操作dom(统一计算出所有变化后统一更新一次DOM)进行浏览器DOM一次性更新。其实DOM fragment我们不用平时发开也能用,但是这样程序员写业务代码就用把DOM操作放到fragment里,这就是框架的价值,程序员才能专注于写业务代码**。**
26.使用v-for的时候为什么要添加key?
- key属性可以用来提升v-for渲染的效率,vue中使用v-for渲染数据的时候,并不会去改变原有的元素和数据,而是创建新的元素,再把新的数据渲染进去。
- key的作用主要是为了高效的更新虚拟DOM。
- 另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果
27.闭包的概念,优缺点,怎么使用?
- 概念:内部变量供外部使用,(一个函数的私有函数被内部的函数存储到内存中)
- 在哪里使用:
- 节流
- 设计模式,单体模式
- 优缺点:
- 优点:
- 变量长期驻扎到内存中
- 避免全局变量污染
- 私有成员的存在
- 缺点:
- 容易造成内存泄漏(无法被垃圾回收机制回收)
- 优点:
28.em与px的区别?
- em是相对于父节点的
- px是规定的单位
29.promise,内部源码是同步还是异步?
- 异步
30.用过响应式布局吗?弹性布局的原理?
- 弹性布局的原理:类似于流式布局(百分比布局)
31.定时器概念?
延迟一段时间后执行(代码)
32.css布局
- 流式布局
- 表格
- 弹性盒子
- 固定布局
- 浮动布局
- 网格布局(row、col)
- 列布局
33.微信小程序常用的请求
wx.request
34.js或jq怎么添加标签属性
js方式创建标签及添加属性
<script>
var tr = document.getElementById('tr_id1') //根据id属性获取tr标签
var td = document.createElement('td') //创建td标签
td.setAttribute('aa','td_aa'); //设置标签属性aa=‘td_aa’
td.innerHTML = '哈哈哈哈'; //设置td标签文本值为'哈哈哈哈'
tr.appendChild(td); //将新创建的td标签插到tr标签中
</script>
jquery方式创建标签及添加属性
1 <script>
2 var td = $("<td>"); //创建td标签
3 td.attr('aa','td_aa'); //设置标签属性aa=‘td_aa’
4 td.html('哈哈哈哈'); //设置td标签文本值为'哈哈哈哈'
5 $("#tr_id1").append(td); //将新创建的td标签插到id为tr_id1的标签中
6 </script>
<script>
//保存一个属性
$("a").attr("title","爱你");
//获取一个属性
console.log($("a").attr("title"))
//保存多个属性
$("a").attr({
id:"woniu",
class:"xiao woniu"
})
//删除属性
$("a").removeAttr("class")
</script>
35.less与scss的区别
- less可以在服务器端也可以在客户端(编译)
- scss只能在服务器端(编译)
- less编译完成后不会产生一个同名的css文件,scss编译完成后会产生一个同名的scss文件
36.定位了解吗
- 相对定位(relative):不脱离文档流相对于自身定位
- 绝对定位(absolute):脱离文档流,相对于祖先元素上的relative定位
- 固定定位(fixed):脱离文档流,相对于浏览器串口定位
- 默认值(static):不脱离文档流
37.项目打包白屏处理
1.设置router.js中的mode:‘hash’
2.配置vue.config.js文件, publicPath: ‘./’
在config文件夹中找到index.js打开,把build下的assetsPublicPath: '/'改成assetsPublicPath: ‘./’。dev下的不用改
①使用v-text渲染数据
②使用{{}}语法渲染数据,但是同时使用v-cloak指令(用来保持在元素上直到关联实例结束时候进行编译),v-cloak要放在什么位置呢,v-cloak并不需要添加到每个标签,只要在el挂载的标签上添加就可以
38.用什么与后端交互
- axios
- jsonp
- ajax
39.项目怎么做的导航权限控制(???)
- 动态路由配置:后台根据用户权限,将路由配置以数据返回
40.如何更新小程序页面中的值
this.setData({
name:XXX // 更新name属性
})
41.ajax如何使用
function ajax(url,method,data,callback){
//1.创建XMLHttpRequest对象:xhr
let xhr = new XMLHttpRequest();
//2.打开通道
xhr.open(method,url);
if(method.toUpperCase()=='POST'){
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
}
//3.发送请求
xhr.send(data);
//4.通过事件来获取响应结果
xhr.onreadystatechange=function(){
//5.readyState=4说明整个请求已经完成了
if(this.readyState==4){
//6.获取HTTP状态码,如果是200则成功
if(this.status==200){
let res = JSON.parse(this.response)
if(res.errcode){
alert(res.errmsg)
return;
}
//将结果传给回调函数
callback(res);
}else{
//7.如果状态码不是200,我们就打印状态文本,例如:404 文本就是 Not Found
console.log(this.statusText)
}
}
}
}
42.浏览器的标准盒模型与怪异盒模型
- 标准盒模型:
- box-content
- 浏览器按照w3c的标准解析执行代码
- 怪异盒模型
- box-border
- 浏览器按照自己的方式解析执行代码
- 图片元素的垂直对齐方式 对于行内元素和table-cell元素,标准模式下vertical-align属性默认值是baseline,而在怪异模式下,table单元格中的图片的vertical-align属性默认值是bottom,因此在图片底部会有几像素的空间
- baseline:使元素的基线与父元素的基线对齐。
- bottom:使元素及其后代元素的底部与整行的底部对齐。
- 元素中的字体 css中font的属性都是可以继承的,怪异模式下,对于table元素,字体的某些元素不能从其他封装元素继承中得到,特别是font-size属性
- 内联元素的尺寸 标准模式下,non-replaced inline元素无法自定义大写,怪异模式下,定义元素的宽高会影响元素的尺寸
- 元素的百分比高度 当一个元素使用百分比高度时,在标准模式下,高度取决于内容变化,在怪异迷失下,百分比被准确应用
- 元素溢出的处理 标准模式下,overflow取值默认值为visible,在怪异模式下,这个溢出会被当做扩展box对待,就是元素的大小由内容决定,溢出不会裁剪,元素框自动调整,包含溢出内容
43.react与vue的区别
- vue数据双向(通过劫持实现),react数据单向(可以使用受控来实现数据双向)
- vue渐进式开发(轻量化),react是jsx模板语法的纯js库
- vue的双向是根据object.defindProperty进行对于属性getset的劫持
*44讲一下promise
一、什么是Promise?我们用Promise来解决什么问题?
我们都知道,Promise是承诺的意思,承诺它过一段时间会给你一个结果。
Promise 是一种解决异步编程的方案,相比回调函数和事件更合理和更强大。
从语法上讲,promise是一个对象,从它可以获取异步操作的消息;
二、promise有三种状态:pending 初始状态也叫等待状态,fulfiled成功状态,rejected失败状态;状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
三、Promise的两个特点
1、Promise对象的状态不受外界影响
2、Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,
四、Promise的三个缺点
1)无法取消Promise,一旦新建它就会立即执行,无法中途取消
2)如果不设置回调函数,Promise内部抛出的错误,不会反映到外部
3)当处于pending(等待)状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成
promise是用来解决两个问题的:
1.回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
2.promise可以支持多并发的请求,获取并发请求中的数据
这个promise可以解决异步的问题,本身不能说promise是异步的
45请简述async的用法
Async就是generation和promise的语法糖,async就是将generator的*换成async,将yiled换成await
函数前必须加一个async,异步操作方法前加一个await关键字,意思就是等一下,执行完了再继续走,注意:await只能在async函数中运行,否则会报错
Promise如果返回的是一个错误的结果,如果没有做异常处理,就会报错,所以用try…catch捕获一下异常就可以了
es6新特性
??
vue响应式原理
??
vue用到了那些js设计模式
- 单例模式
- 观察-订阅模式
- 工厂模式
vue那些数据劫持不到
数组:(解决方案)
- $set
- ???
如何阻止数据双向
- Object.freeze(数据名)
vue环境开发中的data为什么是函数?
- 组件之间是对象,容易造成数据混淆
- 避免数据污染
vue中为什么是this.变量,不是this.data.变量
forEach与map的区别
- map有返回值,forEach没有返回值
- 共同点:
- 都是循环遍历数组中的每一项。
- forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前项的索引index,原始数组input。
- 匿名函数中的this都是指Window。
- 只能遍历数组。
new原理
1.创建一个空对象
var obj={}
2.这个新对象继承原构造函数的原型
obj._proto_=Constructor.prototype
3.更改this指向,为对象设置属性
let result=Constructor.apply(obj,...args)
4.返回新对象
return result instanceof Object ? result : obj
vuex内的数据在页面刷新后,如何保存?
- 缓存
- 发送到服务器
小程序组件内添加视频或者别的页面
- view
- web-view
- 类似于??
*微信支付流程
Echars截取数据进行渲染
- 在data上
- ???
ES6
let、const、模板字符串(反引号)、扩展运算符、默认值、解构赋值、set集合、map集合
数组、Set、Map 对比
Array | 有序集合 | 下标唯一,值可重复,下标是有序的 |
---|---|---|
Set | 无序集合 | 值维一,没有下表 |
Map | 无序集合 | 键值对,键唯一,值可重复 |
W3C标准
js的几大规范
- amd – 内置函数defind暴漏
- commonJS服务端模块化
- umd
- 支持amd与commonJS
- ???
- 代码写法规范
如何做用户的优化
-
代码复用
-
路由懒加载
-
图片懒加载
-
js原生
- 获得视窗的距离(window.innerHeight)
- 获得图片距离视窗顶部的距离(getBoundingClientRect().top)
- 判断图片是否进入视窗
-
vue
-
第一步: 安装
npm install vue-lazyload --save
第二步: 全局注册
main.js 文件 import VueLazyload from 'vue-lazyload' Vue.use(VueLazyload) // 配置项 Vue.use(VueLazyload, { preLoad: 1.3, error: 'dist/error.png', loading: 'dist/loading.gif', attempt: 1 })
键 描述 默认 选项 preLoad 表示lazyload的元素,距离页面底部距离的百分比.计算值为(preload - 1) 1.3 Number error 加载失败后图片地址 ‘data-src’ String loading 加载时图片地址 ‘data-src’ String attempt 图片加载失败后的重试次数 3 Number listenEvents 触发懒加载的事件 [‘scroll’,‘wheel’,‘mousewheel’,‘resize’,‘animationend’,‘transitionend’,‘touchmove’] 无 adapter 注册img 的loading,loaded,error三个状态的回调函数,参数会暴露懒加载的img元素,可以对其进行作. { } 无 filter img未加载之前,解析到src 的时候注册的回调函数.可以在加载图片之前,对src进行修改.注册在filter下的所有的函数都会执行 {} 无 lazyComponent 是否启用懒加载组件.组件中的内容只有在出现在preload的位置中才会加载组件.这个lazyloadComponent组件有个缺点就是,组件在加载前是什么都不渲染的,这样子的话,有可能会影响布局,以及加载前到加载后的切换不好,有点突兀和生硬. false Boolean dispatchEvent 触发dom事件 false Number throttleWait 等待时长 200 Number observer 等待时长 是否启用IntersectionObserver,这个api有兼容问题 Number observerOptions IntersectionObserver选项 { rootMargin: ‘0px’,threshold: 0.1 } 无 silent 不打印调试信息 true Boolean 因为src中的文件会被webpack编译,assets文件夹中的图片地址,会在编译过程中重命名。vue-lazyload是在main.js文件中引入,不会被webpack进行编译,因此vue-lazyload无法获得正确的图片地址,所以直接写相对地址就无法获取到图片正确地址
第三步: 写loading图片的样式(不是必须, 视情况而定)
img[lazy="loading"]{ display:block; width:50px !important; height:50px !important; margin:0 auto; }
第四步: 使用 ( :src—>v-lazy )
<div class="lazyLoad"> <ul id="container"> <li v-for="img in arr"> <img v-lazy="img.thumbnail_pic_s"> </li> </ul> </div>
-
-
-
优化HTTP请求数
- 使用雪碧图、图标字体文件
- 合并css与js(webpack)
- 利用浏览器缓存
-
预加载(当用户需要时在请求资源)
-
引用优化
- 引用css放在内,引用js放在结束标签前
- css加载是异步的,更早的加载出样式,就能更早的呈现页面
- 将js放到最后加载,避免因浏览器加载js阻塞页面,导致页面白屏
如何让for循环中定义的变量,在循环完后不会被回收
- 自执行闭包
- 计时器闭包
- 事件闭包
Css预处理sass less是什么?为什么使用他们
Sass和less都是css预处理器,是css上的一种抽象层,是一种特殊的语法,最终会编译成css,less是一种动态样式语言,给css赋予了动态语言的特性,比如:变量,继承,嵌套。Less既可以在客户端运行,在可以在服务端运行(需要借助node)
Js中.call()与.apply()区别
apply:调用一个对象的一个方法,用另一个对象替换当前对象。
call:调用一个对象的一个方法,用另一个对象替换当前对象。
从定义中可以看出,call和apply都是调用一个对象的一个方法,用另一个对象替换当前对象。而不同之处在于传递的参数,apply最多只能有两个参数——新this对象和一个数组argArray,如果arg不是数组则会报错
相同点:两个方法产生的作用是完全一样的。call, apply作用就是借用别人的方法来调用,就像调用自己的一样.
不同点:方法传递的参数不同
为什么css3不建议,多层嵌套选择器书写模式。比如:box1 box2 box3{},还有查找顺序是从左到右还是从右到左?
react的ref的作用,什么是受控组件、不受控组件
说一下js引擎的任务队列,或者是js引擎的执行过程
- 单线程
- 同步
- 异步
webpack的带来的深层作用是什么
- 进行重新加载编译。实际就是将浏览器不认识的语法编译成浏览器认识的语法。比如less
编译成css,ES6 语法 转成 ES5等等。 - 减少io请求。通常我们在请求后,会返回一个html到浏览器。这时,我们如果打开控制台,就会发现在html页面通过script,link等标签引用的静态资源, 浏览器会再次发出请求去获取这些资源。但是webpack的打包,将所有的静态资源都合并好了,减少了io请求。
Css模块化的好处
- 提高代码性能
标准盒模型与怪异盒模型的区别
不在请求头加入token与后端交互,纯在前端就完成token验证
动态路由挂载
解释一下原型
- 每个函数自带的
- 只有在被实例化后才会存在原型
- ???
什么是面向对象
面向对象三大特征
- 封装:把对象所有的逻辑代码都封装起来,只暴漏一个接口
- 继承:子类继承父类
- 多态:
说一下小程序的整个购物的流程,购物车的数据保存在哪里
说一下箭头函数
普通函数怎么改成箭头函数
- function fun(){} : let fun = () =>{}
深拷贝与浅拷贝
- 数组:??
- ???
有哪些数据类型
说一下promise
如何判断一个数据类型
状态机(vuex)有哪些核心
状态机(vuex)怎么修改值
了解websock吗?
compute和methods的区别
some/every
- 数组的常用方法
- some:检查数组中是否含有指定的条件
- every:检查数组中每个元素是否都满足指定的条件
路由的两种模式
- hash/history
- hash:锚标记
- history:???
vue中怎么跳转页面
组件中的name是干啥的
- 组件的动态挂载
- ???
开发的项目流程
uni-app打包流程
原生js写轮播图的几种方法
h5与c3特性
双向绑定
Vue数据双向绑定是通过数据劫持和观察者模式来实现的,
数据劫持,object.defineproperty它的目的是:当给属性赋值的时候,程序可以感知到,就可以控制属性值的有效范围,可以改变其他属性的值
观察者模式它的目的是当属性发生改变的时候,使用该数据的地方也发生改变
Vue中使用了那些设计模式
- 数据双向原理的设计模式:MVVM
- js高级:
- 工程模式
- 单例设计模式
- 订阅-观察者模式
Vue性能优化
- 组件复用(max混合)
- 懒加载
- keep-alive
- 按需引入
- 图片远程
keep-alive
保持活着
Vue.extend作用和原理
Vue.nextTick
- 延迟代码到整个界面DOM完成时候执行
Vue模板编译原理
-
获取app元素下的所有节点
-
使用原生js创建一个代码片段
-
进行节点遍历(递归算法)
-
遍历一个给代码片段中(vue中的各种编译
-
元素上指令编译
-
事件编译
-
数据编译
接入diff算法 创建一个原始的虚拟DOM
)添加一个
- 将代码片段添加到代码中
-
为啥data是一个函数
Vue的父子组件生命周期钩子函数执行顺序
v-for为什么要加key
- 唯一标识
diff算法
- 2.0:???
- 3.0:同级比较
了解过require.js吗?
- ???
模板引擎有哪些
- ejs(???)
- jade(???)
跨域
- jsonp
- ???
怎么按照顺序取消定时器
- 把定时器名存到数组中,然后按存入顺序取消定时器
解释下什么是动态路由绑定
- 后端:
- 动态路由分配表:最少3张
vue刷新页面如何使数据不被清除?
- 缓存
如何适配多端外设?
- 媒体查询
- 固定模式适配(<meta width=320px width=device-width)
- js适配
js引擎如何让实现异步
- ajax
- 计时器
- 原理:js的事件循环机制
什么是跨域
- 产生:浏览器的同源策略
- 解决
- jsonp
- proxy代理
- CORS
uniapp和微信小程序的区别
- 微信小程序是腾讯自己的小程序开发
- uni-app是内置vue的,可以用于多方面的开发
vue与react的区别
- vue数据双向,react数据单项
- vue设计模式MVVM,react设计模式MVC
- react组件式开发分为函数组件和类组件
- vue的事件响应机制是以指令的方式解析到远程DOM上的,react合成即使
实现一个圆
- border-radius
- ??
路由的跳转
- 编程式导航($router.push() / $router.replace / $router.go())
你知道webpack
webpack是一个现代js程序的静态模块打包器(会捋顺各模块之间的关系,把该合并的合并,该压缩的压缩)
- 本身只能用来处理js文件
- 要想处理其他类型的文件,需要装插件
如何进行用户权限管理
vue.use原理
- 功能
- 注册使用第三方插件,类似组件的全局注册
- 内部先检测组件的重复注册
- vue.use()必须有一个参数,且参数类型为Object或function
- 对参数进行检测,如果注册了直接跳出,如果没注册,则获取 install ,然后进行注册。
Vue如何封装插件
面向对象三大特征
- 封装、继承、多态
- 封装就是隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别,将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。
- 继承是面向对象的基本特征之一,继承机制允许创建分等级层次的类。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
- 多态同一个行为具有多个不同表现形式或形态的能力。是指一个类实例(对象)的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。