-
Notifications
You must be signed in to change notification settings - Fork 142
docs: add a guide for using Components
#204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| temporarilyUnloadWidget() { | ||
| // You can also unload it temporarily if needed | ||
| this.widget.unload(); | ||
| window.setTimeout(() => this.widget.load(), 5000); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is a good example for plugins. Usually Components should not be calling load/unload themselves. If they are properly attached to a parent, then the parent Component is responsible for loading and unloading
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed this example for now. The main idea behind this is that you can fully unload and re-load the component, and everything will be handled properly.
| window.addEventListener("resize", onResize); | ||
| } | ||
|
|
||
| onunload() { | ||
| window.removeEventListener("resize", onResize); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example is awkward since onResize is undefined and its very easy to mess up removeEventListener (if you don't pass in the exact instance, it won't be properly removed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if there is a different, but still simple, example that can be used for this. For now, I have changed the example such that onResize is a method on the class.
| } | ||
| ``` | ||
|
|
||
| While this works, it quickly becomes repetitive and error-prone. Fortunately, Obsidian's `Component` system offers a better solution. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems a little awkward since the example with onload and onunload is already using functions of Component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for the purposes of this example, that is fine. The main point to demonstrate here is that explicitly registering something to the Component is safer, rather than handling the loading/unloading yourself (be it in a Plugin, a custom class that you manage the lifecycle of, etc...). The Plugin just happens to be the most well known construction for this 😅
What do you think of:
While this works fine, you need to remember to remove your listener in the
onunloadcall. Obsidian fortunately offers a better and simpler methods to register events via theComponentsystem:
| createEl("button", { text: "Click me!" }) | ||
| ); | ||
| // Good | ||
| button.addEventListener("click", onButtonClick); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Obsidian native approach for these would be:
new ButtonComponent(this.containerEl).setButtonText('Click me!').onClick(() => {
new Notice('Button clicked!');
});
// keyboard events
this.scope = new Scope(this.app.scope); //this does not need to be unloaded, Obsidian takes care of it
this.scope.register(['Ctrl'], 's', () => {
new Notice('Shortcut pressed!');
})There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intentionally chose this construction with button and window to showcase the parallels for registering listeners, and the difference in how long these listeners would live for.
Do you think this should be added as a separate example? Or maybe as an additional note clarifying that there is a more correct implementation available using Obsidian API's.
This is a preliminary PR for adding a guide on how to use the
Componentclass for managing lifecycles and events.This guide aims to give developers a tool to avoid common mistakes made during plugin development, including:
window,document,view, ..., but not removing them up when the plugin/view/... is unloadedComponentfor aMarkdownRenderer.rendercall, but never attaching it to a parentComponentAny input would be very welcome: