前端面试(真题重现,确定不进来看看?)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

setTimeout(function() {
    console.log('宏任务setTimeout');  //先遇到setTimeout,将其回调函数注册后分发到宏任务Event Queue
  //如果setTimeout设置时间,那它会先把函数放到宏任务Event Table,等时间到了再放入宏任务Event Queue里面
})
new Promise(function(resolve) {
    console.log('微任务promise');  	//new Promise函数立即执行
    resolve();						//必须resolve执行才能执行then
}).then(function() {
    console.log('微任务then');  		  //then函 Queue
})
console.log('主线程console');
 
//执行顺序结果: 微任务promise、主线程console、微任务then、宏任务setTimeout
一、前端常见的兼容性问题

1:不同浏览器的标签默认的外补丁( margin )和内补丁(padding)不同
解决方案: css 里增加通配符 * { margin: 0; padding: 0; }
2:IE6双边距问题;在 IE6中设置了float , 同时又设置margin , 就会出现边距问题
解决方案:设置display:inline;
备注:我们最常用的就是div+CSS布局了,而div就是一个典型的块属性标签,横向布局的时候我们通常都是用div float实现的,横向的间距设置如果用margin实现,这就是一个必然会碰到的兼容性问题。
3:当标签的高度设置小于10px,在IE6、IE7中会超出自己设置的高度
解决方案:超出高度的标签设置overflow:hidden,或者设置line-height的值小于你的设置高度
备注:这种情况一般出现在我们设置小圆角背景的标签里。出现这个问题的原因是IE8之前的浏览器都会给标签一个最小默认的行高的高度。即使你的标签是空的,这个标签的高度还是会达到默认的行高。
4:图片默认有间距
解决方案:使用float 为img 布局
备注:因为img标签是行内属性标签,所以只要不超出容器宽度,img标签都会排在一行里,但是部分浏览器的img标签之间会有个间距。去掉这个间距使用float是正道。
5:光标手形:cursor:hand 在safari 上不支持 IE才支持
解决方案:统一使用 cursor:pointer
6:解决在 IE6 下,列表与日期错位的问题
日期<span> 标签放在标题 <a> 标签之前即可
7:IE6-7 line-height 失效的问题
问题:在ie 中 img 与文字放一起时,line-height 不起作用
解决:都设置成 float
8:两个块级元素,父元素设置了overflow:auto;子元素设置了position:relative ;且高度大于父元素,在IE6、IE7会被隐藏而不是溢出;
解决方案:父级元素设置position:relative
9:上下(边距)margin的重叠问题
描述:给上边元素设置了margin-bottom,给下边元素设置了margin-top,浏览器只会识别较大值;
解决方案:margin-top和margin-bottom中选择一个,只设置其中一个值;
10:表单元素行高不一致
解决方案:给表单元素添加float:left(左浮动);或者是vertical-align:middle;(垂直对齐方式:居中)

二、vue中怎么重置Data

使用Object.assign()

// 重置data数据
Object.assign(this.$data, this.$options.data())
三、vue组件中name的作用

1.当项目使用keep-alive时,可搭配组件name进行缓存过滤
举个例子:
我们有个组件命名为detail,其中dom加载完毕后我们在钩子函数mounted中进行数据加载
2.DOM做递归组件时:比如说detail.vue组件里有个list.vue子组件,递归迭代时需要调用自身name
3.当你用vue-tools时
vue-devtools调试工具里显示的组见名称是由vue中组件name决定的

四、vue—router、routes、route的区别

1.routerthis.$router 是路由【导航对象】,用它 可以方便的 使用 JS 代码,实现路由的 前进、后退、 跳转到新的 URL 地址
vue-router有两种模式:
hash router 有一个明显的标志是url 中带有#, 我们可以通过监听url中的hash来进行路由跳转
history:比如history.back() 就能轻松的做到页面回退
2.routes:指创建vue-router路由实例的配置项。用来配置多个route路由对象
3.routethis.$route 是路由【参数对象】,所有路由中的参数, params, query 都属于它
在这里插入图片描述

五、JS通用的事件注册函数
function addEvent(element, type, handler)
{
    if (element.addEventListener)
    {
        element.addEventListener(type, handler, false);
    }
    else if (element.attachEvent)     //for IE
    {
        element.attachEvnet(“on” + type, handler);
    }
    else
    {
        element[“on” + type] = handler;
    }
}

六、vue-router路由跳转分为两大类

1.命名路由搭配params,刷新页面参数会丢失
2.查询参数搭配query,刷新页面数据不会丢失
3.接收参数使用this.$router后面就是搭配路由的名称就能获取到参数的值
在这里插入图片描述

