Javascript MVC ——Controller

142 阅读2分钟

该思路 是通过MVC 数据层 控制层这种方式,来实现数据量比较大的页面交互效果

image.png

目录结构

image.png

1. 数据层 model.ts

/**
 *  数据层
 */
import { DataSourceType, IModelType } from './interface';
import Event from './event';

export default class Model implements IModelType {
  // 页面需要变量数据
  private dataSource: DataSourceType | null = null;
  private static model: IModelType | null = null;

  constructor(payload: DataSourceType) {
    this.dataSource = payload
  }

  public static getInstance(payload: DataSourceType) {
    if (!this.model) {
      this.model = new Model(payload);
    }
    return this.model;
  }

  public setValue(key: string, val: any) {
    (this as any).dataSource[key] = val
    this.update((this as any).dataSource)
  }

  public getValue(key: string) {
    const current = (this as any).dataSource[key];
    if (current) {
      return current;
    }
    return null;
  }

  public getValues(): any {
    return this.dataSource
  }

  public update(payload: DataSourceType) {
    this.dataSource = payload
    Event.dispatchEvent('change', payload)
  }
}

2. 数据变更触发监听器,发布订阅 event.ts

/**
 * 数据变更触发监听器,发布订阅
 */
import { IHandleType } from './interface';

export default class Event {
  public static handlers: IHandleType = {}

  public static addEventListener (type: any, handler: any) {
    if (!(type in this.handlers)) {
      this.handlers[type] = []
    }
    this.handlers[type].push(handler)
  }

  public static dispatchEvent (type: any, ...params: any) {
    if (!(type in this.handlers)) {
      return new Error('未注册该事件')
    }
    this.handlers[type].forEach((handler: any) => {
      handler(...params)
    })
  }

  public static removeEventListener (type: any, handler: any) {
    if (!(type in this.handlers)) {
      return new Error('无效事件')
    }
    if (!handler) {
      delete this.handlers[type]
    } else {
      const idx = this.handlers[type].findIndex((ele: any) => ele === handler)
      if (idx === undefined) {
        return new Error('无该绑定事件')
      }
      this.handlers[type].splice(idx, 1)
      if (this.handlers[type].length === 0) {
        delete this.handlers[type]
      }
    }
  }
}

3. 数据 ui 交互中间层 controller.ts

/**
 *  数据 ui 交互中间层
 */
import { IModelType, IControllerType, DataSourceType } from './interface';
import Model from './model';

export default class Controller implements IControllerType {
  private readonly dataSource: DataSourceType | null = null;
  private model: IModelType | null = null;
  private static controller: IControllerType | null = null;
  
  constructor(payload: DataSourceType) {
    this.dataSource = payload
  }

  public static getInstance(payload: DataSourceType | null) {
    if (!this.controller) {
      this.controller = new Controller(payload as any);
    }
    return this.controller;
  }

  public init() {
    this.model = Model.getInstance((this as any).dataSource);
  }
  
  public getValue(key: string) {
    return (this as any).model.getValue(key);
  }

  public setValue(key: string, val: any) {
    (this as any).model.setValue(key, val);
  }

  public getValues() {
    return (this as any).model.getValues();
  }

  public update(payload: DataSourceType) {
    (this as any).model.update(payload);
  }
}

4. 定义接口 interface.ts


export type StateInfoType = {
   current_state?: string;
   errors: any[];
   partner_edited?: boolean;
}

export interface SubmissionItemType {
   client_id?: string;
   id?: number | string;
   default_locale_code?: string;
   locale_code: string;
   state_info: StateInfoType;
}

export interface Type {
   getValue: (k: any) => string;
   setValue: (k: string, v: string | boolean) => void;
   getValues: () => DataSourceType;
   update: (payload: DataSourceType) => void;
  }
  
  export interface IControllerType extends Type {
   init: () => void
  }
  
  export interface IModelType extends Type {}
  
  export interface IHandleType {
   [k: string]: any
  }

  export interface DataSourceType {
   [key: string]: any
  }

  export interface DesignDataType {

  }

  export interface DesignContextProps {
     data: DesignDataType;
     cloneData: DesignDataType;
     handleSetValue: any;
     handleUpdateValue?: any;
     handleCloneDefaultData?: any;
  }

  export interface RuleDataType {
    [x: string]: any;
    rule_scope_list: any;
    spu_sku_info: {};
   shop_rule_id?: number | string | undefined;
   target_group: number | string
  }

  export interface RuleContextProps {
   data: RuleDataType;
   handleSetValue: any;
   handleUpdateValue?: any;
  }

5. 页面调用

image.png

image.png image.png

6. 通过provider 的方式传递给子组件

父组件 image.png

image.png

子组件

image.png

image.png