Read this article 📖
You will be:
- Know two
ElementUI
Components that are not documented in official documentation but have actually been built in. - Learn to use them and acquire them
demo
A. - To understand
ElementUI
The basic principle of the pop-up layer component is to face laterappendToBody
And related problems into bamboo in the chest.
“ElementUI you Don’t Know” series
This series will delve into ElementUI and provide you with “divine knowledge” that only experienced ElementUI users and even code contributors know. They are very useful both in daily work and in job interviews. Plus: This series is also suitable for Element Plus users, since the core philosophy of Element hasn’t changed much.
A,ElementUI
Two modes for all pop-up layers in
The pop-up layer of ElementUI (including but not limited to: Dialog, SELECT, popover, date-picker, etc.) has two implementations of element positioning:
- Solution a:
append-to-body
Type. In this mode, the pop-up layer is placed<body>
On the element, passposition:fixed
Positioning, fit dynamictop
å’Œleft
Property to complete the positioning of the pop-up element. - Plan 2: No
append-to-body
Type. In this mode, the pop-up layer passesposition:absolute
Position, matching the parent elementposition:relative
To complete the positioning of the pop-up element.
In most cases, ElementUI is “Scheme one: Append-to-body” by default. The reason is simply that option 2: Non-Append-to-body has serious side effects and should only be used as a last resort.
For example, when the parent element of the pop-up layer component has position: relative; Overflow: Auto; whether the component is append-to-body may directly affect the display of the component:
Example code: github.com/zhangshichu…
Why does “non-append-to-body” cause this problem, but “append-to-body” does not? This is a BASIC CSS question, feel free to post your understanding in the comments.
In addition to the above scenarios, “non-append-to-body mode” can cause similar problems in a variety of scenarios.
This is the root reason why ElementUI sets all pop-up layers to append-to-body mode.
Second,ElementUI
How is the pop-up layer managedz-index
?
As discussed in the first section, ElementUI automatically uses the append-to-body mode to implement the pop-up layer unless specifically specified. With that in mind, pretend you’re an ElementUI developer and how do you achieve the following:
- How to ensure
dialog
In the component,select
Component pop-up layer is higher thandialog
The pop-up layer? - How to ensure
dialog-1
Pop up again ondialog-2
Is higher thandialog-1
The hierarchy of?
The folks at ElementUI came up with a simple but amazing solution when designing this area: as long as the new pop-up layers are always higher than all the previous ones, no “new” shells can be obscured by “old” ones.
Imagine a scenario where clicking a button on “popup-1” brings up “popup-2” and there is a “dropdown component” on “popup-2”. What would their Z-index look like?
As shown in the figure above, you can guarantee that no pop-up layer will be blocked for no reason, as long as you ensure that each pop-up layer is +1 from the current maximum Z-index.
Remember this mechanism, which is the core implementation mechanism for the ElementUI pop-up layer.
So, who manages the z-index for the whole project?
Of course it is — Popup butler
Iii. Understanding: PopupManager
As Batman battles various villains in Gotham City, his old steward Alfred always helps him keep things in order.
Behind all the pop-up layers in ElementUI, there is a hard-working manager called PopupManager.
PopupManager: Provides the pop-up layer with the ability to get instances, register, unregister, and so on, but the most important capability is to provide the z-index hierarchy management capability.
How to use it?
<template>
<div>
<el-button @click="onClick">increase</el-button>
z-index: {{ value }} </div>
</template>
<script>
import { PopupManager } from 'element-ui/src/utils/popup'
export default {
data() {
return {
value: 0}},methods: {
onClick() {
// Yes, it's that simple to use, just one line
this.value = PopupManager.nextZIndex()
}
}
}
</script>
Copy the code
The effect is as follows:
Notice that popupManager.nextzIndex () returns 2000 the first time and then +1 every time you click.
The subsequent +1 makes sense, as each pop-up layer gets the latest available Z-index by 1 more than the previous layer.
But why 2000 in the first place?
This is actually a “pop-up layer Z-index cardinality” built into ElementUI, but it can be modified.
When you install ElementUI, you can change the built-in 2000 to 3000 with the following code.
// This increases the pop-up layer's z-index from 3000
Vue.use(Element, { zIndex: 3000 });
Copy the code
Understanding the role of the old manager goes beyond just understanding ElementUI’s Z-index management mechanism, which can be very useful in real production and projects.
Example code: github.com/zhangshichu…
Four, actual combat: a more flexible full-screen component
The official full screen API is good, but the product manager says the official doesn’t understand the business.
It is well known that has an official full-screen browser is API: Element. RequestFullscreen (), it allows an Element to immediately covered with Windows, and above all elements.
Although it’s a beautiful API, the product manager always has some weird requests: “This page supports full screen, and then it has some popovers, which contain some complicated forms…..”
I was numb when I heard this:
“The official full screen is set level above everything else, those append-to-body popovers, no matter how high the Z-index is, will never show up.”
“Pop-up layers that are not append-to-body do fall short in some business scenarios.) “
On second thought, a “full-screen component that meets ElementUI level standards” is also wrapped.
The idea is simple:
The full screen implementation of the browser API is basically the same idea, but the difference is:
- The official full screen will default to the top and z-index will be infinite
- Self – encapsulated full screen, Z-index compliant
PopupManager
Housekeeping rules.
So I wrote a rough 20-line demo:
<template>
<div :class="{ 'my-full-screen': isFullScreen }" :style="{zIndex: currentZIndex}">
<slot></slot>
</div>
</template>
<script>
import { PopupManager } from 'element-ui/src/utils/popup'
export default {
data() {
return {
isFullScreen: false.currentZIndex: null}},methods: {
request() {
this.isFullScreen = true
this.currentZIndex = PopupManager.nextZIndex()
}
}
}
</script>
<style>
.my-full-screen {
position: fixed ! important;
top: 0 ! important;
left: 0 ! important;
right: 0 ! important;
bottom: 0 ! important;
width: 100% ! important;
height: 100% ! important;
}
</style>
Copy the code
The effect is compared to the official browser API:
Although the effect is certainly not as good as the official direct full screen, self-encapsulation must be combined with manual F11, but it completely confirms a problem:
PopupManager can be used in production to solve practical problems.
Example code: github.com/zhangshichu…
V. Understanding: Vue-Popper
As good as Alfred the Butler is, Batman can’t ride Alfred into battle. Hence the Batmobile.
Vue-popper’s is the Batmobile. It’s no exaggeration. Most of the pop-up layers in ElementUI that we’ve been able to touch are implemented based on vue-Popper components.
Just to name a few: Select, date-Picker, cascading Cascader, Dropdown, popover, Tooltip… Wait, these components are all based on vue-popper components to implement the pop-up layer.
So how does vue-Popper work?
In general, its main use is mixins. Use it in three steps:
The most typical example, which I won’t list in too much code, is the ElementUI dropdown-menu. See the code: github.com/ElemeFE/ele…
The mixin example is too complicated. Is there a way to use it as a component without mixin?
B: of course!
Five, actual combat: fully custom pop-up layer
How to write a simple “custom pop-up layer” demo using Vue-Popper.
Follow the following three steps:
- First we introduce
vue-popper
Reference the component in the template and define a pop-up layer element, a positioning element.
<template>
<! -- Positioning elements -->
<div class="my-picker">
<! -- Vue-popper component -->
<Popper ref="popper" v-model="showPopper">
</Popper>
<! -- Popup component -->
<div ref="fly-piece" v-show="showPopper" class="my-picker__popper">Look, I popped it out</div>
</div>
</template>
<script>
// Introduce vuE-popper components
import Popper from 'element-ui/src/utils/vue-popper';
export default {
components: {
Popper
},
data() {
return {
// Bidirectional binding to control whether the pop-up layer is pop-up
showPopper: false}},}</script>
Copy the code
- to
vue-popper
specifiesPop-up layerandPositioning layer.
mounted() {
this.$refs.popper.popperElm = this.$refs['fly-piece'];
this.$refs.popper.referenceElm = this.$el;
}
Copy the code
- By controlling the
vue-popper
çš„props.value
To control whether or not to pop.
this.showPopper = !this.showPopper
Copy the code
Can achieve the following effect:
Isn’t that easy?
Is it useful when you want to implement custom complex components?
Example code: github.com/zhangshichu…
conclusion
Ok, let’s remember what we talked about in this article:
ElementUI
Two modes of pop-up layer, and how they are implemented.ElementUI
How to manage the pop-up layerz-index
.PopupManager
The usage and actual combat.vue-popper
The usage and actual combat.