feat: add lifecycle

This commit is contained in:
chaoling 2024-04-19 15:21:17 +08:00
parent d7101ff5e3
commit b725b0d98c
17 changed files with 297 additions and 46 deletions

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2023 Huawei Technologies Co.,Ltd.
*
* openInula is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
'use strict';
module.exports = {
printWidth: 120, // 一行120字符数如果超过会进行换行
tabWidth: 2, // tab等2个空格
useTabs: false, // 用空格缩进行
semi: true, // 行尾使用分号
singleQuote: true, // 字符串使用单引号
quoteProps: 'as-needed', // 仅在需要时在对象属性添加引号
jsxSingleQuote: false, // 在JSX中使用双引号
trailingComma: 'es5', // 使用尾逗号(对象、数组等)
bracketSpacing: true, // 对象的括号间增加空格
bracketSameLine: false, // 将多行JSX元素的>放在最后一行的末尾
arrowParens: 'avoid', // 在唯一的arrow函数参数周围省略括号
vueIndentScriptAndStyle: false, // 不缩进Vue文件中的<script>和<style>标记内的代码
endOfLine: 'lf', // 仅限换行(\n
};

View File

@ -0,0 +1,2 @@
## 适配Vue

View File

@ -0,0 +1,19 @@
{
"name": "@inula/vue-adapter",
"version": "0.0.1",
"description": "vue adapter",
"main": "./src/index.ts",
"scripts": {
"test": "vitest --ui"
},
"dependencies": {
"openinula": "workspace:*"
},
"devDependencies": {
"@testing-library/user-event": "^12.1.10",
"@vitest/ui": "^0.34.5",
"jsdom": "^24.0.0",
"vitest": "^0.34.5",
"@vitejs/plugin-react": "^4.2.1"
}
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openInula is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
export * from './lifecycle';

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openInula is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
import { useEffect, useLayoutEffect, useRef } from 'openinula';
// 用于存储组件是否已挂载的状态
const useIsMounted = () => {
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
return isMounted;
};
export const onBeforeMount = (fn: () => void) => {
const isMounted = useIsMounted();
if (!isMounted) {
fn?.();
}
};
export function onMounted(fn: () => void) {
useEffect(() => {
fn?.();
}, []);
}
export function onBeforeUpdated(fn: () => void) {
useEffect(() => {
fn?.();
});
}
export function onUpdated(fn: () => void) {
useEffect(() => {
fn?.();
});
}
export const onBeforeUnmount = (fn: () => void) => {
useLayoutEffect(() => {
return () => {
fn?.();
};
}, []);
};
export function onUnmounted(fn: () => void) {
useEffect(() => {
return () => {
fn?.();
};
}, []);
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
*
* openInula is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck For the compiled code.
import { describe, it, vi, expect } from 'vitest';
import { render, act, useState } from 'openinula';
import { onBeforeUnmount } from '../src';
describe('lifecycle', () => {
it('should call the onBeforeUnmount before the component unmounts', () => {
const fn = vi.fn(() => {
// 断言在组件卸载之前,子组件仍然存在于 DOM 中
expect(document.querySelector('span')).not.toBeNull();
});
const Comp = () => {
const [toggle, setToggle] = useState(true);
return (
<>
{toggle ? <Child /> : null}
<button onClick={() => setToggle(false)}>Unmount</button>
</>
);
};
const Child = () => {
onBeforeUnmount(fn);
return <span />;
};
const container = document.createElement('div');
document.body.appendChild(container);
render(<Comp />, container);
expect(document.querySelector('span')).not.toBeNull();
act(() => {
container.querySelector('button').dispatchEvent(new MouseEvent('click', { bubbles: true }));
});
expect(fn).toHaveBeenCalledTimes(1);
expect(document.querySelector('span')).toBeNull();
});
});

View File

@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"moduleResolution": "Node",
"strict": true,
"esModuleInterop": true,
},
"ts-node": {
"esm": true
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openInula is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
import react from '@vitejs/plugin-react';
let alias = {
react: 'openinula', // 新增
'react-dom': 'openinula', // 新增
'react/jsx-dev-runtime': 'openinula/jsx-dev-runtime',
};
export default {
plugins: [react()],
test: {
environment: 'jsdom',
},
resolve: {
alias,
},
};

View File

@ -13,7 +13,8 @@
* See the Mulan PSL v2 for more details.
*/
import { ref, reactive, watchEffect, computed } from 'openinula';
import { vueReactive } from '../../../src';
const { ref, reactive, watchEffect, computed } = vueReactive;
describe('test computed', () => {
it('should correctly update the computed value', () => {

View File

@ -13,7 +13,8 @@
* See the Mulan PSL v2 for more details.
*/
import { reactive, isReactive, toRaw, ref, isRef, computed, watchEffect } from 'openinula';
import { vueReactive } from '../../../src';
const { reactive, isReactive, toRaw, ref, isRef, computed, watchEffect } = vueReactive;
describe('test reactive', () => {
it('should validate the reactivity of an object', () => {

View File

@ -13,18 +13,9 @@
* See the Mulan PSL v2 for more details.
*/
import {
ref,
isRef,
isReactive,
reactive,
watchEffect,
unref,
shallowRef,
isShallow,
RefType,
computed,
} from 'openinula';
import { vueReactive, RefType } from '../../../src';
const { ref, isRef, isReactive, reactive, watchEffect, unref, shallowRef, isShallow, computed } = vueReactive;
describe('test ref', () => {
it('should validate the value holding capability', () => {

View File

@ -13,10 +13,12 @@
* See the Mulan PSL v2 for more details.
*/
import { render, act, useReactive, useReference, useComputed, useWatch } from '../../../src';
import { render, act, vueReactive, RefType, unmountComponentAtNode } from '../../../src';
import { Text, triggerClickEvent } from '../../jest/commonComponents';
import * as Inula from '../../../src';
const { useReactive, useReference, useComputed, useWatch } = vueReactive;
describe('test reactive in FunctionComponent', () => {
const { unmountComponentAtNode } = Inula;
let container: HTMLElement | null = null;

View File

@ -13,7 +13,9 @@
* See the Mulan PSL v2 for more details.
*/
import { ref, reactive, watch, computed } from '../../../src';
import { vueReactive } from '../../../src';
const { ref, reactive, watch, computed } = vueReactive;
describe('test watch', () => {
it('should watch effect', async () => {

View File

@ -13,7 +13,9 @@
* See the Mulan PSL v2 for more details.
*/
import { reactive, toRaw, watchEffect } from 'openinula';
import { vueReactive } from '../../../src';
const { reactive, toRaw, watchEffect } = vueReactive;
function stop(stopHandle: () => void) {
stopHandle();

View File

@ -13,7 +13,8 @@
* See the Mulan PSL v2 for more details.
*/
import { createStore, watch, watchEffect } from '../../../src/index';
import { createStore, watch, vueReactive } from '../../../src/index';
const { watchEffect } = vueReactive;
describe('watch', () => {
it('should watch primitive state variable', async () => {

View File

@ -75,6 +75,24 @@ import {
import { syncUpdates as flushSync } from './renderer/TreeBuilder';
import { isReactive, isShallow } from './inulax/CommonUtils';
const vueReactive = {
ref,
useReference,
isRef,
unref,
shallowRef,
reactive,
useReactive,
isReactive,
isShallow,
computed,
useComputed,
watchEffect,
watch,
useWatch,
toRaw,
};
const Inula = {
Children,
createRef,
@ -126,20 +144,7 @@ const Inula = {
StrictMode,
Suspense,
// vue reactive api
ref,
useReference,
isRef,
unref,
shallowRef,
reactive,
useReactive,
isReactive,
isShallow,
computed,
useComputed,
watchEffect,
useWatch,
toRaw,
vueReactive,
};
export const version = '';
@ -197,20 +202,7 @@ export {
StrictMode,
Suspense,
// vue reactive api
ref,
useReference,
isRef,
unref,
shallowRef,
reactive,
useReactive,
isReactive,
isShallow,
computed,
useComputed,
watchEffect,
useWatch,
toRaw,
vueReactive,
};
export * from './types';

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
*
* openInula is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
export * from './reactive/Reactive';
export * from './reactive/Reactive';
export * from './reactive/Reactive';