山外小楼

前端攻略

0%

默认创建对象时属性为数据属性

数据属性

字面量创建属性时默认为

1
2
3
4
5
6
{
value: undefined,
writable: true,
enumerable: true,
configurable: true
}

Object.defineProperty方法创建属性时默认为

1
2
3
4
5
6
{
value: undefined,
writable: false,
enumerable: false,
configurable: false
}

可以使用Object.getOwnPropertyDescriptorObject.getOwnPropertyDescriptors方法来获取对象属性的描述符信息;

  1. configurablefalse,writabletrue时,可通过赋值的方式或者Object.defineProperty的方式修改value值;
  2. configurablefalse,writablefalse时,只能通过Object.defineProperty的方式修改value值;
  3. configurablefalse,writabletrue时,可将wirtable设置为false;
  4. configurablefalse,writablefalse时,无法修改wirtable的值;
  5. configurablefalse后,也无法修改为true;

访问器属性

字面量创建访问器属性为

1
2
3
4
5
const obj={
get a() {
return 1
}
}

Object.defineProperty方法创建访问器属性

1
2
3
4
5
6
const obj={}
Object.defineProperty(obj, 'a' ,{
get() {
return 1
}
})

默认值为

1
2
3
4
5
6
{
get: undefined,
set: undefined,
enumerable: true,
configurable: true
}

方法

  1. 为目标对象设置单个属性
    设置单个属性可以使用Object.defineProperty()方法,要注意的是,对于同一个属性,不可以同时在描述符中指定属于数据描述符的value,writable和属于访问器描述符的get,set,否则会报错。

  2. 为目标对象设置多个属性
    设置多个属性可以使用Object.defineProperties()方法。

  3. 禁止目标对象扩展(不允许添加新属性
    禁止添加新属性可以使用Object.preventExtensions()方法,该方法接收一个目标对象传入,使用后该对象禁止添加新属性。使该对象禁止扩展。

  4. 密封目标对象(不允许扩展且不允许进行属性配置)
    我们可以使用Object.seal() 方法创建一个“密封”的对象,这个方法实际上会在一个现有对象上调用 Object.preventExtensions()方法 并把所有现有属性标记为configurable:false。密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(但是可以修改属性的值)

  5. 冻结目标对象(密封对象且不允许修改)
    Object.freeze(..) 会创建一个冻结对象,这个方法实际上会在一个现有对象上调用 Object.seal(..) 并把所有“数据访问”属性标记为 writable:false,这样就无法修改它们的值。

图例

flex示例

说明

本身的宽高,不包括border

  • clientWidth
  • clientHeight

本身的宽高,包括border

  • offsetWidth
  • offsetHeight

距离左侧和上部的距离,相对于窗口

  • offsetLeft
  • offsetTop

获取可以滚动的宽度(不包括border)如果内容宽高比本身小,该值为本身宽高,否则就是内容的宽高

  • scrollWidth
  • scrollHeight

滚动出去的距离

  • scrollLeft
  • scrollTop

相对于窗口左上角的点

  • clientX
  • clientY

相对于屏幕左上角的点(建议移动端使用)

  • screenX
  • screenY

相对于本身左上角的点(非标准属性)

  • offsetX
  • offsetY

相对于整个文档左上角的点(建议移动端使用)

  • pageX
  • pageY

获取窗口的宽高

  • document.body.clientWidth
  • document.body.clientHeight
  • document.body.offsetWidth (border)
  • docuemnt.body.offsetHeight (border)

获取正文的宽高(可以滚动的宽高)

  • document.body.scrollWidth
  • docuemnt.body.scrollHeight

获取正文滚出去的宽高

  • document.body.scrollTop
  • document.body.scrollLeft

获取屏幕分辨率宽高

  • window.screen.width
  • window.screen.height

获取左边框宽度和上边框宽度

  • clientLeft
  • clientTop

问题

在绑定 scroll 、resize 这类事件时,当它发生时,它被触发的频次非常高,间隔很近。如果事件中涉及到大量的位置计算、DOM 操作、元素重绘等工作且这些工作无法在下一个 scroll 事件触发前完成,就会造成浏览器掉帧。加之用户鼠标滚动往往是连续的,就会持续触发 scroll 事件导致掉帧扩大、浏览器 CPU 使用率增加、用户体验受到影响。尤其是在涉及与后端的交互中,前端依赖于某种事件如 resize,scroll,发送 Http 请求,在这个过程中,如果不做防抖处理,那么在事件触发的一瞬间,会有很多个请求发过去,增加了服务端的压力。

函数防抖(debounce)

当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。定义如下:

对于短时间内连续触发的事件(上面的滚动事件),防抖的含义就是让某个时间期限(如 1000 毫秒)内,事件处理函数只执行一次。

例如:在第一次触发事件时,不立即执行函数,而是给出一个期限值比如 200ms,然后:

  • 如果在 200ms 内没有再次触发滚动事件,那么就执行函数
  • 如果在 200ms 内再次触发滚动事件,那么当前的计时取消,重新开始计时

效果:如果短时间内大量触发同一事件,只会执行一次函数。

实现:既然前面都提到了计时,那实现的关键就在于 setTimeOut 这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function debounce(fn, delay) {
let timer = null; //借助闭包
return function() {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(fn, delay); // 简化写法
};
}
function showTop() {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log("滚动条位置:" + scrollTop);
}
window.onscroll = debounce(showTop, 1000); // 为了方便观察效果我们取个大点的间断值,实际使用根据需要来配置

函数节流(throttle)

另一种场景,比如在做图片懒加载的时候,我们是希望一段时间去触发一次,而不是只在最后触发一次。这样我们可以设计一种类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这段时间后再重新激活(类似于技能冷却时间)。

效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 时间戳方案
var throttle = function(func, delay) {
var prev = Date.now();
return function() {
var context = this;
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
};
};
function handle() {
console.log(Math.random());
}
window.addEventListener("scroll", throttle(handle, 1000));

// 定时器方案
var throttle = function(func, delay) {
var timer = null;
return function() {
var context = this;
var args = arguments;
if (!timer) {
timer = setTimeout(function() {
func.apply(context, args);
timer = null;
}, delay);
}
};
};
function handle() {
console.log(Math.random());
}
window.addEventListener("scroll", throttle(handle, 1000));

总结

函数防抖:将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

函数节流:使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。

区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

问题

近期将项目的 vue 脚手架由 2 升级到了 3,在此过程中遇到的一些问题记录如下

案例

  1. vue 挂载方式改变
1
2
3
4
5
6
7
8
9
10
11
12
//原方式
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
// 现改为
new Vue({
router,
render: h => h(App)
}).$mount('#app')
  1. HTML 标签之间的间隙默认被删除,表现为原来在页面上内联元素之间因换行产生的空隙没有了
1
2
3
4
5
6
7
8
9
10
11
// 由于原项目并没有处理空隙,而且利用了空隙,为保持表现一致,可添加如下配置
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.compilerOptions.preserveWhitespace = true
return options
})
}

3.

作者:蓝博
链接:https://juejin.im/post/5c642f2ff265da2de660ecfc
来源:掘金

起源

2019年1月29日,Chrome72正式版(72.0.3626.81)发布,本次发布带来了一个改变,且没有在更新日志中提及,该改变导致某些网站发生了布局错乱。该改变主要针对的是嵌套的flex布局,下面我们一起看下是怎么回事。

问题

首先,我们有一个嵌套的flex布局,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<style>
div {
box-sizing: border-box;
}
.flex {
display: flex;
flex-direction: column;
}
.area {
padding: 10px;
height: 300px;
width: 300px;
background-color: #3fb9ab;
color: #fff;
}
.item {
padding: 10px;
flex: 1;
background-color: #158c7e;
}
.nest-item {
flex: 1;
overflow: auto;
background-color: #046b5f;
}
.content {
padding: 10px;
height: 600px;
}
</style>
<div class="area flex">
area
<div class="item flex">
item
<div class="nest-item">
<div class="content">content</div>
</div>
</div>
</div>

希望实现这样的效果:父容器area有一个指定的高度,且它是一个flex弹性盒子,它内部有一个子元素item,使用 flex: 1 指定了占满剩余空间,且item也是一个flex弹性盒子,它内部还有一个同样占满剩余空间的嵌套子元素nest-item,通过设置 overflow: auto 让它的内容超出后显示滚动条。效果如下:

flex示例

这样布局的想法很简单,即通过设置弹性盒子子元素的扩展比率,能得到一个自动占满剩余空间高度的容器,再在这个容器中放需要显示的内容,在某些情况下,这确实是一个比较不错的主意,在Chrome72之前都是可以正常显示的。但是Chrome72.0.3626.81中显示如下:

flex示例

追溯

为什么会出现这样的问题呢?我们看一下规范,flex弹性盒子主轴上子元素的最小大小是内容的大小(视主轴方向为宽或高)。

那么我们再看一下上面的例子,area的主轴是纵向的,子元素item的最小高度即是内容的高度,而nest-item被content撑开,content有一个高度(600px,超出了容器的高度),那么item的最小高度也就超过了600px。这样一来,一层层都是被内容撑开,也就没有出现滚动条了,这样似乎是符合规范预期的。

在chromium的issue反馈中,有人提到了这个问题,根据回复,这正是官方为了让Chrome更加符合规范行为而做的调整。也就是说,Chrome72之前的版本,这算是一个没有按照规范行为而出现的bug。新的调整,其实就是让flex弹性盒子的子元素最小高度的默认行为应用 min-height: min-content ,就像官方回复中提到的那样,让子元素作为flex弹性盒子时却和普通盒子处理方式不同是会让人困惑的。

解决方法

既然知道了原因,那么如果我们还想使用这样的布局方式,该怎么做呢?

对的,我们给item指定一个最小高度,让它不使用默认的行为(即内容的高度),一般我们指定最小高度为0 min-height: 0。给item加上这个样式后,我们再看一下效果:

flex示例

嗯,已经符合我们的预期了。为了验证规范中提到的对主轴方向的行为,我们修改一下代码,将主轴设置为水平方向试试,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<style>
div {
box-sizing: border-box;
}
.flex {
display: flex;
flex-direction: row;
}
.area {
padding: 10px;
height: 300px;
width: 300px;
background-color: #3fb9ab;
color: #fff;
}
.item {
padding: 10px;
flex: 1;
background-color: #158c7e;
}
.nest-item {
flex: 1;
overflow: auto;
background-color: #046b5f;
}
.content {
padding: 10px;
width: 600px;
}
</style>
<div class="area flex">
area
<div class="item flex">
item
<div class="nest-item">
<div class="content">content</div>
</div>
</div>
</div>

效果如下:

flex示例

看来主轴为水平方向时,是符合规范预期行为的(Chrome72及以前的版本都符合),那么我们给item加上一句样式 min-width: 0 ,效果如下:

flex示例

嗯,是符合我们预期的。

结语

好了,现在你已经知道是怎么一回事了,可是等等,你说你升级到Chrome72没有发现我说的问题?

那是因为官方注意到这个修改会影响到一些网站的正常显示,因此在2019年2月6日(正是春节假期间)发布的Chrome72.0.3626.96中,将这个问题还原回以前的行为了。

官方的意思是为了避免这个修改给某些网站带来的不好的影响,因此预留时间给大家修改,等到Chrome73将会发布这一改变。所以为了未来更好的浏览体验,检查一下你的页面吧!

文章出处:https://www.cnblogs.com/JRliu/p/9004304.html

问题

我们在使用 async/await 语法时,有时会这样用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function getName () {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('tony')
}, 2000)
})
}
function getId () {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('123')
}, 3000)
})
}