六、前端性能优化方法总结
  1. 内容层面
    ① DNS解析优化(DNS是域名系统, 浏览器访问域名的时候,是需要去解析一次DNS,也就是把域名google.com解析到对应的ip地址上)
    减少DNS查询次数(首先查看浏览器缓存是否存在,不存在则访问本机DNS缓存,再不存在则访问本地DNS服务器。所以DNS也是开销,通常浏览器查找一个给定URL的IP地址要花费20-120ms,在DNS查找完成前,浏览器不能从host那里下载任何东西。);
    ② 避免重定向
    重定向至少访问两个不同地址,会减慢访问速度;(301重定向,从“重定向”的意思本身我们能明确是指向一个新的地址。也就是说是将现在的地址重新指向一个新的地址。大白话上我们可以理解为是网页的跳转。301是http协议中的一个跳转协议,301重定向就是当前页面永久性的跳转到一个新的地址上了。)
    ③ 杜绝404
    404代表服务器没有找到资源,网页中需要加载一个外部脚本,结果返回一个404,不仅阻塞了其他脚本下载,客户端还会将下载回来的内容(404)当成JavaScript去解析。

2)网络传输阶段
① 减少传输过程中实体的大小
b. cookie优化
去除没有必要的cookie,如果网页不需要cookie就完全禁掉。将cookie的大小减到最小。设置合适的过期时间,较长的过期时间可以提高响应速度。
c. 文件压缩
压缩传输文件通常可以减少70%网页内容的大小,包括脚本、样式表、图片等文件。
② 减少请求的次数
a. 文件适当的合并
将多个JS脚本文件合并成一个文件,将多个CSS样式表文件合并成一个文件,以此来减少文件的下载次数。
b. 雪碧图
把小图标合成一张大图,通过给元素的公共css设置background-image为该合成图,这样每个元素都会以该合成图为背景,而且页面也只加载一张合成图,然后再给每个元素单独微调其background-position。把多个请求合并成一个。
③ 异步加载
通过async和defer关键字或动态创建

  1. 渲染阶段
    ① js放底部,CSS放顶部
    将js脚本置底,可以让网页渲染所需要的内容尽快加载显示给用户。浏览器在CSS全部传输完全之前不会去渲染任何的东西,将CSS放在文档顶部能使页面加载得更快。
    ② 减少重绘和回流
    重绘和回流会延长网页的加载时间。
    减少重绘和回流的方法有:①将多次改变样式属性的操作合并成一次操作。
    ②用transform 代替 top,left ,top, margin-left… 这些位移属性
    当渲染树(render tree)中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
    当渲染树(render tree)中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就称为回流(reflow)。
    区别:回流必将引起重绘,而重绘不一定会引起回流。
    ③ 减少DOM节点。(那么dom操作为什么慢?
    这就要提及浏览器渲染页面,浏览器分为:渲染引擎和js引擎。
    渲染引擎工作:
    1、解析HTML代码,生产DOM tree。
    2、解析CSS样式,结合DOM tree生产Render tree(display:none;的结点不会存在Render tree上,最后不会被paint)。
    3、计算Render tree 各个节点的布局信息,比如box的位置、尺寸、颜色、外形等。
    4、根据计算后的布局信息,调用浏览器的UI引擎进行渲染。
    而操作dom会产生几种动作,极大的影响渲染的效率。其中layout(布局)和paint(绘制)是最大的。
    1、layout就是布局变动造成重新计算(耗CPU,有时也很耗内存)。
    2、paint就是调用浏览器UI引擎进行渲染展示页面(耗cpu和内存)。
    虚拟DOM
    1、虚拟DOM不会进行排版与重绘操作。
    2、虚拟DOM进行频繁修改,然后一次性比较并修改真实DOM中需要改的部分,最后并在真实DOM中进行排版与重绘,减少过多DOM节点排版与重绘,减少过多DOM节点排版与重绘损耗。
    3、真实DOM频繁排版与重绘的效率是相当低的。
    4、虚拟DOM有效降低大面积(真实DOM节点)的重绘与排版,因为最终与真实DOM比较差异,可以只渲染局部。)
    ④ 网页中元素过多对网页的加载和脚本的执行都是沉重的负担,因此要减少DOM元素的数量。
  1. 脚本执行阶段
    ① 事件委托
    采用事件委托机制,在父级元素上添加一个事件监听,来替代在每一个子元素上添加事件监听。
    ② 避免无谓的循环,break、continue、return的适当使用
    break:跳出所在的当前整个循环,到外层代码继续执行。break不仅可以结束其所在的循环,还可结束其外层循环,但一次只能结束一种循环。
    continue:跳出本次循环,从下一个迭代继续运行循环,内层循环执行完毕,外层代码继续运行。
    return:直接返回函数,return同时结束其所在的循环和其外层循环,最多只能返回一个值!
    小总结
    break; 可用作于switch和循环
    continue; 只可用作于循环
    return表达式; 只可用作于函数
七、谈谈你对vuex的理解

vuex五大核心属性:state,getter,mutation,action,module
state:存储数据,存储状态;在根实例中注册了store 后,用 this.$store.state 来访问;对应vue里面的data;存放数据方式为响应式,vue组件从store中读取数据,如数据发生变化,组件也会对应的更新。
getters:可以认为是 store 的计算属性,它的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
mutation:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
action:包含任意异步操作,通过提交 mutation 间接更变状态。
module:将 store 分割成模块,每个模块都具有statemutation、action、getter、甚至是嵌套子模块。

八、HTML5新特性

HTML是超文本标记语言,
2.语义化标签 header. footer. section
在这里插入图片描述

