目的:为了可以在方法中无需引用组件即可在页面生成dom结构
新建一个base文件夹,放置
1.baseComponent.js
2.index.js
baseComponent.js
import Vue from 'vue';
// 定义base组件
function BaseComponent () {
}
/**
* 生成一个Vue 实例
* @param Component
* @param properties
* @param dom
* @param args
* @returns {{[p: number]: *, some(callbackfn: (value: *, index: number, array: *[]) => unknown, thisArg?: any): boolean, keys(): IterableIterator, values(): IterableIterator<*>, shift(): (* | undefined), pop(): (* | undefined), slice(start?: number, end?: number): *[], find: {(predicate: (this:void, value: *, index: number, obj: *[]) => value is S, thisArg?: any): (S | undefined), (predicate: (value: *, index: number, obj: *[]) => unknown, thisArg?: any): (* | undefined)}, flat: {(this:U[][][][][][][][], depth: 7): U[], (this:U[][][][][][][], depth: 6): U[], (this:U[][][][][][], depth: 5): U[], (this:U[][][][][], depth: 4): U[], (this:U[][][][], depth: 3): U[], (this:U[][][], depth: 2): U[], (this:U[][], depth?: 1): U[], (this:U[], depth: 0): U[], (depth?: number): any[], (this:A, depth?: D): FlatArray[]}, join(separator?: string): string, reduceRight: {(callbackfn: (previousValue: *, currentValue: *, currentIndex: number, array: *[]) => *): *, (callbackfn: (previousValue: *, currentValue: *, currentIndex: number, array: *[]) => *, initialValue: *): *, (callbackfn: (previousValue: U, currentValue: *, currentIndex: number, array: *[]) => U, initialValue: U): U}, copyWithin(target: number, start: number, end?: number): this, indexOf(searchElement: *, fromIndex?: number): number, every(callbackfn: (value: *, index: number, array: *[]) => unknown, thisArg?: any): boolean, map(callbackfn: (value: *, index: number, array: *[]) => U, thisArg?: any): U[], reduce: {(callbackfn: (previousValue: *, currentValue: *, currentIndex: number, array: *[]) => *): *, (callbackfn: (previousValue: *, currentValue: *, currentIndex: number, array: *[]) => *, initialValue: *): *, (callbackfn: (previousValue: U, currentValue: *, currentIndex: number, array: *[]) => U, initialValue: U): U}, [Symbol.iterator](): IterableIterator<*>, splice: {(start: number, deleteCount?: number): *[], (start: number, deleteCount: number, ...items: *[]): *[]}, forEach(callbackfn: (value: *, index: number, array: *[]) => void, thisArg?: any): void, length: number, destroy(*=): void, includes(searchElement: *, fromIndex?: number): boolean, concat: {(...items: ConcatArray<*>): *[], (...items: ConcatArray<*> | *[]): *[]}, sort(compareFn?: (a: *, b: *) => number): this, fill(value: *, start?: number, end?: number): this, reverse(): *[], push(...items: *[]): number, [Symbol.unscopables](): {copyWithin: boolean, entries: boolean, fill: boolean, find: boolean, findIndex: boolean, keys: boolean, values: boolean}, props: ({option}|*), findIndex(predicate: (value: *, index: number, obj: *[]) => unknown, thisArg?: any): number, flatMap: {(callback: (this:This, value: *, index: number, array: *[]) => (ReadonlyArray | U), thisArg?: This): U[], (callback: (this:This, value: *, index: number, array: *[]) => (ReadonlyArray | U), thisArg?: This): U[]}, filter: {(callbackfn: (value: *, index: number, array: *[]) => value is S, thisArg?: any): S[], (callbackfn: (value: *, index: number, array: *[]) => unknown, thisArg?: any): *[]}, lastIndexOf(searchElement: *, fromIndex?: number): number, entries(): IterableIterator<[number, *]>, component, name: string, toString(): string, unshift(...items: *[]): number, toLocaleString(): string}|VNode}
*/
BaseComponent.prototype.newInstance = (Component, properties, dom, ...args) => {
const props = properties || {};
delete props.option.template;
const Instance = new Vue({
render (h) {
return h(Component, {
props: props
});
}
});
const component = Instance.$mount();
if (dom) {
dom.appendChild(component.$el);
} else {
document.body.appendChild(component.$el);
}
let name = null;
if (properties.option) {
name = properties.option.name || 'undefined';
}
// 动态生成的组件
const notification = Instance.$children[0];
return {
...args,
name: name || 'undefined',
component: notification,
props: properties,
destroy (callback) {
setTimeout(() => {
// 清除dom元素
dom ? dom.removeChild(component.$el) : document.body.removeChild(component.$el);
// 销毁实例
notification.$destroy();
if (callback && callback instanceof Function) {
callback(notification);
}
}, 300)
}
};
};
export default BaseComponent;
2.index.js
import BaseComponent from './baseComponent'
// 创建store来存储组件
let store = [];
let noticeInstance;
let createInstance = function (option) {
// 创建实例对象
let instance = new BaseComponent().newInstance(option.template, {
option: option,
destroy: function () {
if (noticeInstance !== null) {
// 数组中删除component
store = store.filter(function (item) {
return item.name !== noticeInstance.name;
})
// 删除实例对象
noticeInstance.destroy(() => {
noticeInstance = null;
});
}
}
}, option.dom);
if (option.name) {
let flag = true;
for (let i = 0; i < store.length; i++) {
if (store[i].name === option.name) {
flag = false;
break;
}
}
if (flag) {
store.push({
name: option.name,
component: instance
});
}
}
return instance;
};
/**
* 动态新建一个组件
* @param option
* @returns {*}
*/
function loadComponentInstance (option) {
// 组件存在
if (noticeInstance) {
if (noticeInstance.name !== 'undefined') {
if (option.name !== noticeInstance.name) {
let flag = false;
// 在数组中寻找组件是否存在
store.forEach((item) => {
if (item.name === option.name) {
flag = true;
noticeInstance = item.component;
return noticeInstance;
}
})
// 不存在
if (!flag) {
noticeInstance = createInstance(option);
}
}
} else {
noticeInstance.component.destroy();
noticeInstance = createInstance(option);
}
} else {
// 组件不存在
noticeInstance = createInstance(option);
}
return noticeInstance;
}
/**
* 销毁组件
* @param option
* @returns {*}
*/
function destroyInstance (name) {
if (name === null) {
console.error('destroyInstance function needs name...');
}
store.forEach((item) => {
if (item.name === name) {
let instance = item.component;
instance.destroy();
}
})
}
export default {
loadComponentInstance,
destroyInstance
};
使用
在main.js 文件引入组件
import loadView from '_c/base/index'
Vue.prototype.$loadView = loadView;
在***.vue文件中使用
switchDomain () {
const obj = this.$loadView.loadComponentInstance({
name: 'switch-domain-modal',
template: switchDomainModal
})
//拿到组件实例
let modal = obj.component;
//组件方法 我这是modal框 执行打开
modal.open();
}