-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
423 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
created: 20240327064109737 | ||
creator: 林一二 | ||
modified: 20240327064130227 | ||
modifier: 林一二 | ||
tags: 太微原理 | ||
title: JS微件 | ||
|
||
本主题解析几个例子,帮你理解 JavaScript 写的微件。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
created: 20240327063745039 | ||
creator: 林一二 | ||
modified: 20240327063811516 | ||
modifier: 林一二 | ||
tags: TiddlyWiki | ||
title: wikitext-macros | ||
|
||
\procedure activatePluginTab() | ||
<$action-setfield $tiddler="$:/state/tab-1749438307" text="$:/core/ui/ControlPanel/Plugins"/> | ||
<$action-navigate $to="$:/ControlPanel"/> | ||
\end | ||
|
||
\procedure activateTiddlerWindow() | ||
<$action-sendmessage $message="tm-open-window" $param=<<currentTiddler>> windowTitle="Side by Side View" width="800" height="600" /> | ||
\end | ||
|
||
\procedure controlPanel-plugin-link() | ||
<$button actions=<<activatePluginTab>> class="tc-btn-invisible tc-tiddlylink"> | ||
{{$:/core/images/options-button}} ~ControlPanel | ||
</$button> | ||
\end | ||
|
||
\procedure open-tiddler-in-window() | ||
\whitespace notrim | ||
<$button actions=<<activateTiddlerWindow>> class="tc-btn-invisible tc-tiddlylink"> | ||
open ''this'' tiddler in a new window | ||
</$button> | ||
\end | ||
|
||
\procedure activateEditionWindow(url) | ||
<$action-sendmessage $message="tm-open-external-window" $param=<<url>> windowName="_edition" windowFeatures="width=800 height=600" /> | ||
\end | ||
|
||
\procedure open-external-window(url) | ||
\whitespace notrim | ||
<$button actions=<<activateEditionWindow <<url>> class="tc-btn-invisible tc-tiddlylink"> | ||
open the ''example edition'' in a new window | ||
</$button> | ||
\end | ||
|
||
|
||
\procedure wikitext-example(src) | ||
<div class="doc-example"> | ||
<$macrocall $name="copy-to-clipboard-above-right" src=<<src>>/> | ||
<$codeblock code=<<src>>/> | ||
<p> | ||
That renders as: | ||
</p> | ||
<$transclude $variable="src" $mode="block"/> | ||
<p> | ||
... and the underlying HTML is: | ||
</p> | ||
<$wikify name="html" text=<<src>> output="html"> | ||
<$codeblock code=<<html>>/> | ||
</$wikify> | ||
</div> | ||
\end | ||
|
||
\procedure wikitext-example-without-html(src) | ||
<div class="doc-example"> | ||
<$macrocall $name="copy-to-clipboard-above-right" src=<<src>>/> | ||
<$codeblock code=<<src>>/> | ||
<p> | ||
That renders as: | ||
</p> | ||
<$transclude $variable="src" $mode="block"/> | ||
</div> | ||
\end | ||
|
||
\procedure wikitext-example-table-header() <thead><tr><th/><th>wiki text</th><th>renders as</th></tr></thead> | ||
|
||
\procedure wikitext-example-table-row(id, code) | ||
<tr> | ||
<th><<id>></th> | ||
<td><$codeblock code=<<code>>/></td> | ||
<td><<code>></td> | ||
</tr> | ||
\end | ||
|
||
\procedure tw-code(tiddler) | ||
<$codeblock language={{$tiddler$!!type}} code={{$tiddler$}}/> | ||
\end | ||
|
||
\procedure tw-code-link(tiddler) | ||
[[$tiddler$]]: | ||
<<tw-code $tiddler$>> | ||
\end | ||
|
||
\procedure flex-card(class,bordercolor:"",backgroundcolor:"",textcolor:"",imageField:"image",captionField:"caption",subtitle:"",descriptionField:"description",linkField:"link") | ||
<$link class={{{ [<class>addprefix[tc-card ]] }}} to={{{ [<currentTiddler>get<linkField>else<currentTiddler>] }}}> | ||
<div class="tc-card-accent" style.borderTop={{{ [<bordercolor>!is[blank]addprefix[5px solid ]] }}} style.background={{!!background}} style.backgroundColor=<<backgroundcolor>> style.color=<<textcolor>> style.fill=<<textcolor>>> | ||
<$list filter="[<currentTiddler>has[ribbon-text]]" variable="ignore"> | ||
<div class="tc-card-ribbon-wrapper"> | ||
<div class="tc-card-ribbon" style.backgroundColor={{{ [<currentTiddler>get[ribbon-color]else[red]] }}}> | ||
<div class="tc-card-ribbon-inner"> | ||
<$text text={{!!ribbon-text}}/> | ||
</div> | ||
</div> | ||
</div> | ||
</$list> | ||
<$list filter="[<currentTiddler>has<imageField>]" variable="ignore"> | ||
<div class="tc-card-image"> | ||
<$image source={{{ [<currentTiddler>get<imageField>] }}}/> | ||
</div> | ||
</$list> | ||
<div class="tc-card-title"><$transclude field=<<captionField>>><$view field="title"/></$transclude></div> | ||
<$list filter="[<subtitle>!is[blank]]" variable="ignore"> | ||
<div class="tc-card-subtitle"> | ||
<$text text=<<subtitle>>/> | ||
</div> | ||
</$list> | ||
<div class="tc-card-icon"><$transclude tiddler={{!!icon}}/></div> | ||
<div class="tc-card-body-wrapper"> | ||
<div class="tc-card-body"> | ||
<$transclude field=<<descriptionField>> mode="block"/> | ||
</div> | ||
<div class="tc-card-body-clear"> | ||
</div> | ||
</div> | ||
<$list filter="[all[current]has[button-text]]" variable="ignore"> | ||
<div class="tc-card-button" style.background-color={{!!button-color}} style.border-color={{!!button-color}}> | ||
<$text text={{!!button-text}}/> {{$:/core/images/chevron-right}} | ||
</div> | ||
</$list> | ||
</div> | ||
</$link> | ||
\end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
created: 20240327063449945 | ||
creator: 林一二 | ||
modified: 20240327065810228 | ||
modifier: 林一二 | ||
tags: 插件开发 | ||
title: 在太微里使用JavaScript | ||
|
||
!! 推荐的方式:包装成微件 | ||
|
||
例如最常见的动作微件: | ||
|
||
<<wikitext-example """ | ||
<$button> | ||
<$action-confirm $message="真的要让本条目自毁吗?" $prompt={{$:/state/promptUser}}> | ||
<$action-deletefield $tiddler="在太微里使用JavaScript" $field="text"/> | ||
</$action-confirm> | ||
删除本条目 | ||
</$button> | ||
""">> | ||
|
||
详见[[弹框确认微件action-confirm]]里的解析,它就是对 `window.confirm` 这个 JS 调用的包装。 | ||
|
||
此外[[Modern.TiddlyDev|https://tiddly-gittly.github.io/Modern.TiddlyDev/]]的教程里也介绍了如何创建一个简单的按钮微件 | ||
|
||
!! 包装成事件监听器 | ||
|
||
看看消息是如何在[[消息发送微件action-sendmessage]]里发送的,以及是如何在[[微件收发信息addEventListener和dispatchEvent]]里接收的。 | ||
|
||
!! 直接放入 RawMarkup | ||
|
||
详见[[SystemTag: $:/tags/RawMarkup|https://tiddlywiki.com/#SystemTag%3A%20%24%3A%2Ftags%2FRawMarkup]] | ||
|
||
这适合要全局生效的脚本,不过这样的用法不多,这个功能一般是用于放 Google Analysis 之类的第三方服务,或添加字体 CSS 用([[如何添加在线字体]]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
created: 20240327064131431 | ||
creator: 林一二 | ||
modified: 20240327064451603 | ||
modifier: 林一二 | ||
tags: JS微件 | ||
title: 弹框确认微件action-confirm | ||
|
||
|
||
```ts | ||
import { widget as Widget } from '$:/core/modules/widgets/widget.js'; | ||
import { IChangedTiddlers } from 'tiddlywiki'; | ||
import './index.css'; | ||
|
||
// 定义 ConfirmWidget 类,继承自 Widget | ||
class ConfirmWidget extends Widget { | ||
private message: string; | ||
private prompt: boolean; | ||
|
||
// 构造函数,初始化 ConfirmWidget | ||
constructor(parseTreeNode: any, options: any) { | ||
super(parseTreeNode, options); | ||
this.execute(); | ||
} | ||
|
||
// 计算微件的内部状态 | ||
execute() { | ||
this.message = this.getAttribute('$message', $tw.language.getString('ConfirmAction')); | ||
this.prompt = this.getAttribute('$prompt', 'yes') !== 'no'; | ||
this.makeChildWidgets(); | ||
} | ||
|
||
// 将此微件渲染到 DOM 中 | ||
render(parent: Element, nextSibling: Element) { | ||
this.parentDomNode = parent; | ||
this.renderChildren(parent, nextSibling); | ||
} | ||
|
||
// 刷新微件,确保属性是最新的 | ||
refresh(changedTiddlers: IChangedTiddlers): boolean { | ||
let changedAttributes = this.computeAttributes(); | ||
if (changedAttributes['$message'] || changedAttributes['$prompt']) { | ||
this.refreshSelf(); | ||
return true; | ||
} | ||
return this.refreshChildren(changedTiddlers); | ||
} | ||
|
||
// 触发与此微件相关联的动作 | ||
invokeAction(triggeringWidget: Widget, event: Event): boolean { | ||
let invokeActions = true; | ||
if (this.prompt) { | ||
invokeActions = window.confirm(this.message); | ||
} | ||
return invokeActions ? this.invokeActions(triggeringWidget, event) : false; | ||
} | ||
|
||
// 控制动作传播的方法 | ||
allowActionPropagation(): boolean { | ||
return false; | ||
} | ||
} | ||
|
||
// 将 ConfirmWidget 类导出为太微微件 | ||
declare let exports: { | ||
[key: string]: typeof ConfirmWidget; | ||
}; | ||
exports['action-confirm'] = ConfirmWidget; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
created: 20240327064646408 | ||
creator: 林一二 | ||
modified: 20240327065601795 | ||
modifier: 林一二 | ||
tags: JS微件 | ||
title: 微件收发信息addEventListener和dispatchEvent | ||
|
||
[[消息发送微件action-sendmessage]]的原理是调用 `dispatchEvent`。 | ||
|
||
在微件的方法里调用 `dispatchEvent` 会实际调用 `Widget` 这个父类上的 `dispatchEvent` 方法,然后逐级顺着微件树向上传递,最终传到 `$tw.rootWidget` 上。 | ||
|
||
最终遇到通过 `$tw.rootWidget.addEventListener` 注册了的事件监听器,或中间某一级微件注册了监听器,就会开始执行监听器里的逻辑。 | ||
|
||
```ts | ||
class Widget { | ||
private eventListeners: EventListener = {}; | ||
|
||
// 向微件添加事件监听器 | ||
addEventListener(type: string, handler: string | ((event: any) => boolean)) { | ||
const self = this; | ||
if (typeof handler === 'string') { | ||
// 如果 handler 是字符串,则认为是这个微件上的一个方法名 | ||
this.eventListeners[type] = function(event) { | ||
return self[handler].call(self, event); | ||
}; | ||
} else { | ||
// 如果 handler 是函数,则直接作为事件处理函数 | ||
this.eventListeners[type] = function(event) { | ||
return handler.call(self, event); | ||
}; | ||
} | ||
} | ||
|
||
// 向微件派发事件 | ||
dispatchEvent(event: any) { | ||
event.widget = event.widget || this; | ||
// 如果这个微件处理了这个事件,则派发它 | ||
const listener = this.eventListeners[event.type]; | ||
if (listener) { | ||
// 如果监听器返回 false,则不再向上传播事件 | ||
if (!listener(event)) { | ||
return false; | ||
} | ||
} | ||
// 否则,将事件派发给父级微件 | ||
if (this.parentWidget) { | ||
return this.parentWidget.dispatchEvent(event); | ||
} | ||
return true; | ||
} | ||
|
||
// 其他类方法 | ||
} | ||
``` | ||
|
||
使用方法 | ||
|
||
```ts | ||
class MyWidget extends Widget { | ||
constructor(parseTreeNode: any, options: any) { | ||
super(parseTreeNode, options); | ||
// 用法一:为 'myCustomEvent' 事件注册监听器 | ||
// 注意这只能捕获子微件,也就是被包在当前微件里的其它微件 | ||
this.addEventListener('myCustomEvent', this.handleMyCustomEvent); | ||
|
||
// 用法二:在根微件上注册监听器,这可以捕获任何地方发送的消息 | ||
$tw.rootWidget.addEventListener("tm-scroll",function(event) { | ||
$tw.pageScroller.handleEvent(event); | ||
}); | ||
} | ||
|
||
// 定义一个方法来处理事件 | ||
handleMyCustomEvent(event: any): boolean { | ||
console.log('接收到事件:', event); | ||
// 返回 false 停止事件传播 | ||
return false; | ||
} | ||
|
||
// 在微件的某个地方触发事件 | ||
someMethod() { | ||
// 方法一:在自己身上发,然后让它逐级冒泡上去 | ||
this.dispatchEvent({ type: 'myCustomEvent', data: '一些数据' }); | ||
|
||
// 方法二:直接发到根微件上 | ||
$tw.rootWidget.dispatchEvent({type: "tm-auto-save-wiki"}); | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.