vue2.x挂载$mount函数的作用(有elementUI message联想)
程序员文章站
2024-03-05 11:23:12
...
文章参考
问题描述
- 在使用elementUI的时候,发现了
this.$message('这是一条消息提示');
这个函数,觉得使用非常方法,不需要引用组件,直接调用方法 - 自己琢磨了一下,如果针对提示或者一些简单的UI界面,如果使用方法调用,大大提高使用效率,于是查看了源代码
- 是使用了 Vue函数式编程(类似于React的函数式组件写法),本质还是使用了vue文件(定义好了template界面和methods逻辑),然后继承该组件,通过方法实例化
vm.$mount 官方文档介绍
参数:
{Element | string} [elementOrSelector]
{boolean} [hydrating]
返回值:vm - 实例自身
用法:
- 如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。可以使用 vm.$mount() 手动地挂载一个**
未挂载的实例
**。 -
如果没有提供 elementOrSelector 参数,模板将被渲染为文档之外的的元素,并且你必须使用原生 DOM API 把它插入文档中
。 - 这个方法返回实例自身,因而可以链式调用其它实例方法。
不执行 $mount()方法,则Vue对象中的 $el 属性是没有的
示例:
var MyComponent = Vue.extend({
template: '<div>Hello!</div>'
})
// 创建并挂载到 #app (会替换 #app)
new MyComponent().$mount('#app')
// 同上
new MyComponent({ el: '#app' })
// 或者,在文档之外渲染并且随后挂载
var component = new MyComponent().$mount()
document.getElementById('app').appendChild(component.$el)
elementUI 提供方法的源代码
import Vue from 'vue';
import { PopupManager } from 'hui/src/utils/popup';
import { isVNode } from 'hui/src/utils/vdom';
import MessageMain from './main.vue'; // 定义好 message 的组件界面和逻辑
// let MessageConstructor = Vue.extend(require('./main.vue'));
// 创建一个组件继承 message组件的配置
const MessageConstructor = Vue.extend(MessageMain);
let instance;
const instances = [];
let seed = 1;
var Message = function( ) {
if (Vue.prototype.$isServer) return;
options = options || {};
if (typeof options === 'string') {
options = {
message: options
};
}
const userOnClose = options.onClose;
const id = 'message_' + seed++;
options.onClose = function() {
Message.close(id, userOnClose);
};
// 根据配置创建一个 message Vue对象 实例
instance = new MessageConstructor({
data: options
});
let verticalOffset = 0;
instances.forEach(item => {
verticalOffset += item.$el.offsetHeight + 16;
});
// 首个的位置为top:20px
verticalOffset += 20;
instance.verticalOffset = verticalOffset;
instance.id = id;
if (isVNode(instance.message)) {
instance.$slots.default = [instance.message];
instance.message = null;
}
// vm.$mount() 手动地挂载一个未挂载的实例,返回自身实例
instance.vm = instance.$mount();
// 将组件的界面最后添加到 body 标签中
document.body.appendChild(instance.vm.$el);
instance.vm.visible = true;
instance.dom = instance.vm.$el;
instance.dom.style.zIndex = PopupManager.nextZIndex();
instances.push(instance);
return instance.vm;
};
// 优化API接口 ,提供 this.$message.error('错了哦,这是一条错误消息'); 使用方式
['success', 'warning', 'info', 'error'].forEach(type => {
Message[type] = options => {
if (typeof options === 'string') {
options = {
message: options
};
}
options.type = type;
return Message(options);
};
});
Message.close = function(id, userOnClose) {
const len = instances.length;
for (let i = 0; i < len; i++) {
if (id === instances[i].id) {
if (typeof userOnClose === 'function') {
userOnClose(instances[i]);
}
const removedHeight = instances[i].dom.offsetHeight;
instances.splice(i, 1);
if (len <= 1) return;
for (let j = i; j < len - 1; j++) {
instances[j].dom.style.top =
parseInt(instances[j].dom.style.top, 10) - removedHeight - 16 + 'px';
}
break;
}
}
};
Message.closeAll = function() {
for (let i = instances.length - 1; i >= 0; i--) {
instances[i].close();
}
};
export default Message;
在elementUI中的说明
- instance.$mount(); 手动地挂载一个未挂载的实例,生成了HTML代码,但是没有挂载到body标签中
- document.body.appendChild(instance.vm.$el); 将生成的HTML代码挂载到Body中,形成了我们看到的界面