Skip to content

Commit

Permalink
[gem] Remove Gem.docTitle
Browse files Browse the repository at this point in the history
Closed #192, #190
  • Loading branch information
mantou132 committed Sep 1, 2024
1 parent 4207c4a commit 5f44a43
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 84 deletions.
23 changes: 23 additions & 0 deletions packages/gem-examples/src/life-cycle/children.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,27 @@ import {

export type Message = number[];

@customElement('app-descendant')
@shadow()
export class Descendant extends GemElement {
key = 0;

constructor() {
super();
console.log(`descendant${this.key} cons`);
}

@mounted()
#init = () => {
console.log(`descendant${this.key} mounted`);
};

render() {
console.log(`descendant${this.key} render`);
return html``;
}
}

/**
* @attr first-name
* @attr last-name
Expand Down Expand Up @@ -70,6 +91,8 @@ export class Children extends GemElement {
<p part=${Children.paragraph}>properties: ${JSON.stringify(this.message)}</p>
<slot name=${Children.light}></slot>
<button @click=${() => this.sayHi({}, { bubbles: true, composed: true })}>say hi</button>
<app-descendant .key=${1}></app-descendant>
<app-descendant .key=${2}></app-descendant>
`;
}
}
21 changes: 19 additions & 2 deletions packages/gem-examples/src/multi-page/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import '../elements/layout';
import './page-b';
import './page-c';

// 没写 `basePath`

const routes = [
{
pattern: '/',
Expand All @@ -32,8 +34,21 @@ const routes = [
content: html`<app-page-c>C: </app-page-c>`,
},
{
pattern: '/',
content: html`<div>hello</div>`,
pattern: '/empty',
content: html``,
},
{
pattern: '/*',
content: html`<div>
<gem-light-route
.routes=${[
{
pattern: '/*',
content: html`pattern match`,
},
]}
></gem-light-route>
</div>`,
},
];

Expand Down Expand Up @@ -62,6 +77,8 @@ class _App extends GemElement {
<gem-link path="/a">PageA</gem-link>
<gem-link path="/b">PageB</gem-link>
<gem-link path="/c/e" pattern="/c/*">PageC</gem-link>
<gem-link path="/empty">Empty</gem-link>
<gem-link path="/test">Test</gem-link>
</nav>
<main><gem-light-route .routes=${routes}></gem-light-route></main>
`;
Expand Down
19 changes: 9 additions & 10 deletions packages/gem/docs/en/003-api/008-utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

Some frequently used functions

| name | description |
| --------------------- | -------------------------------------------------------------------------------- |
| `css` | Template string label function, only use for CSS text syntax highlighting |
| `raw` | Template string tag function, only use for HTML text syntax highlighting |
| `styled` | A collection of template string label functions, provide CSS highlighting |
| `styleMap` | Convert objects into `style` attribute |
| `classMap` | Convert objects into `class` attribute |
| `partMap` | Convert objects into `part` attribute |
| `addMicrotask` | Add microtask, avoid repetitive |
| `addMicrotaskToStack` | Similar to `addMicrotask`, but the microtasks added later will be executed first |
| name | description |
| -------------- | ------------------------------------------------------------------------- |
| `css` | Template string label function, only use for CSS text syntax highlighting |
| `raw` | Template string tag function, only use for HTML text syntax highlighting |
| `styled` | A collection of template string label functions, provide CSS highlighting |
| `styleMap` | Convert objects into `style` attribute |
| `classMap` | Convert objects into `class` attribute |
| `partMap` | Convert objects into `part` attribute |
| `addMicrotask` | Add microtask, avoid repetitive |
19 changes: 9 additions & 10 deletions packages/gem/docs/zh/003-api/008-utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

一些经常被用到的函数

| 名称 | 描述 |
| --------------------- | --------------------------------------------------------- |
| `css` | 模版字符串标签函数,仅用于 CSS 文本语法高亮 |
| `raw` | 模版字符串标签函数,仅用于 HTML 文本语法高亮 |
| `styled` | 模版字符串标签函数的集合,用来提供 CSS 规则高亮和 JS 引用 |
| `styleMap` | 将对象构建成 `style` 属性 |
| `classMap` | 将对象构建成 `class` 属性 |
| `partMap` | 将对象构建成 `part` 属性 |
| `addMicrotask` | 添加微任务,会避免重复 |
| `addMicrotaskToStack` | 类似 `addMicrotask`, 但先添加的微任务后执行 |
| 名称 | 描述 |
| -------------- | --------------------------------------------------------- |
| `css` | 模版字符串标签函数,仅用于 CSS 文本语法高亮 |
| `raw` | 模版字符串标签函数,仅用于 HTML 文本语法高亮 |
| `styled` | 模版字符串标签函数的集合,用来提供 CSS 规则高亮和 JS 引用 |
| `styleMap` | 将对象构建成 `style` 属性 |
| `classMap` | 将对象构建成 `class` 属性 |
| `partMap` | 将对象构建成 `part` 属性 |
| `addMicrotask` | 添加微任务,会避免重复 |
19 changes: 12 additions & 7 deletions packages/gem/src/elements/base/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
adoptedStyle,
mounted,
effect,
boolattribute,
} from '../../lib/decorators';
import { history, basePathStore } from '../../lib/history';
import { absoluteLocation, css } from '../../lib/utils';
Expand Down Expand Up @@ -61,8 +62,9 @@ export class GemLinkElement extends GemElement {
@attribute path: string;
@attribute query: string;
@attribute hash: string;
@attribute docTitle: string;
@attribute hint: 'on' | 'off';
/** Preload route content when point over */
@boolattribute preload: boolean;

// 动态路由,根据 route.pattern 和 options.params 计算出 path
@property route?: RouteItem;
Expand Down Expand Up @@ -113,24 +115,19 @@ export class GemLinkElement extends GemElement {
await this.prepare?.();

if (this.route) {
history.pushIgnoreCloseHandle({
...createHistoryParams(this.route, this.#routeOptions),
title: this.route.title || this.docTitle,
});
history.pushIgnoreCloseHandle(createHistoryParams(this.route, this.#routeOptions));
} else if (this.href) {
const url = new URL(locationString, location.origin);
history.pushIgnoreCloseHandle({
path: url.pathname,
query: url.search,
hash: url.hash,
title: this.docTitle,
});
} else {
history.pushIgnoreCloseHandle({
path: this.path,
query: this.query,
hash: this.hash,
title: this.docTitle,
});
}
};
Expand All @@ -146,9 +143,17 @@ export class GemLinkElement extends GemElement {
: new URL(history.basePath + locationString, location.origin).toString();
};

#preload = () => {
// 也许是 `getter`
this.route?.content;
// 只触发 `getContent` 调用,参数不使用
this.route?.getContent?.({}, this.shadowRoot!);
};

@mounted()
#init() {
this.addEventListener('click', this.#onClick);
this.addEventListener('pointerenter', this.#preload);
}

render() {
Expand Down
5 changes: 4 additions & 1 deletion packages/gem/src/elements/base/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,10 @@ export class GemLightRouteElement extends GemElement {
return;
}
if (this.trigger === history) {
updateStore(titleStore, { title: route?.title });
// 嵌套路由执行顺序也是从父到子
if (location.href !== titleStore.url || route?.title) {
updateStore(titleStore, { url: location.href, title: route?.title });
}
}
const contentOrLoader = content || getContent?.(params, this.shadowRoot || this);
this.loading(route);
Expand Down
57 changes: 24 additions & 33 deletions packages/gem/src/elements/base/title.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,34 @@
* 修改标题:titleStore 的 title 优先级高,比如 history 添加的 dialog Title
*
* - `<gem-route>` 匹配路由时自动设置 `route.title`
* - `<gem-link>` 的 `doc-title` 属性和 `route.title`
* - 修改路径时,`history` 默认设置 `title` 为空
* - 修改路径(查询参数)时,`history` 默认设置 `title` 为空,运行 Modal 设置临时标题
* - 数据获取后,手动调用 `Title.setTitle`
* - `<gem-title>` 作为默认值设置
*/

import { GemElement, html } from '../../lib/element';
import { attribute, boolattribute, effect, shadow } from '../../lib/decorators';
import { attribute, boolattribute, effect, mounted, shadow } from '../../lib/decorators';
import { updateStore, connect } from '../../lib/store';
import { titleStore } from '../../lib/history';
import { addMicrotask } from '../../lib/utils';

const defaultTitle = document.title;
// 避免重定向时的中间状态标题
let timer = 0;
const setTitle = (documentTitle: string) => {
clearTimeout(timer);
timer = window.setTimeout(() => (document.title = documentTitle));
};

let documentTitle = '';
const setTitle = () => (document.title = documentTitle);

function setDocumentTitle(str?: string | null, prefix = '', suffix = '') {
const title = titleStore.title || str;
if (title && title !== defaultTitle) {
function setDocumentTitle(defaultTitle?: string | null, prefix = '', suffix = '') {
const title = titleStore.title || defaultTitle;
if (title && title !== titleStore.defaultTitle) {
GemTitleElement.title = title;
documentTitle = prefix + GemTitleElement.title + suffix;
setTitle(prefix + GemTitleElement.title + suffix);
} else {
GemTitleElement.title = defaultTitle;
documentTitle = GemTitleElement.title;
GemTitleElement.title = titleStore.defaultTitle;
setTitle(GemTitleElement.title);
}
// 避免重定向时的中间状态
addMicrotask(setTitle);
}

connect(titleStore, setDocumentTitle);

export const PREFIX = `${defaultTitle} | `;
export const SUFFIX = ` - ${defaultTitle}`;

/**
* @customElement gem-title
* @attr prefix
Expand All @@ -60,21 +53,19 @@ export class GemTitleElement extends GemElement {
updateStore(titleStore, { title });
}

@effect(() => [])
#mounted = () => {
new MutationObserver(() => this.update()).observe(this, {
characterData: true,
childList: true,
subtree: true,
});
};

@effect((i) => [i.inert])
#connectStore = () => !this.inert && connect(titleStore, this.update);

render() {
// 多个 <gem-title> 时,最终 document.title 按执行顺序决定
#ob = new MutationObserver(() => this.update());

@mounted()
#obTextContent = () => {
this.#ob.observe(this, { characterData: true, childList: true, subtree: true });
};

render = () => {
// 多个 <gem-title> 时,最终 document.title 按渲染顺序决定
setDocumentTitle(this.textContent?.trim(), this.prefix, this.suffix);
return html`${GemTitleElement.title}`;
}
};
}
2 changes: 1 addition & 1 deletion packages/gem/src/lib/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class GemHistory extends EventTarget {
// `<gem-**>` 只读写父应用 `basePath`
const gemHistory = new GemHistory();

const [gemTitleStore, updateTitleStore] = useStore({ title: '' });
const [gemTitleStore, updateTitleStore] = useStore({ defaultTitle: document.title, url: '', title: '' });

const _GEMHISTORY = { history: gemHistory, titleStore: gemTitleStore, basePathStore: gemBasePathStore };

Expand Down
20 changes: 0 additions & 20 deletions packages/gem/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,6 @@ export function addMicrotask(func: () => void) {
microtaskSet.add(func);
}

const microtaskStack: (() => void)[] = [];

function execMicrotaskStack() {
for (let i = microtaskStack.length - 1; i >= 0; i--) {
microtaskStack[i]();
}
microtaskStack.length = 0;
}

/**
* 添加回调函数到微任务队列栈;
* 先进后执行,使用这个函数可以改变嵌套的元素 `mounted` 的顺序;
*/
export function addMicrotaskToStack(func: () => void) {
if (!microtaskStack.length) {
addMicrotask(execMicrotaskStack);
}
microtaskStack.push(func);
}

// 不编码 hash 用于比较
export function absoluteLocation(currentPath = '', relativePath = '') {
const { pathname, search, hash } = new URL(relativePath, location.origin + currentPath);
Expand Down

0 comments on commit 5f44a43

Please sign in to comment.