首页
Javascript
Html
Css
Node.js
Electron
移动开发
工具类
服务端
浏览器相关
前端收藏
其他
关于

Fetch进阶指南

2019年08月21日 转载自 路易斯 阅读(95)

导读

Fetch 是 web异步通信的未来. 从chrome42, Firefox39, Opera29, EdgeHTML14(并非Edge版本)起, fetch就已经被支持了. 其中chrome42~45版本, fetch对中文支持有问题, 建议从chrome46起使用fetch. 传送门: fetch中文乱码 .

Fetch

先过一遍Fetch原生支持率.


可见要想在IE8/9/10/11中使用fetch还是有些犯难的,毕竟它连 Promise 都不支持, 更别说fetch了. 别急, 这里有polyfill(垫片).

由于IE8基于ES3, IE9支持大部分ES5, IE11支持少量ES5, 其中只有IE10对ES5支持比较完整. 因此IE8+浏览器, 建议依次装载上述垫片.

尝试一个fetch

先来看一个简单的fetch.

  1. var word = '123',
  2. url = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+word+'&json=1&p=3';
  3. fetch(url,{mode: "no-cors"}).then(function(response) {
  4. return response;
  5. }).then(function(data) {
  6. console.log(data);
  7. }).catch(function(e) {
  8. console.log("Oops, error");
  9. });

fetch执行后返回一个 Promise 对象, 执行成功后, 成功打印出 Response 对象.

response headers

该fetch可以在任何域名的网站直接运行, 且能正常返回百度搜索的建议词条. 以下是常规输入时的是界面截图.

response headers

以下是刚才fetch到的部分数据. 其中key name 为”s”的字段的value就是以上的建议词条.(由于有高亮词条”12306”, 最后一条数据”12366”被顶下去了, 故上面截图上看不到)

response headers

看完栗子过后, 就要动真格了. 下面就来扒下 Fetch.

Promise特性

fetch方法返回一个Promise对象, 根据 Promise Api 的特性, fetch可以方便地使用then方法将各个处理逻辑串起来, 使用 Promise.resolve() 或 Promise.reject() 方法将分别返会肯定结果的Promise或否定结果的Promise, 从而调用下一个then 或者 catch. 一但then中的语句出现错误, 也将跳到catch中.

Promise若有疑问, 请阅读 Promises .

① 我们不妨在 https://sp0.baidu.com 域名的网页控制台运行以下代码.

  1. var word = '123',
  2. url = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+word+'&json=1&p=3';
  3. fetch(url).then(function(response){
  4. console.log('第一次进入then...');
  5. if(response.status>=200 && response.status<300){
  6. console.log('Content-Type: ' + response.headers.get('Content-Type'));
  7. console.log('Date: ' + response.headers.get('Date'));
  8. console.log('status: ' + response.status);
  9. console.log('statusText: ' + response.statusText);
  10. console.log('type: ' + response.type);
  11. console.log('url: ' + response.url);
  12. return Promise.resolve(response);
  13. }else{
  14. return Promise.reject(new Error(response.statusText));
  15. }
  16. }).then(function(data){
  17. console.log('第二次进入then...');
  18. console.log(data);
  19. }).catch(function(e){
  20. console.log('抛出的错误如下:');
  21. console.log(e);
  22. });

运行截图如下:

fetch then

② 我们不妨在非 https://sp0.baidu.com 域名的网页控制台再次运行以上代码.(别忘了给fetch的第二参数传递{mode: “no-cors”})

运行截图如下:

fetch catch

由于第一次进入then分支后, 返回了否定结果的 Promise.reject 对象. 因此代码进入到catch分支, 抛出了错误. 此时, 上述 response.typeopaque .

response type

一个fetch请求的响应类型(response.type)为如下三种之一:

  • basic
  • cors
  • opaque

如上情景①, 同域下, 响应类型为 “basic”.

如上情景②中, 跨域下, 服务器没有返回CORS响应头, 响应类型为 “opaque”. 此时我们几乎不能查看任何有价值的信息, 比如不能查看response, status, url等等等等.

fetch type

同样是跨域下, 如果服务器返回了CORS响应头, 那么响应类型将为 “cors”. 此时响应头中除 Cache-Control , Content-Language , Content-Type , Expores , Last-ModifiedProgma 之外的字段都不可见.

注意: 无论是同域还是跨域, 以上 fetch 请求都到达了服务器.

mode

fetch可以设置不同的模式使得请求有效. 模式可在fetch方法的第二个参数对象中定义.

  1. fetch(url, {mode: 'cors'});

可定义的模式如下:

  • same-origin: 表示同域下可请求成功; 反之, 浏览器将拒绝发送本次fetch, 同时抛出错误 “TypeError: Failed to fetch(…)”.
  • cors: 表示同域和带有CORS响应头的跨域下可请求成功. 其他请求将被拒绝.
  • cors-with-forced-preflight: 表示在发出请求前, 将执行preflight检查.
  • no-cors: 常用于跨域请求不带CORS响应头场景, 此时响应类型为 “opaque”.

除此之外, 还有两种不太常用的mode类型, 分别是 navigate , websocket , 它们是 HTML标准 中特殊的值, 这里不做详细介绍.

header

fetch获取http响应头非常easy. 如下:

  1. fetch(url).then(function(response) {
  2. console.log(response.headers.get('Content-Type'));
  3. });