3.增强型表单
input输入框增加了多个输入类型。比如新增:color.,date等
在这里插入图片描述

4.新增视频和音频标签video和audio
5.新增canvas绘图
6.地理定位Geolocation
7.拖放api.
8.web store
9.脚本和链接无需type
10.语义化的HeaderFooter
语义化:明白每个标签的用途即直观的人是标签和属性的用途和作用。
好处:
①去掉样式能让页面结构呈现清晰
②屏幕阅读器会按标记“读”你的网页
③有益于SEO,SEO就是搜索引擎优化
④便于团队开发和维护

九、数组API的方法

数组的删除添加
1.pop() 方法用于删除数组的最后一个元素并返回删除的元素。
注意:此方法改变数组的长度
2.shift() 方法
shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
3.push() 方法
push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
4.unshift() 方法
unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。

set方法去重
1.多个数组去重 返回不同数据展示

let a = [1, 2, 3, 4]
let b = [3, 4, 5]
let union = [...new Set([...a, ...b])]
console.log(union)

2.单个数组的去重

var arr [0,2,3,4,4,0,2]
var arr2= Array.fromnew Set(arr);
console.log(arr2)

set是一种新的数据结构,它可以接收一个数组或者是类数组对象,自动去重其中的重复项目,正常情况下,NaN === NaN 返回的是false,但是在set里,一样能够帮你去重,但是这里大家可以看到,set返回的是一个对象,但是我们想要的是数组啊。这回,就该轮到Array.from出场了,它的作用,就是可以把类数组对象、可迭代对象转化为数组。目前主流的浏览器,Chrome,Firfox,Opera,Safari,包括微软的Edge,都是支持的,唯独IE系列不支持。

十、margin负值之对自身的影响

【1.margin-left/margin-right负值】
  当元素不存在width属性或width:auto时,负值margin会增加元素的宽度。
  注意:这仅是在元素不存在width属性或则width属性默认时。
【2.margin-top负值】
    margin-top为负值时,不会增加宽度,但会让元素上移。
【3.margin-bottom负值】
    margin-bottom为负值时不会位移,但会减少自身供css读取的高度。

十一、事件循环

宏任务 -> 微任务 -> 渲染,然后重复

  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

主线程运行的时候,会产生堆和栈。栈中的代码会调用各种外部 API。他们在任务队列中加入各种事件。只要栈中的代码执行完毕,主线程就会去读取“任务列队”,依次执行哪些事件所对应的回调函数。主线程从“任务队列”中读取事件,这个过程是循环不断的。所以叫事件循环机制。

十二、深拷贝和浅拷贝的区别

浅拷贝:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
深拷贝:在计算机中开辟一块新的内存地址用于存放复制的对象。
区别:深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
深拷贝的实现方法1:JSON.parse(JSON.stringify())
2.用递归去复制所有层级属性

浅拷贝的实现方法:object.assign(target,source)
Object.assign 方法只复制源对象中可枚举的属性和对象自身的属性

十三、link和@import的区别

1、从属关系区别
@import是 CSS 提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等。
2、加载顺序区别
页面被加载时,link 会同时被加载,而 @import 引用的 css 会等到页面加载结束后加载;
3、兼容性区别
link 此没有兼容性要求,而 @import IE低版本浏览器不支持。
4、DOM可控性区别
link 可以使用 js 动态引入,@import不行;

十四、v-for key的作用

1.key的主要作用就是用来提高渲染性能的!这个key属性必须是唯一的标识
2.key属性可以避免数据混乱的情况出现 (如果元素中包含了有临时数据的元素,如果不用key就会产生数据混乱)

十四、git和svn的区别
  • svn是集中式版本控制系统,git是分布式版本控制系统。
    svn就是所有人修改的都是服务器上的程序,如果有人修改了同样的部分,那就冲突了。所以呢,一般团队会约定,对于公共部分的程序,尽量标注出开发人员特有标识,又或者A从上添加,B从下添加。
    git就是开发人员创建自己的分支,这个分支就相当于将源码copy一份在本机上,之后修改的都是本地的代码,可随时拉取服务器的代码进行同步,git可创建无数分支,开发人员只需将自己修改的代码提交就可以了,这样冲突的几率会小很多。
  • svn是直接与服务器进行交互,git是将项目缓存在本地再推送到服务器。
  • svn必须在联网的情况下工作,git可不联网开发。
  • svn旨在项目管理,git旨在代码管理。
  • svn适用于多项目并行开发,git适用于单项目开发。
  • svn适用于企业内部,由项目经理协调多个项目统筹开发,git适用于通过网络多人开发同一项目。
  • GIT的内容完整性要优于SVN
    GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏
十五、数组遍历的方法
  1. forEach 循环
    遍历数组中的每一项,没有返回值,对原数组没有影响,但不支持IE
arr.forEach((value, index, array) => {
	// 参数一是: 数组元素
	// 参数二是: 数组元素的索引
	// 参数三是:当前的数组
})

2.filter 数组过滤
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素,主要用于筛选数组。
注意:它不会改变原始数组,但是直接返回一个新数组。

