roymondchen de47514f69 feat: 完善迭代器嵌套使用问题,重构事件配置处理代码
* feat(editor,core,data-source,dep,schema,ui,utils,vue-runtime-help): 完善迭代器

* test: 完善测试用例

* chore: 构建

* feat: 迭代器嵌套事件传递数据

---------

Co-authored-by: roymondchen <roymondchen@tencent.com>
2024-12-09 20:21:34 +08:00

154 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Tencent is pleased to support the open source community by making TMagicEditor available.
*
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import EventEmitter from 'events';
import { cloneDeep } from 'lodash-es';
import type { default as TMagicApp } from '@tmagic/core';
import type { CodeBlockContent, DataSchema, DataSourceSchema } from '@tmagic/schema';
import { getDefaultValueFromFields } from '@tmagic/utils';
import { ObservedData } from '@data-source/observed-data/ObservedData';
import { SimpleObservedData } from '@data-source/observed-data/SimpleObservedData';
import type { ChangeEvent, DataSourceOptions } from '@data-source/types';
/**
* 静态数据源
*/
export default class DataSource<T extends DataSourceSchema = DataSourceSchema> extends EventEmitter {
public isInit = false;
/** @tmagic/core 实例 */
public app: TMagicApp;
protected mockData?: Record<string | number, any>;
#type = 'base';
#id: string;
#schema: T;
#observedData: ObservedData;
/** 数据源自定义字段配置 */
#fields: DataSchema[] = [];
/** 数据源自定义方法配置 */
#methods: CodeBlockContent[] = [];
constructor(options: DataSourceOptions<T>) {
super();
this.#id = options.schema.id;
this.#schema = options.schema;
this.app = options.app;
this.setFields(options.schema.fields);
this.setMethods(options.schema.methods || []);
let data = options.initialData;
// eslint-disable-next-line @typescript-eslint/naming-convention
const ObservedDataClass = options.ObservedDataClass || SimpleObservedData;
if (this.app.platform === 'editor') {
// 编辑器中有mock使用mock没有使用默认值
this.mockData = options.schema.mocks?.find((mock) => mock.useInEditor)?.data || this.getDefaultData();
data = cloneDeep(this.mockData);
} else if (typeof options.useMock === 'boolean' && options.useMock) {
// 设置了使用mock就使用mock数据
this.mockData = options.schema.mocks?.find((mock) => mock.enable)?.data || this.getDefaultData();
data = this.mockData;
} else if (!options.initialData) {
data = this.getDefaultData();
} else {
// 在ssr模式下会将server端获取的数据设置到initialData
this.#observedData = new ObservedDataClass(options.initialData ?? {});
// 设置isInit,防止manager中执行init方法
this.isInit = true;
return;
}
this.#observedData = new ObservedDataClass(data ?? {});
}
public get id() {
return this.#id;
}
public get type() {
return this.#type;
}
public get schema() {
return this.#schema;
}
public get fields() {
return this.#fields;
}
public get methods() {
return this.#methods;
}
public setFields(fields: DataSchema[]) {
this.#fields = fields;
}
public setMethods(methods: CodeBlockContent[]) {
this.#methods = methods;
}
public get data() {
return this.#observedData.getData('');
}
public setData(data: any, path?: string) {
this.#observedData.update(data, path);
const changeEvent: ChangeEvent = {
updateData: data,
path,
};
this.emit('change', changeEvent);
}
public setValue(path: string, data: any) {
return this.setData(data, path);
}
public onDataChange(path: string, callback: (newVal: any) => void) {
this.#observedData.on(path, callback);
}
public offDataChange(path: string, callback: (newVal: any) => void) {
this.#observedData.off(path, callback);
}
public getDefaultData() {
return getDefaultValueFromFields(this.#fields);
}
public async init() {
this.isInit = true;
}
public destroy() {
this.#fields = [];
this.removeAllListeners();
this.#observedData.destroy();
}
}