设置http请求头也一样简单.

  1. var headers = new Headers();
  2. headers.append("Content-Type", "text/html");
  3. fetch(url,{
  4. headers: headers
  5. });

header的内容也是可以被检索的.

  1. var header = new Headers({
  2. "Content-Type": "text/plain"
  3. });
  4. console.log(header.has("Content-Type")); //true
  5. console.log(header.has("Content-Length")); //false

post

在fetch中发送post请求, 同样可以在fetch方法的第二个参数对象中设置.

  1. var headers = new Headers();
  2. headers.append("Content-Type", "application/json;charset=UTF-8");
  3. fetch(url, {
  4. method: 'post',
  5. headers: headers,
  6. body: JSON.stringify({
  7. date: '2016-10-08',
  8. time: '15:16:00'
  9. })
  10. });

credentials

跨域请求中需要带有cookie时, 可在fetch方法的第二个参数对象中添加credentials属性, 并将值设置为”include”.

  1. fetch(url,{
  2. credentials: 'include'
  3. });

除此之外, credentials 还可以取以下值:

  • omit: 缺省值, 默认为该值.
  • same-origin: 同源, 表示同域请求才发送cookie.

catch

同 XMLHttpRequest 一样, 无论服务器返回什么样的状态码(chrome中除407之外的其他状态码), 它们都不会进入到错误捕获里. 也就是说, 此时, XMLHttpRequest 实例不会触发 onerror 事件回调, fetch 不会触发 reject. 通常只在网络出现问题时或者ERR_CONNECTION_RESET时, 它们才会进入到相应的错误捕获里. (其中, 请求返回状态码为407时, chrome浏览器会触发onerror或者reject掉fetch.)

cache

cache表示如何处理缓存, 遵守http规范, 拥有如下几种值:

  • default: 表示fetch请求之前将检查下http的缓存.
  • no-store: 表示fetch请求将完全忽略http缓存的存在. 这意味着请求之前将不再检查下http的缓存, 拿到响应后, 它也不会更新http缓存.
  • no-cache: 如果存在缓存, 那么fetch将发送一个条件查询request和一个正常的request, 拿到响应后, 它会更新http缓存.
  • reload: 表示fetch请求之前将忽略http缓存的存在, 但是请求拿到响应后, 它将主动更新http缓存.
  • force-cache: 表示fetch请求不顾一切的依赖缓存, 即使缓存过期了, 它依然从缓存中读取. 除非没有任何缓存, 那么它将发送一个正常的request.
  • only-if-cached: 表示fetch请求不顾一切的依赖缓存, 即使缓存过期了, 它依然从缓存中读取. 如果没有缓存, 它将抛出网络错误(该设置只在mode为”same-origin”时有效).

如果fetch请求的header里包含 If-Modified-Since, If-None-Match, If-Unmodified-Since, If-Match, 或者 If-Range 之一, 且cache的值为 default , 那么fetch将自动把 cache的值设置为 "no-store" .

async/await

为什么是async/await

回调深渊一直是jser的一块心病, 虽然ES6提供了 Promise, 将嵌套平铺, 但使用起来依然不便.

要说ES6也提供了generator/yield, 它将一个函数执行暂停, 保存上下文, 再次调用时恢复当时的状态.(学习可参考 Generator 函数的含义与用法 - 阮一峰的网络日志) 无论如何, 总感觉别扭. 如下摘自推库的一张图.

我们不难看出其中的差距, callback简单粗暴, 层层回调, 回调越深入, 越不容易捋清楚逻辑. Promise 将异步操作规范化.使用then连接, 使用catch捕获错误, 堪称完美, 美中不足的是, then和catch中传递的依然是回调函数, 与心目中的同步代码不是一个套路.

为此, ES7 提供了更标准的解决方案 — async/await. async/await 几乎没有引入新的语法, 表面上看起来, 它就和alert一样易用, 虽然它尚处于ES7的草案中, 不过这并不影响我们提前使用它.

async/await语法

async 用于声明一个异步函数, 该函数需返回一个 Promise 对象. 而 await 通常后接一个 Promise对象, 需等待该 Promise 对象的 resolve() 方法执行并且返回值后才能继续执行. (如果await后接的是其他对象, 便会立即执行)

因此, async/await 天生可用于处理 fetch请求(毫无违和感). 如下:

  1. var word = '123',
  2. url = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+word+'&json=1&p=3';
  3. (async ()=>{
  4. try {
  5. let res = await fetch(url, {mode: 'no-cors'});//等待fetch被resolve()后才能继续执行
  6. console.log(res);
  7. } catch(e) {
  8. console.log(e);
  9. }
  10. })();

自然, async/await 也可处理 Promise 对象.

  1. let wait = function(ts){
  2. return new Promise(function(resolve, reject){
  3. setTimeout(resolve,ts,'Copy that!');
  4. });
  5. };
  6. (async function(){
  7. try {
  8. let res = await wait(1000);//① 等待1s后返回结果
  9. console.log(res);
  10. res = await wait(1000);//② 重复执行一次
  11. console.log(res);
  12. } catch(e) {
  13. console.log(e);
  14. }
  15. })();
  16. //"Copy that!"

可见使用await后, 可以直接得到返回值, 不必写 .then(callback) , 也不必写 .catch(error) 了, 更可以使用 try catch 标准语法捕获错误.

