parent
843a64ebd9
commit
727db59da0
|
@ -15,6 +15,7 @@
|
|||
|
||||
import { watch } from 'inula-reactive';
|
||||
import { isReactiveObj } from 'inula-reactive';
|
||||
import { RefCallback, RefObject } from './type';
|
||||
|
||||
/**
|
||||
* Creates a function that returns a Node created from the provided HTML string.
|
||||
|
@ -93,7 +94,7 @@ function insertExpression(parent: Node, value: any, prevValue: any, marker?: Nod
|
|||
result = cleanChildren(parent, prevValue, marker);
|
||||
} else if (t === 'function') {
|
||||
// 在watch里面执行
|
||||
watchRender((prev) => {
|
||||
watchRender(prev => {
|
||||
let v = value();
|
||||
while (isReactiveObj(v)) {
|
||||
v = v.get();
|
||||
|
@ -108,7 +109,7 @@ function insertExpression(parent: Node, value: any, prevValue: any, marker?: Nod
|
|||
const array: any[] = [];
|
||||
const isPrevArray: boolean = prevValue && Array.isArray(prevValue);
|
||||
if (flattenArray(array, value)) {
|
||||
watchRender((prev) => {
|
||||
watchRender(prev => {
|
||||
result = insertExpression(parent, array, prev, marker);
|
||||
return result;
|
||||
}, prevValue);
|
||||
|
@ -116,7 +117,8 @@ function insertExpression(parent: Node, value: any, prevValue: any, marker?: Nod
|
|||
return () => result;
|
||||
}
|
||||
|
||||
if (array.length === 0) { // 当前没有节点
|
||||
if (array.length === 0) {
|
||||
// 当前没有节点
|
||||
result = cleanChildren(parent, prevValue, marker);
|
||||
if (multi) {
|
||||
return result;
|
||||
|
@ -135,7 +137,8 @@ function insertExpression(parent: Node, value: any, prevValue: any, marker?: Nod
|
|||
appendNodes(parent, array);
|
||||
}
|
||||
result = array;
|
||||
} else if (value.nodeType) { // 是Node节点
|
||||
} else if (value.nodeType) {
|
||||
// 是Node节点
|
||||
if (Array.isArray(prevValue)) {
|
||||
if (multi) {
|
||||
return cleanChildren(parent, prevValue, marker, value);
|
||||
|
@ -367,3 +370,18 @@ export function style(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a ref to a node.
|
||||
* @param node
|
||||
* @param ref
|
||||
*/
|
||||
export function bindRef<T>(node: T, ref: RefObject<T> | RefCallback<T>): void {
|
||||
if (typeof ref === 'function') {
|
||||
ref(node);
|
||||
} else if (ref && 'current' in ref) {
|
||||
(ref as RefObject<T>).current = node;
|
||||
} else {
|
||||
throw new Error('Invalid ref');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,3 +20,7 @@ export type AppDisposer = () => void;
|
|||
export type Props = Record<string, unknown>;
|
||||
export type Context = Props;
|
||||
export type WithChildren<T = Props> = T & { children?: JSXElement };
|
||||
// --- ref ---
|
||||
export type RefObject<T> = { current: T | null };
|
||||
export type RefCallback<T> = (instance: T | null) => void;
|
||||
export type Ref<T> = RefObject<T> | RefCallback<T> | T;
|
||||
|
|
|
@ -406,7 +406,7 @@ describe('env', () => {
|
|||
|
||||
render(() => $$runComponent(App, {}), container);
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(
|
||||
'<ul><li>root</li><ul><li>sub1</li><li>root-sub1-1</li><li>root-sub1-2</li></ul><ul><li>sub2</li><li>root-sub2-3</li><ul><li>sub3</li><li>root-sub2-sub3-4</li></ul><li>root-sub2-5</li></ul></ul>',
|
||||
'"<ul><li>root</li><ul><li>sub1</li><li>root-sub1-1</li><li>root-sub1-2</li></ul><ul><li>sub2</li><li>root-sub2-3</li><ul><li>sub3</li><li>root-sub2-sub3-4</li></ul><li>root-sub2-5</li></ul></ul>"',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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, expect } from 'vitest';
|
||||
import { domTest as it } from './utils';
|
||||
import { template as $$template, bindRef as $$bindRef } from '../src/dom';
|
||||
import { runComponent as $$runComponent, render } from '../src/core';
|
||||
|
||||
describe('ref', () => {
|
||||
it('should reference to dom.', ({ container }) => {
|
||||
/*
|
||||
* 源码:
|
||||
* function App(props) {
|
||||
* let ref;
|
||||
* return <canvas ref={ref} width="256" height="256" />;
|
||||
* }
|
||||
*/
|
||||
const $tmpl$ = $$template(`<canvas width="256" height="256"></canvas>`);
|
||||
let ref: Node;
|
||||
|
||||
function App() {
|
||||
return (() => {
|
||||
const $div = $tmpl$();
|
||||
const $ref = ref;
|
||||
typeof $ref === 'function' ? $$bindRef($ref, $div) : (ref = $div);
|
||||
return $div;
|
||||
})();
|
||||
}
|
||||
|
||||
render(() => $$runComponent(App, {}), container);
|
||||
expect(ref).toBe(container.firstChild);
|
||||
});
|
||||
|
||||
it('should reference to component.', ({ container }) => {
|
||||
/**
|
||||
* 源码:
|
||||
* // App.tsx
|
||||
* import Canvas from "./canvas";
|
||||
*
|
||||
* function App() {
|
||||
* let canvas;
|
||||
* return <Canvas ref={canvas} />;
|
||||
* }
|
||||
*
|
||||
* render(() => <App />, document.getElementById("app"));
|
||||
*
|
||||
* // canvas.tsx
|
||||
* export default function Canvas(props) {
|
||||
* return <canvas ref={props.ref} width="256" height="256" />;
|
||||
* }
|
||||
*/
|
||||
const $tmpl$ = $$template('<canvas width="256" height="256"></canvas>');
|
||||
|
||||
function Canvas() {
|
||||
return (() => {
|
||||
const $div = $tmpl$();
|
||||
const $ref = canvas;
|
||||
typeof $ref === 'function' ? $$bindRef($ref, $div) : (canvas = $div);
|
||||
return $div;
|
||||
})();
|
||||
}
|
||||
|
||||
let canvas: Node;
|
||||
|
||||
function App() {
|
||||
return $$runComponent(Canvas, {
|
||||
ref($r: Node) {
|
||||
const $ref = canvas;
|
||||
typeof $ref === 'function' ? $ref($r) : (canvas = $r);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
render(() => $$runComponent(App, {}), container);
|
||||
expect(canvas).toBe(container.firstChild);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue