From f0e0279efbf2717d792d65908c0906d5c5f62b11 Mon Sep 17 00:00:00 2001 From: mantou132 <709922234@qq.com> Date: Sun, 11 Aug 2024 23:59:10 +0800 Subject: [PATCH] Use `createRef` instead decorators `@refobject` Closed #188 --- packages/duoyun-ui/src/elements/badge.ts | 12 ++- packages/duoyun-ui/src/elements/button.ts | 16 ++-- packages/duoyun-ui/src/elements/code-block.ts | 21 ++--- packages/duoyun-ui/src/elements/collapse.ts | 16 ++-- .../duoyun-ui/src/elements/color-picker.ts | 11 ++- .../duoyun-ui/src/elements/contextmenu.ts | 23 ++--- .../duoyun-ui/src/elements/file-picker.ts | 13 ++- packages/duoyun-ui/src/elements/flow.ts | 22 ++--- packages/duoyun-ui/src/elements/form.ts | 10 +-- packages/duoyun-ui/src/elements/input.ts | 15 ++-- packages/duoyun-ui/src/elements/list.ts | 22 +++-- packages/duoyun-ui/src/elements/modal.ts | 46 +++++----- packages/duoyun-ui/src/elements/popover.ts | 19 ++-- packages/duoyun-ui/src/elements/select.ts | 34 ++++---- packages/duoyun-ui/src/elements/slider.ts | 11 ++- packages/duoyun-ui/src/patterns/form.ts | 14 +-- packages/duoyun-ui/src/patterns/table.ts | 14 ++- packages/gem-book/src/element/elements/nav.ts | 20 ++--- packages/gem-book/src/element/elements/pre.ts | 19 ++-- .../gem-book/src/element/elements/sidebar.ts | 6 +- packages/gem-book/src/element/index.ts | 7 +- packages/gem-book/src/plugins/docsearch.ts | 10 +-- packages/gem-book/src/plugins/sandpack.ts | 10 +-- packages/gem-devtools/src/modules/panel.ts | 4 +- packages/gem-examples/src/benchmark/index.ts | 9 +- packages/gem-examples/src/controlled/index.ts | 12 +-- packages/gem-examples/src/dialog/index.ts | 8 +- packages/gem-examples/src/effect/index.ts | 8 +- packages/gem-examples/src/gesture/canvas.ts | 14 +-- packages/gem-examples/src/gesture/index.ts | 28 +++--- .../life-cycle/{chidren.ts => children.ts} | 0 packages/gem-examples/src/life-cycle/index.ts | 12 +-- packages/gem-examples/src/ref-route/index.ts | 9 +- packages/gem-examples/src/reflect/index.ts | 16 +--- .../002-advance/002-gem-element-more.md | 8 +- .../gem/docs/en/003-api/001-gem-element.md | 11 ++- .../004-blog/002-create-controlled-element.md | 50 +++++------ .../en/004-blog/008-migrate-from-react.md | 32 +++++++ .../002-advance/002-gem-element-more.md | 8 +- .../gem/docs/zh/003-api/001-gem-element.md | 9 +- .../004-blog/002-create-controlled-element.md | 50 +++++------ .../zh/004-blog/008-migrate-from-react.md | 44 ++++++++-- packages/gem/src/lib/decorators.ts | 86 +------------------ packages/gem/src/lib/element.ts | 42 ++++++++- .../gem/src/test/gem-element/advance.test.ts | 8 +- .../src/test/gem-element/decorators.test.ts | 9 +- .../gem/src/test/gem-element/multi.test.ts | 10 +-- 47 files changed, 413 insertions(+), 465 deletions(-) rename packages/gem-examples/src/life-cycle/{chidren.ts => children.ts} (100%) diff --git a/packages/duoyun-ui/src/elements/badge.ts b/packages/duoyun-ui/src/elements/badge.ts index 3bf0e03e..2cee1d31 100644 --- a/packages/duoyun-ui/src/elements/badge.ts +++ b/packages/duoyun-ui/src/elements/badge.ts @@ -7,13 +7,11 @@ import { numattribute, property, boolattribute, - refobject, - RefObject, state, shadow, mounted, } from '@mantou/gem/lib/decorators'; -import { createCSSSheet, GemElement, html } from '@mantou/gem/lib/element'; +import { createCSSSheet, createRef, GemElement, html } from '@mantou/gem/lib/element'; import { classMap, css } from '@mantou/gem/lib/utils'; import { contentsContainer } from '../lib/styles'; @@ -101,7 +99,7 @@ export class DuoyunBadgeElement extends GemElement { @property icon?: string | Element | DocumentFragment; - @refobject slotRef: RefObject; + #slotRef = createRef(); get #max() { return this.max || 99; @@ -112,19 +110,19 @@ export class DuoyunBadgeElement extends GemElement { } #onSlotChange = () => { - this.inline = !this.slotRef.element!.assignedElements({ flatten: true }).length; + this.inline = !this.#slotRef.element!.assignedElements({ flatten: true }).length; }; @mounted() #init = () => { this.inline = !this.childNodes.length; - this.slotRef.element?.addEventListener('slotchange', this.#onSlotChange); + this.#slotRef.element?.addEventListener('slotchange', this.#onSlotChange); }; render = () => { const value = Number(this.count) > this.#max ? `${this.#max}+` : `${this.count}`; return html` - + ${this.count || this.icon || this.dot ? html` ; @boolattribute small: boolean; @@ -160,10 +161,7 @@ export class DuoyunButtonElement extends GemElement { @property icon?: string | Element | DocumentFragment; @state active: boolean; - @refobject dropdownRef: RefObject; - - @part static button: string; - @part static dropdown: string; + #dropdownRef = createRef(); get #color() { return getSemanticColor(this.color) || this.color || theme.primaryColor; @@ -186,7 +184,7 @@ export class DuoyunButtonElement extends GemElement { e.stopPropagation(); if (this.disabled) return; if (this.dropdown) { - const { element } = this.dropdownRef; + const { element } = this.#dropdownRef; const { right, bottom } = element!.getBoundingClientRect(); const { width } = this.getBoundingClientRect(); element!.active = true; @@ -233,7 +231,7 @@ export class DuoyunButtonElement extends GemElement { } ; + #codeRef = createRef(); #getRanges(str: string) { const ranges = str.split(/,\s*/); @@ -378,7 +369,7 @@ export class DuoyunCodeBlockElement extends DuoyunVisibleBaseElement { @effect((i) => [i.textContent, i.codelang]) #updateHtml = async () => { if (!this.visible) return; - if (!this.codeRef.element) return; + if (!this.#codeRef.element) return; await import(/* @vite-ignore */ /* webpackIgnore: true */ prismjs); const { Prism } = window as any; if (this.codelang && !Prism.languages[this.codelang]) { @@ -396,7 +387,7 @@ export class DuoyunCodeBlockElement extends DuoyunVisibleBaseElement { const htmlStr = Prism.languages[this.codelang] ? Prism.highlight(this.textContent || '', Prism.languages[this.codelang], this.codelang) : this.innerHTML; - this.codeRef.element.innerHTML = this.#getParts(htmlStr); + this.#codeRef.element.innerHTML = this.#getParts(htmlStr); }; render() { @@ -416,7 +407,7 @@ export class DuoyunCodeBlockElement extends DuoyunVisibleBaseElement { `, ) : ''} - ${this.#getParts(this.textContent || '')} + ${this.#getParts(this.textContent || '')} -
+
= { @adoptedStyle(style) @shadow() export class DyPatFormElement> extends GemElement { - @refobject formRef: RefObject; - @property data?: T; @property formItems?: FormItem[]; + #formRef = createRef(); + @memo((i) => [i.data]) #initState = () => { if (!this.data) return; @@ -310,7 +310,7 @@ export class DyPatFormElement> extends GemElement { const ele = this.#createFormInputElement(props.type); ele.addEventListener('change', (evt: CustomEvent) => { this.#onInputChange(evt, props); - this.formRef.element?.dispatchEvent( + this.#formRef.element?.dispatchEvent( new CustomEvent('itemchange', { detail: { name: name, value: evt.detail }, }), @@ -442,7 +442,7 @@ export class DyPatFormElement> extends GemElement { render = () => { return html` - + ${this.#renderItems(this.formItems)} `; @@ -454,7 +454,7 @@ export class DyPatFormElement> extends GemElement { ignoreCache: {}, }); - valid = () => this.formRef.element!.valid(); + valid = () => this.#formRef.element!.valid(); } type CreateFormOptions = { diff --git a/packages/duoyun-ui/src/patterns/table.ts b/packages/duoyun-ui/src/patterns/table.ts index f47c04f8..89f6bfb5 100644 --- a/packages/duoyun-ui/src/patterns/table.ts +++ b/packages/duoyun-ui/src/patterns/table.ts @@ -1,8 +1,7 @@ -import { createCSSSheet, createState, GemElement, html } from '@mantou/gem/lib/element'; +import { createCSSSheet, createRef, createState, GemElement, html } from '@mantou/gem/lib/element'; import { QueryString, addListener, css, styleMap } from '@mantou/gem/lib/utils'; import { Emitter, - RefObject, adoptedStyle, boolattribute, connectStore, @@ -12,7 +11,6 @@ import { memo, numattribute, property, - refobject, shadow, } from '@mantou/gem/lib/decorators'; import { history } from '@mantou/gem/lib/history'; @@ -164,8 +162,6 @@ const style = createCSSSheet(css` @connectStore(locationStore) @shadow() export class DyPatTableElement extends GemElement { - @refobject tableRef: RefObject>; - @boolattribute filterable: boolean; @boolattribute selectable: boolean; @@ -202,6 +198,8 @@ export class DyPatTableElement extends GemElement { | ComparerType, ) => string = (e) => e.replace(/([A-Z])/g, ' $1').replace(/^\w/, ($1) => $1.toUpperCase()); + #tableRef = createRef>(); + get #defaultPagesize() { return this.pagesize || this.sizes?.[0] || 20; } @@ -244,7 +242,7 @@ export class DyPatTableElement extends GemElement { #onContextMenu = (originEvent: MouseEvent, currentRowData?: T, selected?: boolean) => { if (originEvent.altKey) return; if (!this.selectable) return; - const table = this.tableRef.element!; + const table = this.#tableRef.element!; const { selection } = this.#state; originEvent.stopPropagation(); originEvent.preventDefault(); @@ -660,7 +658,7 @@ export class DyPatTableElement extends GemElement { if (!search) return highlights.clear(); - const tbody = this.tableRef.element?.shadowRoot?.querySelector('tbody'); + const tbody = this.#tableRef.element?.shadowRoot?.querySelector('tbody'); if (!tbody) return; const highlight = new Highlight(); @@ -711,7 +709,7 @@ export class DyPatTableElement extends GemElement {
; - @refobject i18nRef: RefObject; + + #spaceRef = createRef(); + #i18nRef = createRef(); #renderI18nSelect = () => { const { langList = [], lang } = bookStore; if (lang) { return html`
- this.i18nRef.element?.click()} .element=${icons.i18n}> + this.#i18nRef.element?.click()} .element=${icons.i18n}> `; + return html``; } } diff --git a/packages/gem-examples/src/dialog/index.ts b/packages/gem-examples/src/dialog/index.ts index 1aa38e55..32a5cfa7 100644 --- a/packages/gem-examples/src/dialog/index.ts +++ b/packages/gem-examples/src/dialog/index.ts @@ -1,4 +1,4 @@ -import { GemElement, html, customElement, refobject, RefObject, render, shadow, createState } from '@mantou/gem'; +import { GemElement, html, customElement, render, shadow, createState, createRef } from '@mantou/gem'; import { createModalClass } from '@mantou/gem/elements/base/modal-factory'; import { GemDialogBaseElement } from '@mantou/gem/elements/base/dialog'; @@ -110,14 +110,14 @@ class Dialog extends GemDialogBaseElement { @customElement('app-root') @shadow() export class Root extends GemElement { - @refobject dialog: RefObject; + #dialog = createRef(); #state = createState({ modal: false, }); #clickHandle = () => { - this.dialog.element?.open(); + this.#dialog.element?.open(); }; render() { @@ -130,7 +130,7 @@ export class Root extends GemElement { this.#state({ modal: true })} @close=${() => this.#state({ modal: false })} > diff --git a/packages/gem-examples/src/effect/index.ts b/packages/gem-examples/src/effect/index.ts index 61065511..6bbf4c1b 100644 --- a/packages/gem-examples/src/effect/index.ts +++ b/packages/gem-examples/src/effect/index.ts @@ -1,4 +1,4 @@ -import { GemElement, html, customElement, RefObject, refobject, render, createState, mounted } from '@mantou/gem'; +import { GemElement, html, customElement, render, createState, mounted, createRef } from '@mantou/gem'; import '../elements/layout'; @@ -13,7 +13,7 @@ function effect([textareaElement, callback]: [HTMLTextAreaElement | undefined, ( @customElement('app-root') export class App extends GemElement { - @refobject textAreaRef: RefObject; + #textAreaRef = createRef(); #state = createState({ height: 0, @@ -26,13 +26,13 @@ export class App extends GemElement { @mounted() #init = () => { - this.effect(effect, () => [this.textAreaRef.element, this.#updateHeight]); + this.effect(effect, () => [this.#textAreaRef.element, this.#updateHeight]); }; render() { return html`
- ${this.#state.hidden ? null : html``} + ${this.#state.hidden ? null : html``}
${this.#state.height}
`; } diff --git a/packages/gem-examples/src/gesture/canvas.ts b/packages/gem-examples/src/gesture/canvas.ts index 2e898a73..6eebb566 100644 --- a/packages/gem-examples/src/gesture/canvas.ts +++ b/packages/gem-examples/src/gesture/canvas.ts @@ -1,17 +1,17 @@ import { PanEventDetail } from '@mantou/gem/elements/gesture'; -import { GemElement, html, customElement, property, refobject, RefObject, mounted } from '@mantou/gem'; +import { GemElement, html, customElement, property, mounted, createRef } from '@mantou/gem'; @customElement('app-canvas') export class AppCanvas extends GemElement { @property data: PanEventDetail[]; - @refobject canvasRef: RefObject; - @refobject canvasRef1: RefObject; + #canvasRef = createRef(); + #canvasRef1 = createRef(); @mounted() #init = () => { - const canvas = this.canvasRef.element!; - const canvas1 = this.canvasRef1.element!; + const canvas = this.#canvasRef.element!; + const canvas1 = this.#canvasRef1.element!; const ctx = canvas.getContext('2d')!; const ctx1 = canvas1.getContext('2d')!; canvas.height = 150; @@ -64,8 +64,8 @@ export class AppCanvas extends GemElement { render() { return html`
- - + + `; } } diff --git a/packages/gem-examples/src/gesture/index.ts b/packages/gem-examples/src/gesture/index.ts index 8e0e38eb..874f4f97 100644 --- a/packages/gem-examples/src/gesture/index.ts +++ b/packages/gem-examples/src/gesture/index.ts @@ -5,7 +5,7 @@ import type { SwipeEventDetail, GemGestureElement, } from '@mantou/gem/elements/gesture'; -import { render, GemElement, html, customElement, refobject, RefObject, createState } from '@mantou/gem'; +import { render, GemElement, html, customElement, createRef, createState } from '@mantou/gem'; import '@mantou/gem/elements/gesture'; import '../elements/layout'; @@ -13,7 +13,7 @@ import './canvas'; @customElement('app-root') export class AppRoot extends GemElement { - @refobject gestureRef: RefObject; + #gestureRef = createRef(); #state = createState({ x: 0, @@ -25,21 +25,21 @@ export class AppRoot extends GemElement { moves: [] as any[], }); - onPan = (evt: CustomEvent) => { + #onPan = (evt: CustomEvent) => { const { detail } = evt; const { x, y } = this.#state; this.#state({ x: detail.x + x, y: detail.y + y, duration: 0 }); }; - onPinch = (evt: CustomEvent) => { + #onPinch = (evt: CustomEvent) => { this.#state({ scale: evt.detail.scale * this.#state.scale }); }; - onRotate = (evt: CustomEvent) => { + #onRotate = (evt: CustomEvent) => { this.#state({ rotate: evt.detail.rotate + this.#state.rotate }); }; - onSwipe = (e: CustomEvent) => { + #onSwipe = (e: CustomEvent) => { this.#state({ swipe: `${e.detail.direction}, speed: ${e.detail.speed}` }); }; - onEnd = () => { + #onEnd = () => { this.#state({ x: 0, y: 0, @@ -47,7 +47,7 @@ export class AppRoot extends GemElement { scale: 1, rotate: 0, swipe: '', - moves: [...this.gestureRef.element!.movesMap.values().next().value], + moves: [...this.#gestureRef.element!.movesMap.values().next().value], }); }; render() { @@ -62,13 +62,13 @@ export class AppRoot extends GemElement { } ; @attribute appTitle: string; + #childRef = createRef(); + constructor(title: string) { super(); this.appTitle = title; @@ -61,7 +61,7 @@ export class App extends GemElement { }; loadHandle = () => { - const { element } = this.childRef; + const { element } = this.#childRef; if (!element) return; const { firstName, lastName, disabled, count } = element; console.log({ firstName, lastName, disabled, count }); @@ -77,7 +77,7 @@ export class App extends GemElement {

${this.appTitle}

; + #routeRef = createRef(); constructor() { super(); @@ -86,7 +85,7 @@ export class App extends GemElement { } #onClick = () => { - if (this.routeRef.element?.currentRoute === routes.home) { + if (this.#routeRef.element?.currentRoute === routes.home) { history.push(createHistoryParams(routes.a, { params: { b: String(Date.now()) } })); } else { history.push(createHistoryParams(routes.home)); @@ -97,7 +96,7 @@ export class App extends GemElement {
${JSON.stringify(locationStore.params)}
; + #childrenRef = createRef(); #state = createState({ mount: true, }); @@ -39,7 +29,7 @@ export class App extends GemElement { ${this.#state.mount ? html` - +