由于await采用的是同步的写法, 看起来它就和alert函数一样, 可以自动阻塞上下文. 因此它可以重复执行多次, 就像上述代码②一样.

可以看到, await/async 同步阻塞式的写法解决了完全使用 Promise 的一大痛点——不同Promise之间共享数据问题. Promise 需要设置上层变量从而实现数据共享, 而 await/async 就不存在这样的问题, 只需要像写alert一样书写就可以了.

值得注意的是, await 只能用于 async 声明的函数上下文中. 如下 forEach 中, 是不能直接使用await的.

  1. let array = [0,1,2,3,4,5];
  2. (async ()=>{
  3. array.forEach(function(item){
  4. await wait(1000);//这是错误的写法, 因await不在async声明的函数上下文中
  5. console.log(item);
  6. });
  7. })();

如果是试图将async声明的函数作为回调传给forEach,该回调将同时触发多次,回调内部await依然有效,只是多次的await随着回调一起同步执行了,这便不符合我们阻塞循环的初衷。如下:

  1. const fn = async (item)=>{
  2. await wait(1000); // 循环中的多个await同时执行,因此等待1s后将同时输出数组各个元素
  3. console.log(item);
  4. };
  5. array.forEach(fn);

正确的写法如下:

  1. (async ()=>{
  2. for(let i=0,len=array.length;i<len;i++){
  3. await wait(1000);
  4. console.log(array[i]);
  5. }
  6. })();
如何试运行async/await

鉴于目前只有Edge支持 async/await, 我们可以使用以下方法之一运行我们的代码.

  1. 随着node7.0的发布, node中可以使用如下方式直接运行:

    1. node --harmony-async-await test.js
  2. babel在线编译并运行 Babel · The compiler for writing next generation JavaScript .

  3. 本地使用babel编译es6或更高版本es.

    1) 安装.

    由于Babel5默认自带各种转换插件, 不需要手动安装. 然而从Babel6开始, 插件需要手动下载, 因此以下安装babel后需要再顺便安装两个插件.

    1. npm i babel-cli -g # babel已更名为babel-cli
    2. npm install babel-preset-es2015 --save-dev
    3. npm install babel-preset-stage-0 --save-dev

    2) 书写.babelrc配置文件.

    1. {
    2. "presets": [
    3. "es2015",
    4. "stage-0"
    5. ],
    6. "plugins": []
    7. }

    3) 如果不配置.babelrc. 也可在命令行显式指定插件.

    1. babel es6.js -o es5.js --presets es2015 stage-0 # 指定使用插件es2015和stage-0编译js

    4) 编译.

    1. babel es6.js -o es5.js # 编译源文件es6.js,输出为es5.js,编译规则在上述.babelrc中指定
    2. babel es6.js --out-file es5.js # 或者将-o写全为--out-file也行
    3. bable es6.js # 如果不指定输出文件路径,babel会将编译生成的文本标准输出到控制台

    5) 实时编译

    1. babel es6.js -w -o es5.js # 实时watch es6.js的变化,一旦改变就重新编译
    2. babel es6.js -watch -o es5.js # -w也可写全为--watch

    6) 编译目录输出到其他目录

    1. babel src -d build # 编译src目录下所有js,并输出到build目录
    2. babel src --out-dir build # -d也可写全为--out-dir

    7) 编译目录输出到单个文件

    1. babel src -o es5.js # 编译src目录所有js,合并输出为es5.js

    8) 想要直接运行es6.js, 可使用babel-node.

    1. npm i babel-node -g # 全局安装babel-node
    2. babel-node es6.js # 直接运行js文件

    9) 如需在代码中使用fetch, 且使用babel-node运行, 需引入 node-fetch 模块.

    1. npm i node-fetch --save-dev

    然后在es6.js中require node-fetch 模块.

    1. var fetch = require('node-fetch');
  4. 本地使用traceur编译es6或更高版本es.请参考 在项目开发中优雅地使用ES6:Traceur & Babel .

如何弥补Fetch的不足

fetch基于Promise, Promise受限, fetch也难幸免. ES6的Promise基于 Promises/A+ 规范 (对规范感兴趣的同学可选读 剖析源码理解Promises/A规范 ), 它只提供极简的api, 没有 timeout 机制, 没有 progress 提示, 没有 deferred 处理 (这个可以被async/await替代).

fetch-jsonp

除此之外, fetch还不支持jsonp请求. 不过办法总比问题多, 万能的开源作者提供了 fetch-jsonp 库, 解决了这个问题.

fetch-jsonp 使用起来非常简单. 如下是安装:

  1. npm install fetch-jsonp --save-dev

如下是使用:

  1. fetchJsonp(url, {
  2. timeout: 3000,
  3. jsonpCallback: 'callback'
  4. }).then(function(response) {
  5. console.log(response.json());
  6. }).catch(function(e) {
  7. console.log(e)
  8. });

abort

由于Promise的限制, fetch 并不支持原生的abort机制, 但这并不妨碍我们使用 Promise.race() 实现一个.

Promise.race(iterable) 方法返回一个Promise对象, 只要 iterable 中任意一个Promise 被 resolve 或者 reject 后, 外部的Promise 就会以相同的值被 resolve 或者 reject.

