# 二.Loading
- 组件介绍 Layout 布局 组件目录
# element-ui
├── packages # 放置element的组件(css样式放置在这个目录下theme-chalk下)
│ ├── alert
│ │ ├── src # alert组件
│ │ │ └── main.vue # 组件注册的入口文件
│ │ └── index.js # 组件注册的入口文件
1
2
3
4
5
6
2
3
4
5
6
# index.js
import directive from "./src/directive"
import service from "./src/index"
export default {
install(Vue) {
Vue.use(directive)
Vue.prototype.$loading = service
},
directive,
service,
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
在 vue 项目中通过引用这个组件,然后通过 vue.use 加载这个组件,内部会调用 install 方法,将组件加载到 Vue 实例内部
# index.js
import Vue from "vue"
import loadingVue from "./loading.vue"
import { addClass, removeClass, getStyle } from "element-ui/src/utils/dom"
import { PopupManager } from "element-ui/src/utils/popup"
import afterLeave from "element-ui/src/utils/after-leave"
import merge from "element-ui/src/utils/merge"
const LoadingConstructor = Vue.extend(loadingVue)
const defaults = {
text: null,
fullscreen: true,
body: false,
lock: false,
customClass: "",
}
let fullscreenLoading
LoadingConstructor.prototype.originalPosition = ""
LoadingConstructor.prototype.originalOverflow = ""
LoadingConstructor.prototype.close = function() {
if (this.fullscreen) {
fullscreenLoading = undefined
}
afterLeave(
this,
(_) => {
const target = this.fullscreen || this.body ? document.body : this.target
removeClass(target, "el-loading-parent--relative")
removeClass(target, "el-loading-parent--hidden")
if (this.$el && this.$el.parentNode) {
this.$el.parentNode.removeChild(this.$el)
}
this.$destroy()
},
300
)
this.visible = false
}
const addStyle = (options, parent, instance) => {
let maskStyle = {}
if (options.fullscreen) {
instance.originalPosition = getStyle(document.body, "position")
instance.originalOverflow = getStyle(document.body, "overflow")
maskStyle.zIndex = PopupManager.nextZIndex()
} else if (options.body) {
instance.originalPosition = getStyle(document.body, "position")
;["top", "left"].forEach((property) => {
let scroll = property === "top" ? "scrollTop" : "scrollLeft"
maskStyle[property] =
options.target.getBoundingClientRect()[property] +
document.body[scroll] +
document.documentElement[scroll] +
"px"
})
;["height", "width"].forEach((property) => {
maskStyle[property] =
options.target.getBoundingClientRect()[property] + "px"
})
} else {
instance.originalPosition = getStyle(parent, "position")
}
Object.keys(maskStyle).forEach((property) => {
instance.$el.style[property] = maskStyle[property]
})
}
const Loading = (options = {}) => {
if (Vue.prototype.$isServer) return
options = merge({}, defaults, options)
if (typeof options.target === "string") {
options.target = document.querySelector(options.target)
}
options.target = options.target || document.body
if (options.target !== document.body) {
options.fullscreen = false
} else {
options.body = true
}
if (options.fullscreen && fullscreenLoading) {
return fullscreenLoading
}
let parent = options.body ? document.body : options.target
let instance = new LoadingConstructor({
el: document.createElement("div"),
data: options,
})
addStyle(options, parent, instance)
if (
instance.originalPosition !== "absolute" &&
instance.originalPosition !== "fixed"
) {
addClass(parent, "el-loading-parent--relative")
}
if (options.fullscreen && options.lock) {
addClass(parent, "el-loading-parent--hidden")
}
parent.appendChild(instance.$el)
Vue.nextTick(() => {
instance.visible = true
})
if (options.fullscreen) {
fullscreenLoading = instance
}
return instance
}
export default Loading
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113