/* eslint-disable no-param-reassign */ /* eslint-disable @typescript-eslint/naming-convention */ import { SuperComponent } from '../super/component'; import { isPlainObject, toObject } from '../utils/object'; // 将 on 开头的生命周期函数转变成非 on 开头的 const RAW_LIFE_CYCLES = ['Created', 'Attached', 'Ready', 'Moved', 'Detached']; const NATIVE_LIFE_CYCLES = RAW_LIFE_CYCLES.map(k => k.toLowerCase()); const COMPONENT_NATIVE_PROPS = [ 'externalClasses', 'properties', 'data', 'options', 'relations', 'behaviors', ]; /** * 将一个普通的 options 对象转化处理为 Component 支持的对象 * 在这里需要对一些方法进行操作 * @param options {} */ export function toComponent(options: any = {}): any { // 处理 properties 属性 if (options.properties) { Object.keys(options.properties).forEach((k) => { // @ts-ignore let opt: any = options.properties[k]; // 如何不是 Object 类型,则默认指定 type = options.properties[k]; if (!isPlainObject(opt)) { opt = { type: opt }; } options.properties[k] = opt; }); } // 处理自定义的方法和生命周期函数 if (!options.methods) options.methods = {} as any; const inits: { [key: string]: PropertyDescriptor } = {}; Object.getOwnPropertyNames(options).forEach((k) => { const desc = Object.getOwnPropertyDescriptor(options, k); if (!desc) return; if (NATIVE_LIFE_CYCLES.indexOf(k) < 0 && typeof desc.value === 'function') { // 非生命周期函数挂载到 methods 对象上面 Object.defineProperty(options.methods, k, desc); delete options[k]; } else if (COMPONENT_NATIVE_PROPS.indexOf(k) < 0) { // 非函数,也非组件内部属性 // 由于小程序组件会忽略不能识别的字段,需要这里需要把这些字段配置在组件 created 的时候赋值 inits[k] = desc; } }); if (Object.keys(inits).length) { const oldCreated = options.created as any; options.created = function () { Object.defineProperties(this, inits); // eslint-disable-next-line prefer-rest-params if (oldCreated) oldCreated.apply(this, arguments); }; } return options; } /** * 将一个继承了 SuperComponent 的类转化成 小程序 Component 的调用 * 根据最新的微信 d.ts 描述文件,Component 在实例化的时候,会忽略不支持的自定义属性 */ export function wxComponent() { return function (constructor: new () => SuperComponent): void { class WxComponent extends constructor { // eslint-disable-next-line @typescript-eslint/no-unused-vars constructor(..._args: any[]) { super(); } created() { super.created && super.created(); } attached() { super.attached && super.attached(); } detached() { super.detached && super.detached(); } } const current = new WxComponent(); current.options = current.options || {}; if (current.options.addGlobalClass === undefined) { current.options.addGlobalClass = true; } if (current.options.multipleSlots === undefined) { current.options.multipleSlots = true; } const obj = toComponent(toObject(current)); Component(obj); }; }