svelte5ダイナミックコンポーネントを使ったテーマ変更 の変更点

更新


#author("2024-09-13T08:49:45+00:00","default:administrator","administrator")
[[プログラミング/svelte]]

* svelte5 ではコンポーネント名を動的に決められるのだそうです [#d531f8a2]

通常であれば

 LANG:html
 <Component>Hello!</Component>

と書くところを、

 LANG:html
 <theme.Component>Hello!</theme.Component>

と書ける。

~

そこで、theme にいろいろなコンポーネントを持たせておいて、
動的にその中身を差し替えることでテーマを変更することが可能になる。

 LANG:ts
   const defaultTheme = {Component: DefaultComponent};
   const alternativeTheme = {Component: AlternativeComponent} satisfies Theme;
   let theme = $derived(sw ? defaultTheme : alternativeTheme);

としておくと、

 LANG:html
 <theme.Component />

と書いた部分を DefaultComponent と AlternativeComponent の間で動的に切り替えられるわけです。

~

こちらで試せます:
[[https://svelte-5-preview.vercel.app/...>https://svelte-5-preview.vercel.app/#H4sIAAAAAAAACoVTXWvjMBD8K1tRaAolfncdF9OmUCh9OHz3cj6oYq8TUVsy0iYlBP_3W8XORx3TvmlnNbOzq9VOlKpCJ8K_O6FljSIUSdOIO0HbxgdugxUhx86sbe6RyOVWNQSV1MtZJshlIs50RqpujCV4wlKuK3o0HGrUBKU1NdxMg2Fi2knf3J-REwaslqQ2eCkwljwXYZkggKIrA7TCGj2WG-3oAKcehRnsjgrhheN278j3D4frPjDlF5FTRSZ11aCWW-ByJJXms_ZBr-l-8idPzY15HOu9BceAKxU6GFh6H2TeQS7MBr25UtnaAcp8dXIH7HdooFdSbn-N8UWF8Klo5Z0zZi06Zhc93YPn45kevXSjyaWGBXJdp6otOBbKV1j4KxUSx9zvtSNJOCG7xtv7Q4b6YVwXaNlaMeGrD19fM7zw7ulR0O2p300dLdZERvNT5ZXKP2a7ye0s7qpeuc92v7-pWS6r_sk9vaN09L2L6XHycRQMkUzzH6lNoXjohQh9E-3d8UsNV-zb_9XET_Pn5PdrGgVN_J3q2FL8oJy8pvNfb0n68mc-rv6v_Q-4dq2dEgQAAA==]]

 LANG:html
 <script lang="ts">
 	import DefaultComponent from './DefaultComponent.svelte';
 	import AlternativeComponent from './AlternativeComponent.svelte';
 
 	// default theme
 	const defaultTheme = {Component: DefaultComponent};
 	type Theme = typeof defaultTheme;
 
 	// one theme may contain many components
 
 	// default theme
 	const alternativeTheme = {Component: AlternativeComponent} satisfies Theme;
 
 	// `satisfies Theme` above confirms each component in alternativeTheme
 	// is compatible with the correspondent in the defaultTheme.
 
 	// theme can be easily switched
 	let sw = $state(true);
 	let theme = $derived(sw ? defaultTheme : alternativeTheme);
 </script>
 
 <button onclick={()=> sw = !sw}>
 	Tollge Theme
 </button>
 
 <theme.Component></theme.Component>

DefaultComponent.svelte
 LANG:html
 <p>DEFAULT</p>

AlternativeComponent.svelte
 LANG:html
 <p>ALTERNATIVE</p>

とても便利!

* これをコンポーネント化する際には気を付けないといけないのかもしれません? [#ua702a99]

発生理由をちゃんと把握できていないのですが、全体を npm コンポーネントにして他のプロジェクトで使おうとした場合、

 <theme.Component>

という書き方をしているとうまく展開されない場合があるのかもしれません?

   const { Component } = theme;
 </script>
 
 <Component>

のような書き方の方が無難かもしれない???

他のいろんなエラーと重なったりで未検証ですがメモとして残しておきます。

* svelte コンポーネントを npm パッケージにする際の vite の設定 [#h79e8c92]

https://github.com/sveltejs/svelte/discussions/11376#discussioncomment-9262171 にあるように、

vite.config.ts に
  optimizeDeps: {
    exclude: ['svelte'],
  },

を加えないと

 Error: onMount can only be used during component initialisation.

のようなエラーで表示が止まることがあるようでした。



Counter: 999 (from 2010/06/03), today: 1, yesterday: 3