支持性: 从 chrome33, Firefox29, Safari7.1, Opera20, EdgeHTML12(并非Edge版本) 起, Promise就被完整的支持. Promise.race()也随之可用. 下面我们来看下实现.

  1. var _fetch = (function(fetch){
  2. return function(url,options){
  3. var abort = null;
  4. var abort_promise = new Promise((resolve, reject)=>{
  5. abort = () => {
  6. reject('abort.');
  7. console.info('abort done.');
  8. };
  9. });
  10. var promise = Promise.race([
  11. fetch(url,options),
  12. abort_promise
  13. ]);
  14. promise.abort = abort;
  15. return promise;
  16. };
  17. })(fetch);

然后, 使用如下方法测试新的fetch.

  1. var p = _fetch('https://www.baidu.com',{mode:'no-cors'});
  2. p.then(function(res) {
  3. console.log('response:', res);
  4. }, function(e) {
  5. console.log('error:', e);
  6. });
  7. p.abort();
  8. //"abort done."
  9. //"error: abort."

以上, fetch请求后, 立即调用abort方法, 该promise被拒绝, 符合预期. 细心的同学可能已经注意到了, “p.abort();” 该语句我是单独写一行的, 没有链式写在then方法之后. 为什么这么干呢? 这是因为then方法调用后, 返回的是新的promise对象. 该对象不具有abort方法, 因此使用时要注意绕开这个坑.

timeout

同上, 由于Promise的限制, fetch 并不支持原生的timeout机制, 但这并不妨碍我们使用 Promise.race() 实现一个.

下面是一个简易的版本.

  1. function timer(t){
  2. return new Promise(resolve=>setTimeout(resolve, t))
  3. .then(function(res) {
  4. console.log('timeout');
  5. });
  6. }
  7. var p = fetch('https://www.baidu.com',{mode:'no-cors'});
  8. Promise.race([p, timer(1000)]);
  9. //"timeout"

实际上, 无论超时时间设置为多长, 控制台都将输出log “timeout”. 这是因为, 即使fetch执行成功, 外部的promise执行完毕, 此时 setTimeout 所在的那个promise也不会reject.

下面我们来看一个类似xhr版本的timeout.

  1. var _fetch = (function(fetch){
  2. return function(url,options){
  3. var abort = null,
  4. timeout = 0;
  5. var abort_promise = new Promise((resolve, reject)=>{
  6. abort = () => {
  7. reject('timeout.');
  8. console.info('abort done.');
  9. };
  10. });
  11. var promise = Promise.race([
  12. fetch(url,options),
  13. abort_promise
  14. ]);
  15. promise.abort = abort;
  16. Object.defineProperty(promise, 'timeout',{
  17. set: function(ts){
  18. if((ts=+ts)){
  19. timeout = ts;
  20. setTimeout(abort,ts);
  21. }
  22. },
  23. get: function(){
  24. return timeout;
  25. }
  26. });
  27. return promise;
  28. };
  29. })(fetch);

然后, 使用如下方法测试新的fetch.

  1. var p = _fetch('https://www.baidu.com',{mode:'no-cors'});
  2. p.then(function(res) {
  3. console.log('response:', res);
  4. }, function(e) {
  5. console.log('error:', e);
  6. });
  7. p.timeout = 1;
  8. //"abort done."
  9. //"error: timeout."

progress

xhr的 onprogress 让我们可以掌控下载进度, fetch显然没有提供原生api 做类似的事情. 不过 Fetch中的Response.body 中实现了getReader()方法用于读取原始字节流, 该字节流可以循环读取, 直到body下载完成. 因此我们完全可以模拟fetch的progress.

以下是 stackoverflow 上的一段代码, 用于模拟fetch的progress事件. 为了方便测试, 请求url已改为本地服务.(原文请戳 javascript - Progress indicators for fetch? - Stack Overflow)

  1. function consume(reader) {
  2. var total = 0
  3. return new Promise((resolve, reject) => {
  4. function pump() {
  5. reader.read().then(({done, value}) => {
  6. if (done) {
  7. resolve();
  8. return;
  9. }
  10. total += value.byteLength;
  11. console.log(`received ${value.byteLength} bytes (${total} bytes in total)`);
  12. pump();
  13. }).catch(reject)
  14. }
  15. pump();
  16. });
  17. }
  18. fetch('http://localhost:10101/notification/',{mode:'no-cors'})
  19. .then(res => consume(res.body.getReader()))
  20. .then(() => console.log("consumed the entire body without keeping the whole thing in memory!"))
  21. .catch(e => console.log("something went wrong: " + e));

以下是日志截图:

刚好github上有个fetch progress的demo, 感兴趣的小伙伴请参看这里: Fetch Progress DEMO .

我们不妨来对比下, 使用xhr的onprogress事件回调, 输出如下:

我试着适当增加响应body的size, 发现xhr的onprogress事件回调依然只执行两次. 通过多次测试发现其执行频率比较低, 远不及fetch progress.

© 本文著作权归原作者所有 来源:路易斯 阅读原文