;(async ()=>{
let name = await getName()
let id = await getId()
alert(`name:${name}, id:${id}`)
})()

一眼看上去,应该是3秒种多一点就会 alert 出 ‘name:tony, id:123’,实际上却花费了5秒才出现提示框,她们是串行执行的!而我们想要的是并行执行,因为她们之间并没有依赖关系。串行执行只会白白增加无谓的等待时间!怎么解决呢?

解决

我们先看 Promise 的语法:

new Promise( function(resolve, reject) {…} /* executor */ );executor是带有 resolve 和 reject 两个参数的函数 。 Promise构造函数执行时立即 调用executor 函数 , resolve 和 reject 两个函数作为参数传递给executor(executor 函数在Promise构造函数返回新建对象前被调用)。resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。executor 内部通常会执行一些异步操作,一旦完成,可以调用resolve函数来将promise状态改成fulfilled,或者在发生错误时将它的状态改为rejected。

传给 Promise 作为参数的函数会在 new 创建实例时立即调用上面的代码,可以分解成这样:

1
2
3
4
5
6
7
;(async ()=>{
let namePromise = getName()
let name = await namePromise
let idPromise = getId() // 2000ms之后才生成 Promise 实例
let id = await idPromise
alert(`name:${name}, id:${id}`)
})()

所以,如果想并行执行,我们应该先生成所有需要使用的Promise实例:

1
2
3
4
5
6
7
;(async ()=>{
let namePromise = getName()
let idPromise = getId() // 先生成所有 promise 实例
let name = await namePromise
let id = await idPromise
alert(`name:${name}, id:${id}`)
})()

或者使用Promise.all

1
2
3
4
;(async ()=>{
var result = await Promise.all([getName(), getId()])
alert(`name:${result[0]}, id:${result[2]}`)
})()

问题引出

在项目中,采用了element-ui框架及echarts;模板结构是一个tab切换页中,引入了自己做了简单封装的echarts;
在上一版还可以正常显示出图,而在后来对封装的echarts做了简单更新后,图表在tab切换页无法显示出来;

问题排查

通过查看element元素发生,图表元素canvas的宽度为0(高度是我自己指定的);然后在echarts组件中通过apiechartsinstance.getWidth()发现结果为0,说明在echarts实例化的时候,dom元素的宽度为0;

echarts的实例化是在vue的mounted阶段进行的,也就是说在这个阶段dom元素没有宽度;

这里还涉及到几个区别;

  1. 图表组件更新之前是可以出图的,排查后发现,之前图表实例化是在数据发生变化的时候执行的,而数据是父组件在mounted阶段通过ajax请求获得数据传给echarts子组件的;那么父组件在mounted阶段,dom情况怎么样了呢

  2. 改版后,图表实例化只执行一次,是在mounted阶段执行的;而tabs组件有可能在初次渲染时,默认tab页面都是属于隐藏的,从而在这个时候可能没有高度;

以上是改版前后的区别及原因的猜想;其中主要涉及的几个问题;

  1. 父组件和子组件的js方法的执行顺序是怎样的?

通过测试可以知道,执行顺序如下;

父组件created—>子组件created—>子组件mounted—>父组件mounted

如果有多个子组件:

父组件created钩子结束后,依次执行子组件的created钩子
多个子组件的created执行顺序为父组件内子组件DOM顺序
多个子组件的mounted顺序无法保证,跟子组件本身复杂程度有关
父组件一定在所有子组件结束mounted钩子之后,才会进入mounted钩子

以上说法存疑

  1. 什么时候才可以获取到dom元素的高度,或者说什么时候dom渲染完成了呢?

这是一个涉及到生命周期的问题;那么再回去仔细看看关于生命周期的说明;在官方文档中有提到

el被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted被调用时 vm.$el 也在文档内。

注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted

1
2
3
4
5
6
7
8

mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}

这样就是相当于,改版前,在父组件的mounted阶段执行请求后得到数据传给子组件,这是一个异步过程,异步是放在最后执行的,然后图表初始化,获得了元素高度;

改版后,是在子元素mounted阶段执行初始化;此时tab中的标签页虽然已存在,但属于隐藏状态,是没有宽度的,此时获取宽度是获取不到的;

DOM的修改不会立马导致渲染,渲染线程是在一个独立的线程运行的,但是渲染线程和Javascript线程是互斥的,必须等待Javascript的这次调度执行完或线程挂起了,才能执行渲染;

前言

由于项目的对外,所以项目需要做国际化,vue项目的国际化自然要用到vue-i18n这个插件,现就国际化中遇到的情况及解决方案整理如下

翻译文本在template

这里的文本会即时替换

翻译文本在实例js

这里的文本由于在首次实例化后就不会再变化,所以需要手动触发一次变化

翻译文本在实例之外的js中

mega 开发 鉴于原系统的维护性较差,项目插件引用众多,代码过多冗余,国际化繁琐,开发vue框架的新版mega(框架部分,首页部分内容,中英文国际化)
clever_db
开发
慢查询详情页面改版完成,新版不需要用户选择分时天粒度,

前言

记录vue在使用中遇到的需要注意的问题

正文

  1. vue-router中路由path值的问题

在嵌套路由使用时,设置path值的时候,注意,如是顶层路由,可以写为/home,即可以加/;在设置二级路由的时候虽然也可以这么写,但就失去了路由层级,在官方文档中有提示:

要注意,以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。

  1. vue-router中路由name值的问题

在编程导航的时候,我们可以使用path或者name,使用name的时候发现,name的值不可以重复,就算时平行路由各自的子路由也不能重复name,否则导航发生混乱;

1xx(临时响应)

表示临时响应并需要请求者继续执行操作的状态代码。

http状态码 100 (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。

http状态码 101 (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。

2xx (成功)

表示成功处理了请求的状态代码。

http状态码 200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。

http状态码 201 (已创建) 请求成功并且服务器创建了新的资源。

http状态码 202 (已接受) 服务器已接受请求,但尚未处理。

http状态码 203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。

http状态码 204 (无内容) 服务器成功处理了请求,但没有返回任何内容。

http状态码 205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。

http状态码 206 (部分内容) 服务器成功处理了部分 GET 请求。

3xx (重定向)

表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。

http状态码 300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。

http状态码 301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。

http状态码 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

http状态码 303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。

http状态码 304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。

http状态码 305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。

http状态码 307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

4xx(请求错误)

这些状态代码表示请求可能出错,妨碍了服务器的处理。

http状态码 400 (错误请求) 服务器不理解请求的语法。

http状态码 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。

http状态码 403 (禁止) 服务器拒绝请求。

http状态码 404 (未找到) 服务器找不到请求的网页。

http状态码 405 (方法禁用) 禁用请求中指定的方法。

http状态码 406 (不接受) 无法使用请求的内容特性响应请求的网页。

http状态码 407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。

http状态码 408 (请求超时) 服务器等候请求时发生超时。

http状态码 409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。

http状态码 410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。

http状态码 411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。

http状态码 412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。

http状态码 413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。

http状态码 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。

http状态码 415 (不支持的媒体类型) 请求的格式不受请求页面的支持。

http状态码 416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。

http状态码 417 (未满足期望值) 服务器未满足”期望”请求标头字段的要求。

5xx(服务器错误)

这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。

http状态码 500 (服务器内部错误) 服务器遇到错误,无法完成请求。

http状态码 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。

http状态码 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。

http状态码 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。

http状态码 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。

http状态码 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。

总结

我们访问网站最常遇到的状态码,200代表请求成功,304是未修改(缓存),403服务器拒绝(文件夹权限问题),404请求失败,文件不存在(路径不存在),500是服务器错误,通常代表服务器没法处理此请求或者服务器挂掉了,503是请求无响应,通常是服务器资源没法分配处理,网站被攻击的会经常遇到503错误的。了解这些状态码代表的含义,可以帮助你快速的定位网站遇到的故障问题。