let arr = [12, 66, 4, 88, 3, 7];
let res = arr.filter((value, index, array) => {
	// 参数一是:数组元素
	// 参数二是:数组元素的索引
	// 参数三是:当前的数组
	return value >= 20;
});
console.log(res); // [66,88] 返回值是一个新数组

3.map 循环
map的回调函数中支持return返回值,相当于把数组中的每一项改变,但并不影响原来的数组,只是相当于把原数组克隆一份,把克隆的这一份的数组中的对应项改变了

let arr = [12,23,24,42,1]; 
let res = arr.map((item, index, arr) => { 
    return item*10; 
}) 
console.log(res); // [120,230,240,420,10];  原数组拷贝了一份,并进行了修改
console.log(arr); // [12,23,24,42,1];  原数组并未发生变化
var arr1 = [1, 2, 3, 4, 5, 6]
    arr2 = arr1.map((item, index) => {
        console.log(item);//分别输出1,2,3,4,5,6
        console.log(index);//分别输出0,1,2,3,4,5
        return item * item
    })
    console.log(arr2);//[1,4,9,16,25,36]

4.some 循环
some() 是查找数组中是否有满足条件的元素,返回值是布尔值,如果查找到这个元素,就返回 true(有任意一项符合条件即返回true) , 如果查找不到就返回 false。
如果查询数组中唯一的元素,用 some 方法更合适,在 some 里面遇到 return true 就是终止遍历,迭代效率更高。

let arr = [10, 30, 4];
let flag = arr.some((value, index, array) => {
	return value < 3;
});
console.log(flag); // false 返回值是布尔值,只要查找到满足条件的一个元素就立马终止循环

5.every 循环
every()是对数组中的每一项运行给定函数,只有当该函数对每一项返回true,才返回true,否则返回false。

let arr = [1, 2, 3, 4, 5, 6];
let flag = arr.every((value, index, array) => {
	return value > 3;
});
console.log(flag); // false

6.for of 循环
for-of 循环是ES6新增特性,for-of 的功能不仅仅用于遍历数组,它还可以 遍历字符串、遍历类数组对象、支持 Map 和 Set 对象遍历

let arr = [1, 2, 3, 4];
for (let item in arr) {
    console.log(item) // 遍历每个元素 1 2 3 4
}
十六、Promise
  • 概述:Promise是异步编程的一种解决方案,Promise是一个对象,可以获取异步操作的消息
  • 目的: (1)、避免回调地狱的问题(2)、Promise对象提供了简洁的API,使得控制异步操作更加容易 (3)、避免了层层嵌套的回调函数
  • 缺点:①无法取消promise ②当处于pending状态时,无法得知目前进展到哪一个阶段
  • Promise有三种状态:pendding //正在请求,rejected //失败,resolved //成功
  • 基础用法:new Promise(function(resolve,reject){ })
  • resolved,rejected函数:在异步事件状态pendding->resolved回调成功时,通过调用resolved函数返回结果;当异步操作失败时,回调用rejected函数显示错误信息
  • then的用法:then中传了两个参数,第一个对应resolve的回调,第二个对应reject的回调
  • catch方法:捕捉promise错误函数,和then函数参数中rejected作用一样,处理错误,由于Promise抛出错误具有冒泡性质,能够不断传递,会传到catch中,所以一般来说所有错误处理放在catch中,then中只处理成功的,同时catch还会捕捉resolved中抛出的异常
十七、Promise的构造函数是同步执行的,then中的方法是异步执行的,promise是微任务,setTimeout是宏任务,promise.then总是先与setTiemout执行
十七、水平居中和垂直居中

讲解水平居中详细方式

水平居中方式:

块级元素
方案一:(分宽度定不定两种情况)
定宽度:需要谁居中,给其设置 margin: 0 auto; (作用:使盒子自己居中)
不定宽度:默认子元素的宽度和父元素一样,这时需要设置子元素为display: inline-block; 或 display: inline;即将其转换成行内块级/行内元素,给父元素设置 text-align: center;

方案二:使用定位属性
首先设置父元素为相对定位,再设置子元素为绝对定位,设置子元素的left:50%,即让子元素的左上角水平居中;
定宽度:设置绝对子元素的 margin-left: -元素宽度的一半px; 或者设置transform: translateX(-50%);
不定宽度:利用css3新增属性transform: translateX(-50%);

方案三:使用flexbox布局实现(宽度定不定都可以)
使用flexbox布局,只需要给待处理的块状元素的父元素添加属性 display: flex; justify-content: center;

垂直居中方式

已知高度和宽度的元素

方案一:设置父元素为相对定位,给子元素设置绝对定位,top: 0; right: 0; bottom: 0; left: 0; margin: auto;
方案二:设置父元素为相对定位,给子元素设置绝对定位,left: 50%; top: 50%; margin-left: --元素宽度的一半px; margin-top: --元素高度的一半px;

未知高度和宽度的元素

1.设置父元素为相对定位,给子元素设置绝对定位,left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%);
2.设置父元素为flex定位,justify-content: center; align-items: center;

十八、oninput 事件- 输入提示

