js 实例化组件及更新

73 阅读1分钟
import { cloneVNode, createApp, createVNode,render as vueRender, type App, type VNode } from 'vue';
import UploadProgressVue from './UploadProgress.vue';

type Opt = {
  title: string;
  progress: number;
  onCancel?: () => void;
  onOk?: () => void;
};

export function triggerVNodeUpdate(vm: VNode, attrs: Record<string, any>, dom: any) {
  vueRender(cloneVNode(vm, { ...attrs }), dom);
}
export class UploadProgress {
  private _instance?: VNode;
  private _parentNode: HTMLDivElement;
  private _opt: Opt;
  private _attr: {[key: string]: any} = {}
  private _isMount: boolean = false;
  constructor(opt: Opt) {
   
    this._opt = opt;
    this._parentNode = document.createElement('div');
    this._attr = {
      title: this._opt.title,
      progress: this._opt.progress,
      onCancel: () => {
        this.unmount();
        if (this._opt.onCancel) {
          this._opt.onCancel();
        }
      },
      onOk: () => {
        this.unmount();
        if (this._opt.onOk) {
          this._opt.onOk();
        }
      }
    }
  }

  mount() {
    this._instance = createVNode(UploadProgressVue, {
      ...this._attr
    });
    document.body.appendChild(this._parentNode);
    // 挂载组件
    vueRender(this._instance, this._parentNode as any);
    this._isMount = true
    return this
  }

  setProgress(value: number) {
    if (!this._instance) return;
    if (!this._isMount) return;
    this._attr.progress = value
    triggerVNodeUpdate(this._instance, {...this._attr}, this._parentNode)
  }

  setStatus(value: 'success' | 'exception' | 'normal' | 'active') {
    if (!this._instance) return;
    if (!this._isMount) return;
    this._attr.status = value
    triggerVNodeUpdate(this._instance, {...this._attr}, this._parentNode)
  }

  unmount() {
    if (!this._instance) return this;
    vueRender(null, this._parentNode as any);
    this._isMount = false
    this._instance = undefined;
    return this;
  }
}