开始
需求很简单,因为一些原因我并不想在template中直接使用子组件,
于是我想是否可以通过方法直接把组件插入到dom中呢?当然是可以的了~~
但是我又想偷懒,于是我想到element plus也是在一些组件中也在dom插入了组件。
于是我就默默的准备copy它的代码了~
第一步,确定哪个组件会有该功能(我想到了message)
第二步,找到该组件
在element plus中找到该组件位置
组件位置:packages/components/message/src
我们看到message/index.ts是入口文件,message.vue应该就是组件的文件了
但是我们是动态插入该组件,那说明在dom中插入该组件的方法不在该文件中,所以先就不看它了。
然后我再打开methods.ts,首先看到了
import { createVNode, render } from 'vue' ... import MessageConstructor from './message.vue' ...
这俩函数我就不多说了,看名字也知道是和创建元素节点和渲染有关的函数了
我们看到也引入了message.vue
这个时候我隐约猜到了,应该就是在这里插入了该组件,于是我搜索了一下createVNode和render方法
于是我找到了
const container = document.createElement('div') const props = { ...options, // now the zIndex will be used inside the message.vue component instead of here. // zIndex: nextIndex() + options.zIndex id, onClose: () => { userOnClose?.() closeMessage(instance) }, // clean message element preventing mem leak onDestroy: () => { // since the element is destroy, then the VNode should be collected by GC as well // we do not want cause any mem leak because we have returned vm as a reference to users // so that we manually set it to false. render(null, container) }, } const vnode = createVNode( MessageConstructor, props, isFunction(props.message) || isVNode(props.message) ? { default: isFunction(props.message) ? props.message : () => props.message, } : null ) vnode.appContext = context || message._context render(vnode, container) // instances will remove this item when close function gets called. So we do not need to worry about it. appendTo.appendChild(container.firstElementChild!)
该代码创建了一个div,然后把MessageConstructor组件插入了这个div中,props是传递了参数
那么问题又来了,我不用的时候如何销毁它呢?
这个时候我们看到了props中有一个代码
... onDestroy: () => { // since the element is destroy, then the VNode should be collected by GC as well // we do not want cause any mem leak because we have returned vm as a reference to users // so that we manually set it to false. render(null, container) } ...
我觉得它就是销毁组件的了~(实际上肯定是得了)
这个时候就不多说了,大概的思路就是这样得了~~
如果要销毁组件,在子组件执行onDestroy或者父组件执行 render(null, container)即可
欢迎前端交流
QQ群:362909884 微信:sdsn10000