oninput 事件在用户输入时触发。
该事件在 <input><textarea> 元素的值发生改变时触发。
提示: 该事件类似于 onchange 事件。不同之处在于 oninput 事件在元素值发生变化是立即触发, onchange 在元素失去焦点时触发。另外一点不同是 onchange 事件也可以作用于 <keygen><select> 元素。

十九、什么是Webpack?怎么使用Webpack?

1.什么是Webpack?
Webpack模块打包工具,它会分析模块之间的依赖关系,然后使用loaders处理它们,最后生成一个优化并合并后的静态资源。
简单的说就是打包,压缩各种静态资源的工具

2.目的?
性能优化
减少浏览器像服务器的请求次数
节约服务器的带宽资源

3.如何使用Webpack?

使用Webpack之前要先搭建node环境

4.如何打包.js文件

第一先创建webpack的配置文件 webpack.config.js
注:main.js文件是我们要打包的文件
build.js文件是我们打包后的输出文件
第二在package.json配置bulid
第三引文件(注意要引打包后的build.js文件)
第四在终端执行npm run build

二十、请说一下JavaScript中的垃圾回收机制

垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为0(没有其他对象引用过该对象),或对该对象的唯一引用是循环的,那么该对象的内存即可回收。

二十一、请说下封装 vue 组件的过程?

首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。
创建一个组件,然后使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件,可以采用emit方法。

二十二、为什么会出现vue修改数据后页面没有刷新这个问题?

受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。
解决方法:
第一种:this.$set
第二种:给数组、对象赋新值
第三种:使用this.$forceupdate强制刷新

二十三、小程序的生命周期
项目的生命周期

App() 函数用来注册一个小程序。接受一个 object 参数,其指定小程序的生命周期函数等。
前台、后台定义: 当用户点击左上角关闭,或者按了设备 Home 键离开微信,小程序并没有直接销毁,而是进入了后台;当再次进入微信或再次打开小程序,又会从后台进入前台。

onLaunch : 小程序初始化时触发
onShow : 小程序首次展示或者切前台时触发
onHide : 小程序切后台时触发

  • 用户首次打开小程序,触发 onLaunch(全局只触发一次)。
  • 小程序初始化完成后,触发onShow方法,监听小程序显示。
  • 小程序从前台进入后台,触发 onHide方法。
  • 小程序从后台进入前台显示,触发 onShow方法。
  • 小程序后台运行一定时间,或系统资源占用过高,会被销毁。

object 参数说明:
在这里插入图片描述

页面的生命周期

Page()函数用来注册一个页面。接受一个 object 参数,其指定页面的初始数据、生命周期函数、事件处理函数等。

onLoad : 页面初始化时触发
onShow : 页面首次出现在前台时触发
onReady : 页面首次渲染完毕时触发
onHide : 页面从前台变为后台时触发
onUnload : 页面销毁时触发
其中 onShow 的触发时间要早于 onReady

  • 小程序注册完成后,加载页面,触发onLoad方法。
  • 页面载入后触发onShow方法,显示页面。
  • 首次显示页面,会触发onReady方法,渲染页面元素和样式,一个页面只会调用一次。
  • 当小程序后台运行或跳转到其他页面时,触发onHide方法。
  • 当小程序有后台进入到前台运行或重新进入页面时,触发onShow方法。
  • 当使用重定向方法wx.redirectTo(OBJECT)或关闭当前页返回上一页wx.navigateBack(),触发onUnload

object 参数说明:
在这里插入图片描述

自定义组件的生命周期
  • created : 组件实例刚刚被创建时触发
  • attached : 组件实例刚进入页面节点树时触发
  • ready : 组件实例挂载到节点树时触发
  • moved : 组件实例被移动到节点树另一个位置时触发
  • detached : 组件实例被销毁时触发
二十四、怎么封装微信小程序的数据请求的?

首先创建一个http文件夹,里面再创建env.jsrequest.jsindex.js
1.先创建一个env.js文件来封装环境

module.exports={
  //开发环境
  dev:{
    baseUrl:'http://127.0.0.1:8080'
  },
  //生产环境
  prod:{
    baseUrl:'https://api.it120.cc'
  },
  //测试环境
  test:{
    baseUrl:'https://api.1909A.com'
  }
}

2.创建一个request.js 文件,来封装请求方法

const {baseUrl} = require('./env.js').prod //引入你要使用的环境
//封装ajax

//配置专属域名
const vipUrl = 'hjl'

module.exports = {
  request: function (url, method = "GET", data = {}, isSubDomain = true) {
    let fullUrl = `${baseUrl}/${isSubDomain ? vipUrl : ''}/${url}`;
    wx.showLoading({
      title: '玩命加载中',
    })
//isSubDomain就是代表是否需要专属域名

    return new Promise((resolve, reject) => {

      wx.request({
        url: fullUrl,
        method,
        data,
        header: {
          'Content-type': 'application/x-www-form-urlencoded'
          //根据要求来配置
        },
        success(res) {
          console.log('wx.request打印结果:', res)
          resolve(res.data.data)
          wx.hideLoading()
          
          if (res.statusCode === 200 && res.data.code === 0) {
            resolve(res.data)
            wx.hideLoading()
          } else {
            wx.showToast({
              title: '接口有问题,请检查',
            })
            reject('接口有问题,请检查')
          }
        },
        
        fail(error) {
          wx.showToast({
            title: '数据接口有问题',
          })
          reject('数据接口有问题')

        }
      })
    })
  }
}