评论

  •  
  • Fetch进阶指南

    发布:2019-08-21 阅读(95)

  • JS包装对象

    对象是 JavaScript 语言最主要的数据类型,三种原始类型的值——数值、字符串、布尔值——在一定条件下,也会自动转为对象,也就是原始类型的“包装对象”

    发布:2019-08-20 阅读(93)

  • JavaScript数组去重(12种方法)

    JS数组去重的各种方法~

    发布:2019-08-07 阅读(167)

  • iviewui-admin框架的一些坑

    使用iviewui-admin框架构建管理系统时,遇到的各类问题

    发布:2019-08-01 阅读(163)

  • 使用es6的exports和import 进行模块化开发

    使用es6的exports和import 进行模块化开发

    发布:2019-06-14 阅读(407)

  • vue项目v-for中动态图片路径拼接

    vue项目中动态图片路径拼接

    发布:2019-04-04 阅读(772)

  • vue之js调用filter

    vue下filter方法的调用

    发布:2019-03-29 阅读(555)

  • 深入学习Cache-Control

    对于 HTTP头Cache-Control,我们经常使用,也非常&amp;amp;quot;熟悉&amp;amp;quot;,然后经常会有问题,为什么我使用了&amp;amp;quot;no-cache&amp;amp;quot;,然后为什么还有缓存? 看这个文章你就知道为什么了。

    发布:2019-03-15 阅读(325)

  • IntersectionObserver API

    在之前,我们要判断一个元素是否出现在视窗内,需要使用`scroll`或`setInterval`来不断计算元素的位置,这样非常损耗性能,Chrome在2016年的时候推出了IntersectionObserver APi,现在看看它是做什么的

    发布:2019-03-12 阅读(540)

  • 推荐21个顶级的Vue UI库!

    21个vue顶级UI框架: Vuetify,Quasar,Vue Material,Keen-UI,Buefy,Bootstrap Vue,Muse-UI,AT-UI,Vux,iView,Uiv,Vuikit,Onsen UI+Vue,Semantic UI+Vue,Fish-UI,Mint UI,Framework7 Vue,Cube UI,Vueblu,Ant Design Vue

    发布:2019-03-04 阅读(530)

  • 收集的一些轻量高效的开源JavaScript插件和库

    轻量高效的开源JavaScript插件和库

    发布:2019-02-25 阅读(602)

  • input输入时,实时格式化

    格式化input输入~

    发布:2019-02-25 阅读(495)

  • 什么是vue的sfc?怎么解析成SFCDescriptor?

    &amp;amp;amp;quot;.vue&amp;amp;amp;quot;文件是如何解析成js对象的~

    发布:2019-01-29 阅读(530)

  • vue源码阅读1--目录结构及package.json

    立个flag,看过年这段时间能不能把vue的源码读完?多年前看过jQuery的部分源码,如果想要更深入的了解vue,还是得从源码开始

    发布:2019-01-29 阅读(569)

  • Vue之源码解读

    vue源码阅读,慢慢学习

    发布:2019-01-29 来源:github

  • Vue的生命周期及相关问题

    vue的生命周期函数

    发布:2019-01-29 阅读(563)

  • react服务器端渲染之--nextjs

    Next.js 是一个轻量级的 React 服务端渲染应用框架。

    发布:2019-01-24

  • window.atob和btoa进行base64编码解码

    使用原生window.atob和btoa进行base64编码解码

    发布:2019-01-17 阅读(519)

  • nodejieba "结巴"中文分词安装使用

    NodeJieba是&amp;amp;amp;amp;quot;结巴&amp;amp;amp;amp;quot;中文分词的 Node.js 版本实现, 由CppJieba提供底层分词算法实现, 是兼具高性能和易用性两者的 Node.js 中文分词组件。

    发布:2019-01-16 阅读(932)

  • React的两种事件传参方式

    通过箭头函数或bind方式,对绑定事件传参

    发布:2019-01-09 阅读(475)

  • vue data为什么是函数?而不是对象

    vue组件的数据data为什么一定要是函数 ?

    发布:2019-01-07 阅读(930)

  • 回顾一下NaN,isNaN,Number.isNaN

    回顾一下NaN,isNaN,Number.isNaN

    发布:2018-12-28 阅读(514)

  • 利用react-hot-loader实现局部更新

    React Hot Loader是一个插件,允许React组件在不丢失状态的情况下进行实时重新加载。它适用于Webpack和其他支持热模块替换(HMR)和Babel插件的捆绑器

    发布:2018-12-27 阅读(576)

  • 前端码农之蜕变 — AST(抽象语法树)

    如果你查看目前任何主流的项目中的`devDependencies`,会发现前些年的不计其数的插件诞生。我们归纳一下有:javascript转译、代码压缩、css预处理器、elint、pretiier,等。有很多js模块我们不会在生产环境用到,但是它们在我们的开发过程中充当着重要的角色。所有的上述工具,不管怎样,都建立在了AST这个巨人的肩膀上

    发布:2018-12-25 阅读(450)

  • 为什么要在javascript中进行静态类型检查.Part2&amp;3[译]

    在第一部分中我们了解了许多基础知识,结束了语法的学习,我们可以进入下一个更有趣的部分:使用静态类型的优势和劣势

    发布:2018-12-21 来源:AlienZHOU

  • 为什么要在javascript中进行静态类型检查.Part1[译]

    作为一个JavaScript开发者,你可以编写一整天编写也不会遇到任何静态类型检查得问题。那么为什么要自找麻烦得去学习它呢? 然而学习静态类型并不仅仅是一个思维拓展的训练。如果你愿意花点时间来学习一些静态类型的优势、劣势以及使用的案例,那将会极大的帮助你进行编码。 怎么样,有意思吧?要是你感兴趣的话,那接下来四个部分将会向你详细解释

    发布:2018-12-21 来源:AlienZHOU

  • Mint-ui this.$messagebox报 Uncaught (in promise) cancel

    Mint-ui this.$messagebox点取消时,报错:Uncaught (in promise) cancel

    发布:2018-11-16 阅读(641)

  • vue vee-validate验证插件使用

    vue-validate使用

    发布:2018-11-08 阅读(868)

  • vue之query和params,$router和$route

    这就是个vue的坑。。。

    发布:2018-11-08 阅读(585)

  • vue监听Enter事件

    vue如何监听enter事件?

    发布:2018-11-08 阅读(923)

  • vue使用axios进行form表单提交

    vue使用axios进行form表单提交

    发布:2018-11-07 阅读(851)

  • ECMA-262-5 详解 - 3.1 词法环境:通用理论 – ds.laboratory

    这一节,我们会讨论词法环境的细节,它是在一些编程语言中用于管理静态作用域的一种机制。为了确保能充分理解这一主题,我们会简要讨论下其对立面:动态作用域(并没有直接用于 ECMAScript)。我们会看到环境是如何管理代码中的词法嵌套结构,以及为闭包提供全面支持。

    发布:2018-11-03 阅读(367)

  • vue中如何改变title标题

    vue中如何改变title标题

    发布:2018-11-02 阅读(524)

  • vue2.0中使用NProgress进度条

    如果在vue2.0中使用NProgress进度条

    发布:2018-11-02 阅读(669)

  • vue2.0 Axios中文说明

    Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。也是vue2.0官方推荐的,同时不再对vue-resource(vue1.0使用)进行更新和维护

    发布:2018-11-01 阅读(610)

  • React资源、教程、案例

    React 的核心思想是:封装组件。 各个组件维护自己的状态和 UI,当状态变更,自动重新渲染整个组件。 基于这种方式的一个直观感受就是我们不再需要不厌其烦地来回查找某个 DOM 元素,然后操作 DOM 去更改 UI

    发布:2018-10-29 阅读(286)

  • ECMA-262-5详述 第一章. 属性和属性描述符

    这一章专门讨论了ECMA-262-5 规范的新概念之一 — 属性特性及其处理机制 — 属性描述符。 当我们说“一个对象有一些属性”的时候,通常指的是属性名和属性值之间的关联关系。但是,正如在ES3系列文章中分析的那样,一个属性不仅仅是一个字符串名,它还包括一系列特性—比如我们在ES3系列文章中已经讨论过的{ReadOnly},{DontEnum}等。因此从这个观点来看,一个属性本身就是一个对象

    发布:2018-10-26 阅读(314)

  • Vue.js 技术揭秘

    分析Vue.js源码

    发布:2018-10-25 来源:github.io

  • 运行npm run dev,vuejs二级路由,刷新页面静态资源404(路径不对)

    npm run dev模式下,webpack4+vue2项目下,类似'/user/login'二级路由,刷新时静态资源路径不对,静态资源返回404

    发布:2018-10-23 阅读(821)

  • vuejs报错:[Vue warn]: Error in render: TypeError: Cannot read property 'matched' of undefined

    [Vue warn]: Error in render: "TypeError: Cannot read property 'matched' of undefined"

    发布:2018-10-22 阅读(1087)

  • Unknown custom element:- did you register the component correctly

    did you register the component correctly? For recursive components, make sure to provide the "name" option

    发布:2018-10-22 阅读(1201)

  • vue.js查看注册了哪些基础组件

    vue.js如何查看注册了哪些组件,获取组件名称

    发布:2018-10-22 阅读(459)

  • [阮一峰]JavaScript 教程

    本教程全面介绍 JavaScript 核心语法,从最简单的讲起,循序渐进、由浅入深,力求清晰易懂。所有章节都带有大量的代码实例,便于理解和模仿,可以用到实际项目中,即学即用。

    发布:2018-10-19 来源:wangdoc.com

  • [阮一峰]ECMAScript 6 入门

    《ECMAScript 6 入门》是一本开源的 JavaScript 语言教程,全面介绍 ECMAScript 6 新引入的语法特性。

    发布:2018-10-19

  • snabbdom——Virtual DOM实现

    vue底层的Virtual DOM就是基于snabbdom修改的

    发布:2018-06-29 来源:snabbdom

  • ECMA-262-3 in detail——第七章:OOP(第二部分:ECMAScript实现)

    这一章的第二部分是关于EMCAScript中的面向对象编程。在第一部分中我们讨论了OOP的基本理论并勾画出和ECMAScript的相似之处。在阅读第二部分之前,如果有必要,我还是建议首先阅读这一章的第一部分.基本理论,因为后面将会用到其中的一些术语。

    发布:2015-05-26 阅读(327)

  • ECMA-262-3 in detail——第七章:OOP(第一部分:一般理论)

    这一章我们讨论ECMAScript中面向对象编程(object-oriented programming)的几个主要方面。由于这一主题已经在许多文章中谈论过,本章并不打算“老调重弹”,而是试图更多地着眼于这些过程内在的理论方面。尤其是,我们将研究对象创建的算法,看看对象间的关系(包括最基本的关系——继承)是如何实现的,并且给出一些讨论中将用到的准确定义(我希望这样能够打消一些术语和思路上的疑惑以及一些关于Javascript文章中OOP部分的常见的混淆)。

    发布:2015-05-06 阅读(301)

  • ECMA-262-3 in detail——第六章:闭包

    在这一章中我们来谈谈Javascript中被讨论最多的话题之一——关于闭包(closures)。事实上这个主题并不是新鲜的。然而我们在这里将试着更多从理论的角度去分析和理解它,然后我们还会看一下ECMAScript内关于闭包的内容。

    发布:2015-04-28 阅读(297)

  • ECMA-262-3 in detail——第五章:函数

    在这章里我们讨论ECMAScript中的一个基本对象——函数。我们将会看到不同类型的函数如何影响一个上下文中的变量对象,以及这些函数的作用域链中都包含什么。我们将会回答像下面这样经常被问到的问题:“下面这两种创建函数的方式有什么区别吗(如果有的话,区别是什么呢)?”

    发布:2015-04-17 阅读(302)

  • ECMA-262-3 in detail——第四章:作用域链

    正如我们从第二章.变量对象中了解到的,执行上下文的数据(变量,函数声明,函数形参)以变量对象的属性的方式储存。

    发布:2015-04-07 阅读(287)

  • ECMA-262-3 in detail——第三章:this关键字

    许多程序员习惯于认为在编程语言中,this关键字是与面向对象编程紧密相关的,而且引用的是由构造式最新创建的对象。在ECMAScript中,这个概念也被实现了,然而我们将看到,在这里它不仅仅指向已创建的对象。

    发布:2015-03-25 阅读(290)

  • ECMA-262-3 in detail——第二章:变量对象

    在程序中我们总是声明变量和函数然后用它们来搭建我们的系统。但是解释器(interpreter)是在哪里和以什么方式来找到我们的数据(函数,变量)的呢?

    发布:2015-03-24 阅读(312)

  • ECMA-262-3 in detail——第一章:执行上下文

    第1章:在这一章里,我们将会讨论ECMAScript中的执行上下文(execution context)以及与它们相关的可执行代码(executable code)的类型。

    发布:2015-01-10 阅读(510)

  • javascript检测浏览器的缩放状态,页面放大了或缩小了

    检测这种缩放有很种方法,QQ空间都通过flash来检测浏览器是否处于缩放。这里提供javascript的方法来检测浏览器的缩放。

    发布:2014-10-13 阅读(567)

  • javascript判断是否有夏令时(Daylight Saving Time)

    当你的项目中的时间需要考虑时区,夏令时时,下面判断夏令时的方法就很有用了!

    发布:2014-07-22 阅读(266)

  • for in循环的输出顺序问题

    在以前的编码过程中,对for...in遍历对象的循环的,一直以为是没有顺序的。直到遇到有对象有的key值为纯数字时,发现现代浏览器对for...in循环是有顺序之分的。

    发布:2014-05-29 阅读(183)

  • 使用js禁用右键菜单、F5刷新和Ctrl+R刷新、backspace键、esc键

    有时候我们需要把网页的右键菜单禁用,然后启用自己模似的右键菜单。或者我们为了避免用户习惯性的使用F5刷新或使用Ctrl+r键刷新导致表单数据的丢失,我们还需要把F5键和ctrl+r键都屏蔽掉。甚至根据需要还可能会屏蔽退格键(Backspace)和退出键(Esc)。

    发布:2014-05-26 阅读(253)

  • js中preventDefault、stopPropagation、return false三者之间的区别及使用

    preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然是说默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用当然就无效了。什么元素有默认行为呢?如链接<a>,提交按钮<input type="submit">等。当Event 对象的 cancelable为false时,表示没有默认行为,这时即使有默认行为,调用preventDefault也是不会起作用的

    发布:2014-05-26 阅读(289)

  • javascript检测是否联网,是否为脱机状态

    通过JS检测网络是否OK,最简单粗暴的方式就是加载网络资源,JS文件或者图片文件...

    发布:2014-05-19 阅读(241)

  • jQuery对象中类数组的概念及操作

    什么是类数组?相信我们对function方法的arguments很熟悉,arguments就像一个数组,但instanceof Array检测会返回false,可以称为“类数组”。

    发布:2014-04-10 阅读(263)

  • 利用iframe实现跨域访问

    利用iframe实现跨域

    发布:2014-03-19 阅读(253)

  • javascript方法setMonth设置2月份变成3月份的小问题

    项目使用了setMonth来设置时间,发现了一个问题,2月份设置下去,显示出来变成3月份了。

    发布:2013-12-22 阅读(240)

  • jquery使用不当导致内存泄漏

    jQuery是现在最流行的js库,一般情况下我们都会放心的使用它,不用考虑其内存泄漏的问题。 最近的项目是基于MVC模式的管理系统,期间要采用ajax不断轮询服务器,以获得最新的数据,这时候使用jQuery的时候就要注意了,一不小心俺们最可爱的IE内存就up up up了~~

    发布:2013-12-10 阅读(270)

  • javascript严格模式(use strict)

    除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode)。顾名思义,这种模式使得Javascript在更严格的条件下运行。

    发布:2013-11-13 阅读(267)

  • IE提示expected 错误,如expected ';' expected '}' expected ')'等等

    IE提示expected 错误,如果语法没问题,不防检查下是不是文件编码问题,改为utf-8试试

    发布:2013-11-01 阅读(243)

  • javascript原始数据类型相互转换

    javascript原始数据类型相互转换示例,如字符串、数字、布尔类型的相互转换

    发布:2013-10-19 阅读(373)

  • javascript Arguments对象之length、callee属性

    arguments是调用对象的一个属性,它与形参及局部变量是一样的,它实际上是调用了一个Arguments对象,Arguments对象与数组相似,但它又不是数组,因为它不具备数组的一些常用方法,如push,sort,shift等等。Arguments对象有两个属性:

    发布:2013-09-30 阅读(261)

  • Javascript容错处理,window.onerror或try{}catch(err){}

    利用javascript开发WEB功能时,代码量小还OK,如果代码非常庞大,这就不可避免的出现一些未知的错误。如果web已经上线,这时却出现了js脚本错误,这对WEB的用户体验是致使的,因为一但出现js脚本错误,网页将停止加载,从而不能正常显示出页面,而失去用户。

    发布:2013-08-15 阅读(234)

  • 利用Object.prototype.toString判断javascript数据类型(数组,函数,类对象{},布尔类等)

    一般情况下,判断javasceript数据类型,使用typeof 或 instanceof 就够了,但偶觉得用起来还是别别扭扭的。这里介绍一个完美的方法,我们可以轻松的判断数组,对象(这里对象暂且指{}),函数(function),布尔(Boolean),null,undefined,number,时间对象(date),正则表达式(RegExp)。

    发布:2013-08-12 阅读(277)

  • 高效javascript模板引擎——doT.js原理及应用

    目前完成的一个基于MVC模式的管理系统,综合考虑后,选择了doT.js,这篇文章主要也是介绍下它的优势及使用方法。

    发布:2013-08-09 阅读(324)

  • js移动光标到文字末尾

    移动光标到文字末尾,如果使用<input><textarea>时,需要把光标定位在文字的后面

    发布:2013-07-28 阅读(211)

  • Javascript数字类型小数表示方式的三种方法:toFixed,toExponential,toPrecision

    javascript提供了三个方法来计算表示小数点的位数:toFixed,toExponential,toPrecision

    发布:2013-05-30 阅读(327)

  • jQuery.support源码分析(检测浏览器兼容)

    jquery.support主要是检测浏览器兼容性,支持力度的方法,用于展示不同浏览器各自特性和bug的属性集合。作为一个静态成员,提供给jquery内部函数,告诉他们某些功能是否能用。避免了以往通过检测浏览器版本做修改。

    发布:2013-05-08 阅读(76)

  • IE下javascript:void(0)触发onbeforeunload

    使用MVC模式开发一些项目时,我们一般会添加onbeforeunload方法,以防止客户无意识的跳出页面,丢失数据。

    发布:2013-03-22 阅读(182)

  • iframe跨域加载页面cookie丢失的问题

    利用iframe跨域加载页面,cookie失效的问题: 主要是浏览器不接受第三方cookie引发的

    发布:2013-03-05 阅读(272)

  • javascript typeof运算符

    typeof操作符,typeof是返回“表达式”的数据类型的字符串

    发布:2013-01-27 阅读(282)

  • javscript原始数据类型相互转换

    发布:2013-01-22 阅读(348)

  • Javascript基本数据类型[Undefined,null,String,Number,Boolean]

    Javascript有五种基本的数据类型:Undefined,null,String,Number,Boolean,这五种数据类型都可以用typeof来检测

    发布:2013-01-05 阅读(297)

  • javascript检测IE6/7/8,chrome,safari,firefox,opera等主流浏览器类型

    利用javascript检测浏览器的类别,网上也会有很多的代码,这里总结写了一下,主要检测主流的五款浏览器(IE,Chrome,Opera,Safari,Firefox)的类别,IE可以检测到IE6-IE9的本种版本,IE10没有检测过。

    发布:2012-11-27 阅读(301)

  • jQuery跳出each循环(替换break,continue)

    jQuery each循环中,如果要实现类似break或continue的功能,不用跟原生javascript for循环一样用break或continue了,而必须用reaturn false、return true

    发布:2012-11-14 阅读(366)

  • 理解javascript函数柯里化(Currying)

    在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术

    发布:2012-11-05 阅读(321)

  • IE6,IE7下onresize事件被执行多次的问题之解决方法

    IE下给window对象定义其onresize事件,在拉伸缩小窗口时,其onresize方法将被执行多次,并且其具体执行的次数在不同的电脑有不同的值,相当诡异,Firefox等其他浏览器则无此现象

    发布:2012-11-05 阅读(442)

  • javascript获取地址栏(url)QueryString(参数)值

    通过浏览器获取URL参数值

    发布:2012-10-30 阅读(388)

  • javascript获取浏览器窗口的宽度、高度

    通过原生js获取浏览器宽高、可视区域、滚动区域等等

    发布:2012-10-29 阅读(378)

  • iframe同域或异域下高度自动适应(兼容种浏览器)

    利用javascript来控制iframe的高度自动适应,介于javascript对不同域名权限的限制,分为两种情况

    发布:2012-10-25 阅读(408)

  • js添加收藏夹代码(兼容IE,firefox,其他浏览器弹信息提示)

    完全兼容IE和firefox的“添加收藏夹代码,chrome,safari会提示信息"添加收藏失败,请同时按"CTRL+D"添加“

    发布:2012-10-23 阅读(356)

  • 获取当前时间、日期、星期(兼容IE,Firefox,Chrome,Opera,Safari...)

    获取当前时间代码,用原生JS所写,兼容种浏览器

    发布:2012-10-22 阅读(526)