实现类似如上图的效果,主要是出于下面几种场景考虑:
- 遇到父元素用了position: fixed;或position: absolute;定位,导致子元素内部的定位left、top错位了
- 父元素overflow: hidden;会切割遮住子元素里面的部分DIV(如动态生成的tip弹窗提示框等情况)
- 子元素有全局的遮罩图层,如:弹窗背后的半透明图层,为了在全局遮住,不得已需要在body挂载
- 子元素部分div必须要在外层最高层级,否者会被body里面的子元素挡住
- 滚动网页的时候不想某些子元素被同步滚动(例如下拉框)
实现代码很简单
// 将自定义组件挂载到对应元素上面 mount({ component, classObj,// 与 `v-bind:class` 的 API 相同,接受一个字符串、对象或字符串和对象组成的数组 style,// 与 `v-bind:style` 的 API 相同,接受一个字符串、对象,或对象组成的数组 attrs,// 普通的 HTML attribute props,// 组件 prop domProps,// DOM 属性 on,// 事件监听器在 `on` 属性内,但不再支持如 `v-on:keyup.enter` 这样的修饰器。需要在处理函数中手动检查 keyCode。 nativeOn,// 仅用于组件,用于监听原生事件,而不是组件内部使用,`vm.$emit` 触发的事件。 directives,// 自定义指令。注意,你无法对 `binding` 中的 `oldValue` 赋值,因为 Vue 已经自动为你进行了同步。 scopedSlots,// 作用域插槽的格式为{ name: props => VNode | Array<VNode> } slot,// 如果组件是其它组件的子组件,需为插槽指定名称 key,// 其它特殊顶层属性 ref,// 如果你在渲染函数中给多个元素都应用了相同的 ref 名 那么 `$refs.ref` 会变成一个数组。 refInFor,// 与v-for 同时使用在此处添加refInFor生成一个ref数组 mountElement, }) { const vm = new Vue({ render: h => h(component, { 'class': classObj, style, attrs, props, domProps, on, nativeOn, directives, scopedSlots, slot, key, ref, refInFor, }) }).$mount();//on是绑定事件对象 let dom = mountElement || document.body;//默认挂载到body上面 dom.appendChild(vm.$el); vm.$children[0].remove = () => dom.removeChild(vm.$el), vm.$destory && vm.$destory(); return vm; },
应用
mount({ component: 自定义引入的组件, props: { //...以下是组件初始化需要传入的属性 id: `contextMenuBodyBlank-${this.type}`, target: this.contextMenuTargetList, data: this.contextMenuBodyList, } })