3.在index.js中封装接口

const { request }=require('./request.js');

//项目中用到的各种业务接口的封装

module.exports={

 //banner图接口
  getBanner:()=>{
    return request('banner/list',"GET",'',true)
  },
}

4.最后在使用的页面的js中先引入index直接调用就ok

const {getBanner} = require('../../http/index');

  //请求轮播接口的数据
  ready() {
    getBanner().then((res)=>{
      console.log(res)
    })
  },
二十五、有哪些参数传值的方法?

1、URL传值
2:全局传值(就是在app.js传值)
3、标签传值
给HTML元素添加 data-* 属性来传递我们需要的值,然后通过 e.currentTarget.datasetonloadparam 参数获取。但 data- 名称不能有大写字母、不可以存放对象

二十五、你使用过哪些方法,来提高微信小程序的应用速度?

一、提高页面加载速度
二、用户行为预测
三、减少默认data的大小
四、组件化方案

二十六、VUE前端配置跨域解决方案

1.后台更改header
2.使用jquery jsonp
3.使用http-proxy-middleware 代理解决(原因就是因为客户端请求服务端的数据是存在跨域问题的,而服务器和服务器之间可以相互请求数据,是没有跨域的概念(如果服务器没有设置禁止跨域的权限问题),也就是说,我们可以配置一个代理的服务器可以请求另一个服务器中的数据,然后把请求出来的数据返回到我们的代理服务器中,代理服务器再返回数据给我们的客户端,这样我们就可以实现跨域访问数据啦。)

1.打开config/index.js,在proxyTable中添写如下代码:

proxyTable: {
      '/api': { // 请求的代称,写在Axios里的BaseUrl
        target: 'http://localhost:8083',  // 真实请求URl
        changeOrigin: true, // 允许跨域
        pathRewrite: {  // 替换,通配/api的替换成/
          '^/api': '/'
        }
      }

2.然后在Axios配置baseUrl/api

getData () { 
 axios.get('/api/bj11x5.json', function (res) { 
   console.log(res) 
 })

通过这中方法去解决跨域,打包部署时还按这种方法会出问题。解决方法如下:

let serverUrl = '/api/'  //本地调试时 
// let serverUrl = 'http://f.apiplus.cn/'  //打包部署上线时 
export default { 
  dataUrl: serverUrl + 'bj11x5.json' 
}

③第三种方法是: .Jquery jsonp

1.引入Jquery ,cnpm install jquery --save-dev
2.在webpack.base.conf.js文件中加入

plugins: [
    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery"
    })
 ],

3.在需要的temple里引入也可以在main.js里全局引入

import $ from 'jquery'
$.ajax({ 
      url: '地址', 
      type: 'GET', 
      dataType: 'JSONP', 
      success: function (res) { 
        self.data = res.data.slice(0, 3)
        self.opencode = res.data[0].opencode.split(',') 
      } 
    }) 
二十七、常见的HTTP状态码

2开头 (请求成功)表示成功处理了请求的状态代码
200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
201 (已创建) 请求成功并且服务器创建了新的资源。
202 (已接受) 服务器已接受请求,但尚未处理。
203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。
204 (无内容) 服务器成功处理了请求,但没有返回任何内容。
205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。
206 (部分内容) 服务器成功处理了部分 GET 请求。

3开头 (请求被重定向)表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

4开头 (请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理。
400 (错误请求) 服务器不理解请求的语法。
401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
403 (禁止) 服务器拒绝请求。
404 (未找到) 服务器找不到请求的网页。
405 (方法禁用) 禁用请求中指定的方法。
406 (不接受) 无法使用请求的内容特性响应请求的网页。
407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
408 (请求超时) 服务器等候请求时发生超时。
409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。
411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。
412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。
413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
415 (不支持的媒体类型) 请求的格式不受请求页面的支持。
416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。
417 (未满足期望值) 服务器未满足"期望"请求标头字段的要求。

5开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。

二十七、Promise.all和Promise.race区别,和使用场景

Promise.all可以将多个Promise实例包装成一个新的Promise实例。用于将多个Promise实例,包装成一个新的Promise实例。
1.它接受一个数组作为参数。
2.数组可以是Promise对象,也可以是其它值,只有Promise会等待状态改变。
3.当所有的子Promise都完成,该Promise完成,返回值是全部值的数组。
4.如果有任何一个失败,该Promise失败,返回值是第一个失败的子Promise的结果。

Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

二十七、从输入URL到网页呈现的过程
  1. DNS解析
  2. TCP连接
    HTTP协议是使用TCP协议作为其传输层协议的,在拿到服务器的IP地址后,浏览器客户端会与服务器建立TCP连接。该过程包括三次握手:
  • 第一次握手:客户端向服务器发送一个建立连接的请求(您好,我想认识您);
  • 第二次握手:服务器接到请求后发送同意连接的信号(好的,很高兴认识您)
  • 第三次握手,客户端接到同意连接的信号后,再次向服务器发送了确认信号(我也很高兴认识您)。

三次握手主要是为了防止已经失效的请求报文字段发送给服务器,浪费资源。

  1. 发送HTTP请求
    浏览器构建http请求报文,并通过TCP协议传送到服务器的指定端口。http请求报文一共包括三个部分:
  • 请求行:指定http请求的方法、url、http协议版本等
  • 请求头:描述浏览器的相关信息,语言、编码等。
  • 请求正文:当发送POST, PUT等请求时,通常需要向服务器传递数据。这些数据就储存在请求正文中。
  1. 服务器处理请求并返回HTTP报文
    服务器处理http请求,并返回响应报文。响应报文包括三个部分:状态码, 响应报头和响应报文
  2. 浏览器解析渲染页面
    浏览器接受到http服务器发送过来的响应报文,并开始解析html文档,渲染页面。
  3. 连接结束(断开TCP连接)
    客户端与服务器四次挥手,断开tcp连接。
  • 客户端向服务器发送一个断开连接的请求(不早了,我该走了);
  • 服务器接到请求后发送确认收到请求的信号(知道了);
  • 服务器向主机发送断开通知(我也该走了);
  • 客户端接到断开通知后断开连接并反馈一个确认信号(嗯,好的),服务器收到确认信号后断开连接;
二十八、排序

排序详细讲解

  1. 冒泡排序
    原理:只需要通过两次遍历,两两交换,就可以实现排序。(使用场景:数据量小于1000)
1、通过sort()方法
var arr = [21,100,-6,99,1]
function sortNum(a,b){
    return a-b;  
}
arr.sort(sortNum);
console.log(arr);
var arr = [210,100,6,99,1,12];
for(var i in arr){
    for(var y in arr){
        if(arr[i]<arr[y]){
            times = arr[i];
            arr[i] = arr[y];
            arr[y] = times;
        }
    }
}
console.log(arr);
var arr = [4,23,100,9,7,49,36,51];
function arrSort(arr){
for (var i=0;i<arr.length-1;i++){ //遍历,这里,arr.length-1,是因为最后一次不用循环了。
   for (var j=0;j<arr.length-i-1;j++) {//双重遍历,遍历i之后的数,例如有8个元素,i在第一项,那么遍历后面7项。
      if(arr[j]>arr[j+1]) {//如果左边,大于左边,那么交换位置。
         var tem = arr[j]
         arr[j] = arr[j+1];
         arr[j+1] = tem;
      }
   }
 }
 return arr;
}

2.选择排序
原理:跟冒泡排序差不多,也是两两交换,不过这两两交换,是第一位和第五位交换,而不是第四位和第五位。(不稳定,因为会碰到重复的数。)

let arr = [145, 248, 31, 45, 9, 11, 145, 300];
function arrSort(arr) {   
    for(let i=0;i<arr.length-1;i++){//遍历数组       
             let min=arr[i];//防止arr[i]发生变化       
             for(j=i;j<arr.length;j++){//双重遍历,查找最小的数进行交换,跟冒泡不一样的地方在于,选择排序,假如第4位更小,则是1,4位交换,不是3,4位交换            
                  if(arr[j]<min){          
                        let temp=arr[j];               
                        arr[j]=min;               
                         min=temp;           
                   }       
              }   
     }  
    return arr;
}

在这里插入图片描述

3 .插入排序(稳定)
原理:1、从第二个元素开始,遍历它之前的元素。
2、如果他之前的元素,大于他,那么交换。并继续往前遍历之前比它大的元素。

                //插入排序
let arr = [145, 248, 31, 45, 9, 11, 145, 300];
function arrSort(array) {
  for(let i = 1; i < array.length; i++) {//遍历一波数组,从数组第二项开始遍历
    let key = array[i];//这里必须要定义,因为循环结束,会用到。
    let j = i - 1;//定义j为i-1,在第一次遍历,是从数组第一项开始
    while(j >= 0 && array[j] > key) {//如果j的值大于i的值,也就是左边的大于右边的,j>=0,防止j--变负数。
   array[j + 1] = array[j];//例如第二项和第三项248和31,那么变成,248,248
   j--;//如果248>31执行成功了,变成了248,248,那么依次判断左边,是否有小于 的。
}
   array[j + 1] = key;//把第一项赋值成最小的那个。
}
return array;
}
console.log(arrSort(arr));

在这里插入图片描述

4 归并排序(稳定)
原理:归并排序使用了非常好的分治思想,把一个数组,分成两部分,排序之后,较小的那个值取出来放在第一个位置,再合并。

                //分治排序
                let arr = [145, 248, 31, 45, 9, 11, 145, 300];
                function merge(left, right) {
                    let result = [];
                    while(left.length > 0 && right.length > 0) {//如果两边数组都有值
                        if(left[0] < right[0]) {//左边小于右边
                            result.push(left.shift());//给result数组添加值,并在left删掉值
                        }
                        else {
                            result.push(right.shift());//给result数组添加值,并在right删掉值
                        }
                    }
                    /* 当左右数组长度不等.将比较完后剩下的数组项链接起来即可 */
                    return [...result,...left,...right];//这里用es6的语法,只是一个简写,百度一眼就会。...left...right是因为万一长度不相等,会少数,所以会加这两个。
                }
                function mergeSort(arr){
                    if(arr.length==1){//如果数组长度为1则返回数组
                        return arr
                    };
                    let mid=Math.floor(arr.length/2);//分成两部分
                    let left_arr=arr.slice(0,mid);//数组分成两份后,塞进去。假如说数组有8个元素,分成两部分,左边(0,4)
                    let right_arr=arr.slice(mid);//右边(4到后面所有)
                    return merge(mergeSort(left_arr),mergeSort(right_arr));//递归
                }
                console.log(mergeSort(arr));

在这里插入图片描述

5 快速排序(不稳定)
原理:在数据集之中,找一个基准点,建立两个数组,分别存储左边和右边的数组,利用递归进行下次比较。

                //快速排序
                let arr = [145, 248, 31, 45, 9, 11, 145, 300];
                function arrSort(arr){
                    if (arr.length <= 1){
                        return arr
                    };
                    var pivotIndex = Math.floor(arr.length / 2);
                    var pivot = arr.splice(pivotIndex,1)[0];//取出中间的数字,比如第一次就取出9
                    var left = [];
                    var right = [];
                    for (var i = 0; i < arr.length; i++){
                        if(arr[i] < pivot) {//第一次运算,如果小于9就进入左数组,大于就进入右数组
                            left.push(arr[i]);
                        }else{
                            right.push(arr[i]);
                        }
                    }
                    return arrSort(left).concat([pivot],arrSort(right));//递归,再把左数组分成两半进行排序,右数组同理。
                }
                console.log(arrSort(arr));
二十九、computed、methods、watch的区别

计算属性computed:支持缓存,只有依赖数据发生改变,才会重新进行计算,主要监听daata
不支持异步,当computed内有异步操作时无效,无法监听数据的变化
数据量大,需要缓存的时候用 computed ;每次确实需要重新加载,不需要缓存时用 methods

侦听属性watch:

  1. 不支持缓存,数据变,直接会触发相应的操作;watch支持异步;
    主要用于监控vue实例的变化,一般用于监控路由,props,input输入框的值
三十、正确理解函数防抖和节流

节流效果(throttle):让高频的执行函数平滑的执行,一段时间内只执行一次。
使用场景:window.onsize 和 window.onscroll等高频执行的函数。

防抖效果(debounce):让高频的执行变为只执行最后一次。
使用场景:input每次输入都去执行函数,鼠标连续点击。

三十一、ES6之6种遍历对象属性的方法

for.in:会同时遍历自身以及原型链上的属性(不含不可枚举属性,不含Symbol属性).

    for (var key in obj) {
        console.log(key);
        //qq  //father //JCname  //JCage
    }

Object.keys():只遍历自身属性,不遍历原型链上的属性
只遍历可枚举属性,不遍历不可枚举属性
不遍历Symbol

    console.log(Object.keys(obj));
    // ['e', 'f']

Reflect.ownKeys():包含对象自身的所有属性 (不论是否可枚举,或者是symbol属性)

        console.log(Reflect.ownKeys(son));
        //["qq", "father", "home", Symbol()]
        返回一个数组

在这里插入图片描述

三十二、HTML渲染过程

HTML解析过程:构建DOM树、构建CSSOM树、根据DOM树和CSSOM树构建render树、有了render树就开始布局、最后绘制paint
1、构建DOM
将HTML构建成一个DOM树,也就是构建节点,把所有的节点都构建出来。
2、构建CSSOM(可以叫对象模型)
解析css去构建CSSOM
3、构建render
DOM已经构建好了,css也有了,浏览器就会根据这两个来构造render树,浏览器就知道了有哪些节点、各个节点的CSS定义以及他们的从属关系。
4、布局
render树有了,通过render树,浏览器开始计算各个节点的位置和样式。
5、绘制
遍历render树,在页面上绘制每个节点。
6、重排(回流)reflow
render树绘制完成之后,比如JS改变样式或添加节点,这时候render树就需要重新计算。
7、重绘 repaint
重新绘制页面。

三十三、NEW操作符具体做了什么(构造函数的实例化过程)

创建一个空对象,
并且this变量引用该对象同时还继承了该函数的原型prototype
属性和方法被加入到this引用的对象中
最后return返回this

三十四、原生js的ajax请求

get请求:

//步骤一:创建异步对象
var ajax = new XMLHttpRequest();
//步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端
ajax.open('get','getStar.php?starName='+name);
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
ajax.onreadystatechange = function () {   if (ajax.readyState==4 &&ajax.status==200) {
    //步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的    console.log(ajax.responseText);//输入相应的内容    }
}

post请求:

//创建异步对象  
var xhr = new XMLHttpRequest();
//设置请求的类型及url
//post请求一定要添加请求头才行不然会报错
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
 xhr.open('post', '02.post.php' );
//发送请求
xhr.send('name=fox&age=18');
xhr.onreadystatechange = function () {
    // 这步为判断服务器是否正确响应
  if (xhr.readyState == 4 && xhr.status == 200) {
    console.log(xhr.responseText);
  } 
};
  • 12
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值