preface

It is not recommended to read the whole article. It is recommended to download the element-UI source code and run it locally. Read the source code in your own way.

This is not to share, but their own reading understanding of the source of the record, do not tangle the disorderly (or vegetables, write bad);

The article is divided into two parts:

  • The basic principles of component implementation are described in detail
  • Specific analysis process: most of the functions, life cycle functions, tool functions/classes in the component, as records; (It is not recommended to read the whole article. It is recommended to read the source code when encountering points that you do not understand. You can refer to them.)

The basic principles of component implementation are introduced

  • Main. vue determines the dom structure of the component, sets the calculation function with the class name, closes the event, the timer, removes the DOM node operation;

  • where Message instances are mounted and added to; where Message instances are added or removed; Maintain style issues for each instance (adjust up and down), and expose two operational instances and an API for instance creation;

$mount() : Vue. Extend vm.$mount() : Vue.


Specific analysis process (boring)

Please do not care about the following format and structure, not suitable for reading, look at the source is a bit divergent thinking, the basic logic is to see which function is analyzed that function, along the context of the function order and the execution of the order to go again

The Message component has a relatively small amount of code, and the order of analysis is roughly as follows: look at the code line by line from top to bottom to understand

MessageConstructor

let MessageConstructor = Vue.extend(Main);
// Documentation: Using the base Vue constructor, create a "subclass". The parameter is an object that contains component options.
Copy the code

Two tools introduced by main.js

import { PopupManager } from 'element-ui/src/utils/popup';
import { isVNode } from 'element-ui/src/utils/vdom';
Copy the code

VNode.js

// VNode.js 
import { hasOwn } from 'element-ui/src/utils/util';
export function isVNode(node) returnnode ! = =null && typeof node === 'object' && hasOwn(node, 'componentOptions');
};
// hasOwn is used to determine whether an attribute is the object itself, as opposed to attributes inherited from the prototype chain. The name of the function is also well understood.
Copy the code

IsVnode’s function is the name of an isVnode, which determines whether something is a VNode. The component’s argument message can be of two types: string/VNode

Generally, the function to do the judgment function is relatively simple. There are not too many associated items for the judgment operation, usually one or two associated items. The function to calculate the operation usually involves more than two items, which are abstracted into classes. The name of good semantically coded code gives you an idea of the tool’s capabilities and complexity

PopupManager

Go back to PopupManager and start with the name, “PopupManager”. Other popovers probably use this tool class too, although popupmanager.nextzindex () is only applicable here. Look at their use of the popup class;

Take a look at how popUp is used by other components:

  • 1 Look firstNotificationNotifications, like message, are, of course, just usedPopupManager.nextZIndex(), the similarity between the two is too high, the other parts are almost the same, there is no need to read the Notification after reading the Message;
  • 2 look atMessageBoxThe VNode method is used. The parameter “Message” is optionalstring / VNode, uses the entire Popup class tomixinsIn the form of;

Two common uses are popupManager.nextzIndex () alone or the introduction of popUp as mixinx as a whole;

Main.js only uses a function of popupManager.nextzIndex () that returns zIndex. The PopupManager is explained in el-dailog

// element\src\utils\popup\popup-manager.js
constPopupManager = {...nextZIndex: function() returnPopupManager.zIndex++; ...}},// Add attributes to the object
Object.defineProperty(PopupManager, 'zIndex', {  
    configurable: true.get() {  
        if(! hasInitZIndex) { zIndex = zIndex || (Vue.prototype.$ELEMENT || {}).zIndex ||2000;      
            hasInitZIndex = true;    
        }
        return zIndex;  
    }, 
    set(value) {    zIndex = value;  }});
/ / the Vue. Prototype. $ELEMENT in ELEMENT \ SRC \ index js
Copy the code

The generic code for the popup component is suddenly deep. Regardless of popup, popup can be understood in conjunction with a component (el-Dialog) that uses popup.

Generation of the Message instance

const Message = fucntion(options){... the instance =new MessageConstructor({  data: options});
// Create a message instance,
instances.push(instance);
// Create an array instances of message instances
}
Copy the code
Message['success']; // Message['success'];
$message.error(' XXX ')
// Message[type] is undefined when initialized, so this.$message.error() is defined
['success'.'warning'.'info'.'error'].forEach(type= > {
    Message[type] = options= >if (typeof options === 'string') { 
            options = { message: options }; 
        } 
        options.type = type; 
        return Message(options);  
    };
});
Copy the code

The following two lines of code are easy to wrap around, with similar names;

// main.vue 
methods: {
    close() {
        this.closed = true// Trigger watch closed to hide the message;
        if (typeof this.onClose === 'function') {  
            this.onClose(this); }}},Copy the code
 function() { 
        Message.close(id, userOnClose);
    };
Copy the code
// main.js
let seed = 1;
const Message = function(options) {...let userOnClose = options.onClose;
    let id = 'message_' + seed++;
    options.onClose = function() { 
        Message.close(id, userOnClose);
    };
    instance = new MessageConstructor({  data: options}); ...}Copy the code
// main.js
Message.close = function(id, userOnClose) {... }// Close the instance based on its id
Copy the code

Closing the execution of a function in a process looks like this: Clicking the close button or the this.timer timer triggers close() on main.vue to execute this.onClose(this); Message.onclose (id, userOnClose), the parameter ID of the Message instance, userOnClose is the parameter passed on the call;

Message.close = function(id, userOnClose) {
    // loop instances to find instances that are closed
    UseOnClose (instance[I]) useOnClose(instance[I])
    // Adjust the position of all instances under the current instance;
}
Copy the code

Message.closeall () closes all instances at once, as the name implies, and can be called manually if necessary;

About the delay function clearTimer/starTimer: the component listens for two events of mouse move and remove, which is convenient for mouse hover to see the message;

@mouseenter="clearTimer"
@mouseleave="startTimer"
Copy the code

The component listens for keyboard events and handles the incoming Esc key;

mounted()this.startTimer(); 
    document.addEventListener('keydown'.this.keydown);
},
beforeDestroy()document.removeEventListener('keydown'.this.keydown);
}
// Register event listener function when component load, remove listener when component unload,

keydown(e)if (e.keyCode === 27) {
        if (!this.closed) { 
            this.close(); }}}// Press ESC to close all messages
// All instances whose this.closed value is false will execute this.close;
Copy the code

Instance logout and DOM removal occur at the end of the animation:

<transition name="el-message-fade" @after-leave="handleAfterLeave">

handleAfterLeave()this.$destroy(true);   
    this.$el.parentNode.removeChild(this.$el);
},
Copy the code

Animation components built into Vue; This is the basic Message implementation of the component;

Message prompts are imperative components that are often used to provide feedback after active action. Element adds the global method $message to vue. prototype.

It can also be used alone

import { Message } from 'element-ui';
Copy the code

Documentation: Call method Message(options). We also define separate methods for each type, such as message.Success (options). And all instances can be closed manually by calling message.closeall ().


To Be Contuine

Have wrong place, kneel beg big guy to show one or two

The last one was:el-form el-form-item

Next up is the popover manager tool classPopup

Read more:

Vue.extend

vm.$mount()

Keyboard button keyCode