vue 面试问题总结
vue-cli 工程常用的 npm 命令有哪些?全局安装 vue-clinpm install --global vue-cli创建一个基于 webpack 模板的新项目vue init webpack my-project进入项目目录,运行cd my-projectnpm installnpm run devvue-cli 生成 生产环境部署资源 的 npm命令:npm...
vue-cli 工程常用的 npm 命令有哪些?
全局安装 vue-cli
npm install --global vue-cli
创建一个基于 webpack 模板的新项目
vue init webpack my-project
进入项目目录,运行
cd my-project
npm install
npm run dev
vue-cli 生成 生产环境部署资源 的 npm命令:
npm run build
用于查看 vue-cli 生产环境部署资源文件大小的 npm命令:
npm run build --report
webpack
//全局安装webpack
cnpm install -g webpack
//安装到你的项目目录
cnpm install --save-dev webpack
//初始化package.json
cnpm init
//使用webpack构建本地服务器
cnpm install --save-dev webpack-dev-server
//运行本地服务器
npm run server
// npm一次性安装多个依赖模块,模块之间用空格隔开
cnpm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react
//css-loader 和 style-loader
cnpm install --save-dev style-loader css-loader
//安装less-loader和less:
cnpm install less less-loader --save-dev
//自动根据模版生成html插件
cnpm install --save-dev html-webpack-plugin
//分离CSS和JS文件
cnpm install --save-dev extract-text-webpack-plugin
--save和--save-dev的区别
相同点:都是写入到package.json中
不同点:1使用 --save-dev 安装的 插件,被写入到 devDependencies 对象里面去,而使用 --save 安装的插件,则被写入到 dependencies 对象里面去。
2devDependencies 里面的插件只用于开发环境,不用于生产环境,而 dependencies 是需要发布到生产环境的。
vue-cli目录解析:
- build 文件夹:用于存放 webpack 相关配置和脚本。开发中仅 偶尔使用 到此文件夹下 webpack.base.conf.js 用于配置 less、sass等css预编译库,或者配置一下 UI 库。
- config 文件夹:主要存放配置文件,用于区分开发环境、线上环境的不同。 常用到此文件夹下 config.js 配置开发环境的 端口号、是否开启热加载 或者 设置生产环境的静态资源相对路径、是否开启gzip压缩、npm run build 命令打包生成静态资源的名称和路径等。
- dist 文件夹:默认 npm run build 命令打包生成的静态资源文件,用于生产部署。
- node_modules:存放npm命令下载的开发环境和生产环境的依赖包。
- src: 存放项目源码及需要引用的资源文件。
- src下assets:存放项目中需要用到的资源文件,css、js、images等。
- src下componets:存放vue开发中一些公共组件:header.vue、footer.vue等。
- src下emit:自己配置的vue集中式事件管理机制。
- src下router:vue-router vue路由的配置文件。
- src下service:自己配置的vue请求后台接口方法。
- src下page:存在vue页面组件的文件夹。
- src下util:存放vue开发过程中一些公共的.js方法。
- src下vuex:存放 vuex 为vue专门开发的状态管理器。
- src下app.vue:使用标签
<route-view></router-view>
渲染整个工程的.vue组件。 - src下main.js:vue-cli工程的入口文件。
- index.html:设置项目的一些meta头信息和提供
<div id="app"></div>
用于挂载 vue 节点。 - package.json:用于 node_modules资源部 和 启动、打包项目的 npm 命令管理。
config文件夹 下 index.js 的对于工程 开发环境 和 生产环境 的配置
build 对象下 对于 生产环境 的配置:
- index:配置打包后入口.html文件的名称以及文件夹名称
- assetsRoot:配置打包后生成的文件名称和路径
- assetsPublicPath:配置 打包后 .html 引用静态资源的路径,一般要设置成 "./"
- productionGzip:是否开发 gzip 压缩,以提升加载速度
dev 对象下 对于 开发环境 的配置:
- port:设置端口号
- autoOpenBrowser:启动工程时,自动打开浏览器
- proxyTable:vue设置的代理,用以解决 跨域 问题
介绍一些 package.json 里面的配置
常用对象解析:
- scripts:npm run xxx 命令调用node执行的 .js 文件
- dependencies:生产环境依赖包的名称和版本号,即这些 依赖包 都会打包进 生产环境的JS文件里面
- devDependencies:开发环境依赖包的名称和版本号,即这些 依赖包 只用于 代码开发 的时候,不会打包进 生产环境js文件 里面。
vue.js的两个核心是什么?
核心思想是:数据驱动、组件系统。
请说出vue几种常用的指令
v-if 条件渲染指令,根据其后表达式的bool值进行判断是否渲染该元素;
v-show 与v-if类似,只是会渲染其身后表达式为false的元素,而且会给这样的元素添加css代码:style="display:none";
v-else 必须跟在v-if/v-show指令之后,不然不起作用;如果v-if/v-show指令的表达式为true,则else元素不显示;如果v-if/v-show指令的表达式为false,则else元素显示
v-for 类似JS的遍历,用法为 v-for="item in items", items是数组,item为数组中的数组元素。
v-bind 这个指令用于响应地更新 HTML 特性,比如绑定某个class元素或元素的style样式。
v-on 用于监听指定元素的DOM事件,比如点击事件。
v-if和v-show的区别?
v-if根据bool值判断显示或不显示元素
v-show根据bool值判断显示或隐藏元素
vue常用的修饰符
.prevent: 提交事件不再重载页面
.stop: 阻止单击事件冒泡
.self: 当事件发生在该元素本身而不是子元素的时候会触发
.capture: 事件侦听,事件发生的时候会调用
.once: 跟v-once作用类似,只渲染一次,第二次不会执行
v-on可以监听多个方法吗?
<!--v-on 定义多个事件,以‘,’号隔开 -->
<a style="cursor:default"
v-on=
'{click:DoSomething,mouseleave:MouseLeave}'
>doSomething</a>
vue中 key 值的作用
需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
key 管理可复用的元素,提高循环的性能。
vue中子组件调用父组件的方法
第一种方法是直接在子组件中通过this.$parent.event来调用父组件的方法
父组件:
<template>
<div>
<child></child>
</div>
</template>
<script>
import child from '~/components/dam/child';
export default {
components: {
child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
};
</script>
子组件:
<template>
<div>
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
methods: {
childMethod() {
this.$parent.fatherMethod();
}
}
};
</script>
第二种方法是在子组件里用$emit
向父组件触发一个事件,父组件监听这个事件就行了。
父组件:
<template>
<div>
<child @fatherMethod="fatherMethod"></child>
</div>
</template>
<script>
import child from '~/components/dam/child';
export default {
components: {
child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
};
</script>
子组件:
<template>
<div>
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
methods: {
childMethod() {
this.$emit('fatherMethod');
}
}
};
</template>
vue中 keep-alive 组件的作用
<keep-alive>
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们<keep-alive>
是一个抽象组件:它自身不会渲染一个DOM元素,也不会出现在父组件链中- 当组件在
<keep-alive>
内被切换,它的activated
和deactivated
这两个生命周期钩子函数将会被对应执行 - 可以使被包含的组件保留状态,或避免重新渲染。
- 它提供了include与exclude两个属性,允许组件有条件地进行缓存。
什么是vue生命周期和生命周期钩子函数?
这就是vue实例从新建到销毁的一个完整流程,以及在这个过程中它会触发哪些生命周期的钩子函数。那说到这儿,可能很多童鞋会问,钩子函数是什么意思?
钩子函数,其实和回调是一个概念,当系统执行到某处时,检查是否有hook,有则回调。说的更直白一点,每个组件都有属性,方法和事件。所有的生命周期都归于事件,在某个时刻自动执行。
Vue为我们提供了renderError方法,这个方法只有在开发的时候它才会被调用,在正式打包上线的过程当中,它是不会被调用的。它主要是帮助我们调试render里面的一些错误。
有且只有当render方法里面报错了,才会执行renderError方法。
vue如何监听键盘事件中的按键?
在Vue中,已经为常用的按键设置了别名,这样我们就无需再去匹配keyCode
,直接使用别名就能监听按键的事件。
<input @keyup.enter="function">
另外,Vue中还支持组合写法:
vue更新数组时触发视图更新的方法
使用$set()方法,既可以新增属性,又可以触发视图更新。
单页面与多页面间的区别及优缺点
单页面应用(SPA),通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于pc端。
多页面(MPA),就是指一个应用中有多个页面,页面跳转时是整页刷新
单页面的优点:
1,用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
2,前后端分离
3,页面效果会比较炫酷(比如切换页面内容时的专场动画)
单页面缺点:
1,不利于seo
2,导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)
3,初次加载时耗时多
4,页面复杂度提高很多
什么是vue的计算属性?
什么是计算属性?
计算属性(computed),也是一个属性,也是用来存储数据用的,但是和data属性相比还是有区别
1 数据是可以进行逻辑处理相关的操作
2 可以对计算属性中的数据进行监视
计算属性和方法的区别?
1 计算属性是基于它所依赖的数据进行更新,在有在相关依赖的数据发生变化了才会进行更新,而普通的方法每次都会执行
2 计算属性是有缓存的,只要它所依赖的数据没有发生改变,后面的每一次访问计算属性中的值,都是之前缓存的结果,不会重复执行。
对于MVVM的理解?
MVVM 是 Model-View-ViewModel 的缩写。
Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
View 代表UI 组件,它负责将数据模型转化成UI 展现出来。
ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
Vue的生命周期
beforeCreate(创建前) 在数据观测和初始化事件还未开始
created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来
beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
1.什么是vue生命周期?
答: Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
Vue的路由实现:hash模式 和 history模式
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”
Vue与Angular以及React的区别?
1.与AngularJS的区别
相同点:
都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。
不同点:
AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观;在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。
2.与React的区别
相同点:
React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。
不同点:
React采用的Virtual DOM会对渲染出来的结果做脏检查;Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。
vue路由的钩子函数
首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。
beforeEach主要有3个参数to,from,next:
to:route即将进入的目标路由对象,
from:route当前导航正要离开的路由
next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。
vuex是什么?怎么使用?哪种功能场景使用它?
只用来读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。
在main.js引入store,注入。新建了一个目录store,….. export 。
场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车
state
Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations
mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
getters
类似vue的计算属性,主要用来过滤一些数据。
action
actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。
vue-cli如何新增自定义指令?
局部指令:
创建指令(可以多个)
directives: {
// 指令名称
dir1: {}
}
全局指令:
Vue.directive('dir2', {
inserted(el) {
console.log(el);
}
})
指令的使用:
<div id="app">
<div v-dir1></div>
<div v-dir2></div>
</div>
vue如何自定义一个过滤器?
html代码:
<div id="app">
<input type="text" v-model="msg" />
{{msg| capitalize }}
</div>
JS代码:
var vm=new Vue({
el:"#app",
data:{
msg:''
},
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
全局定义过滤器:
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
对keep-alive 的了解?
keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。
使用方法
<keep-alive include='include_components' exclude='exclude_components'>
<component>
<!-- 该组件是否缓存取决于include和exclude属性 -->
</component>
</keep-alive>
参数解释:
include - 字符串或正则表达式,只有名称匹配的组件会被缓存
exclude - 字符串或正则表达式,任何名称匹配的组件都不会被缓存
include 和 exclude 的属性允许组件有条件地缓存。二者都可以用“,”分隔字符串、正则表达式、数组。当使用正则或者是数组时,要记得使用v-bind 。
使用示例:
<!-- 逗号分隔字符串,只有组件a与b被缓存。 -->
<keep-alive include="a,b">
<component></component>
</keep-alive>
<!-- 正则表达式 (需要使用 v-bind,符合匹配规则的都会被缓存) -->
<keep-alive :include="/a|b/">
<component></component>
</keep-alive>
<!-- Array (需要使用 v-bind,被包含的都会被缓存) -->
<keep-alive :include="['a', 'b']">
<component></component>
</keep-alive>
一句话就能说明的:
1.css只在当前组件起作用
答:在style标签中写入scoped即可 例如:<style scoped></style>
2.v-if 和 v-show 区别
答:v-if按照条件是否渲染,v-show是display的block或none;
3.$route和$router的区别
答:$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等。
4.vue.js的两个核心是什么?
答:数据驱动、组件系统
5.vue几种常用的指令
答:v-for 、 v-if 、v-bind、v-on、v-show、v-else
6.vue常用的修饰符?
答:.prevent: 提交事件不再重载页面;.stop: 阻止单击事件冒泡;.self: 当事件发生在该元素本身而不是子元素的时候会触发;.capture: 事件侦听,事件发生的时候会调用
7.v-on 可以绑定多个方法吗?
答:可以
8.vue中 key 值的作用?
答:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。
9.什么是vue的计算属性?
答:在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。好处:①使得数据处理结构清晰;②依赖于数据,数据更新,处理结果自动更新;③计算属性内部this指向vm实例;④在template调用时,直接写计算属性名即可;⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。
<router-link></router-link>组件及其属性
vue-router是vue单页面开发的路由,就是决定页面跳转的!
<router-link> 组件支持用户在具体有路由功能的应用中(点击)导航。通过to属性指定目标地址。
Props 属性:
1、to
表示目标路由的链接。当被点击后,内部会立刻把to的值传到router-push()。
2、replace
设置replace属性的话,当点击时,会调用roter.replace()而不是router.push(),所以导航后不会留下history记录,也就是不能回退到上一个页面
3、append
设置append属性后,则在当前路径前添加基路径,例如,我们从/a导航到一个相对路径b,如果没有配置append,则路径为/b,如果配了,则为/a/b
4、tag
有时候想要<router-link>渲染成某种标签,例如<li>。于是我们使用tag prop 类指定何种标签,同样它还是会监听点击,触发导航。
5、active-class
设置链接激活时使用的css类名。默认值可以通过路由的构造选项linkActiveClass来全局配置, 默认值为 ‘router-link-active‘
export default New Router({
linkActiveClass: ‘active‘
})
6、exact
"是否激活",默认是false 。举个粟子,如果当前的路径是/a 开头的,那么<router-link to="/a"> 也会被设置css类名
7、方法
router-link默认是触发router.push(location),如果设置的replace 则触发router.replace(location),这有啥区别呢?
router.push() :导航跑到不同的URL,这个方法会向history栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的url.
router.replace(): 跟router.push作用是一样的,但是,它不会向history添加新记录,而是跟它的方法名一样替换掉当前的history记录.
router.go(n): 这个方法的参数是一个整数,意思是在history记录中向前或者后退多少步,类似window.history.Go(n)
vue-router路由懒加载的实现
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
component: resolve => require(['components/Hello.vue'], resolve)
},
{
path: '/about',
component: resolve => require(['components/About.vue'], resolve)
}
]
})
vuex有哪几种属性?
有五种,分别是 State、 Getter、Mutation 、Action、 Module
- vuex的State特性
A、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于一般Vue对象里面的data
B、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
C、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中 - vuex的Getter特性
A、getters 可以对State进行计算操作,它就是Store的计算属性
B、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
C、 如果一个状态只在一个组件内使用,是可以不用getters - vuex的Mutation特性
Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态;Action 可以包含任意异步操作。
不用Vuex会带来什么问题?
- 可维护性会下降,想修改数据要维护三个地方;
- 可读性会下降,因为一个组件里的数据,根本就看不出来是从哪来的;
- 增加耦合,大量的上传派发,会让耦合性大大增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。
ajax、axios、fetch之间的详细区别以及优缺点
Ajax:
是对原生XHR的封装,为了达到我们跨越的目的,增添了对JSONP的支持。经过这么多年的更新维护,不得不承认它已经很成熟,能够满足我们的基本需求,但是随着react,vue新一代框架的兴起,以及ES规范的完善,更多API的更新,它逐渐暴露了自己的不足
- 针对MVC的编程设计,不符合现在前端MVVM的趋势
- 基于原生的XHR开发,XHR本身的架构不够清晰
- JQuery较大,单纯使用ajax却要引入整个JQuery非常的不合理
- 虽然axios不支持jsonp,但是可以通过引入jsonp模块来解决
Axios:
Vue2.0之后,自从尤雨溪推荐大家用axios替换JQuery ajax,Axios快速的得到大家的关注。Axios本质就是对原生XHR的封装,增加了Promise的实,符合最新的ES规范,从它的官网上可以看到它有以下几条特性:
- 从 node.js 创建 http 请求
- 支持 Promise API
- 客户端支持防止CSRF(请求中携带cookie)
- 提供了一些并发请求的接口(重要,方便了很多的操作)
Axios既提供了并发的封装,体积也较小,也没有下文会提到的fetch的各种问题,当之无愧是现在最应该选用的请求的方式。
fetch:
号称是AJAX的替代品,fetch是基于原生的XMLHttpRequest对象来实现数据请求的,同时也是基于Promise实现链式调用的。它的好处在《传统 Ajax 已死,Fetch 永生》中提到有以下几点:
- 符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里
- 更好更方便的写法,诸如:
-
使用 await 后,告别面条式调用,将异步写成同步,身心舒畅。从上图可以看到await 后面可以跟 Promise 对象,表示等待 Promise resolve() 才会继续向下执行,如果 Promise 被 reject() 或抛出异常则会被外面的 try...catch 捕获。
坦白说,Jquery还是Axios都已经将xhr封装的足够好,使用起来也足够方便,但是Fetch还是得到很多开发者的认可,说明它还是存在很多优势的:
- 更加底层,提供的API丰富(request, response)
- 脱离了XHR,是ES规范里新的实现方式
- 跨域处理(mode为"no-cors")
-
但是在使用fetch的时候,也会遇到了一些问题:
- fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
- fetch默认不会带cookie,需要添加配置项fetch(url, {credentials: 'include'})
- fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费
- fetch没有办法原生监测请求的进度,而XHR可以
- 所有版本的 IE 均不支持原生 Fetch,fetch-ie8 会自动使用 XHR 做 polyfill。但在跨域时有个问题需要处理。IE8, 9 的 XHR 不支持 CORS 跨域,不支持传 Cookie!所以推荐使用 fetch-jsonp
更多推荐
所有评论(0)