[{"data":1,"prerenderedAt":992},["ShallowReactive",2],{"content-/multiplication-slideshow-vue":3,"all-pages-for-dir":990,"og-image-/multiplication-slideshow-vue":991},{"id":4,"title":5,"body":6,"category":971,"description":972,"extension":973,"meta":974,"navigation":975,"ogImage":976,"path":977,"project_name":978,"published":979,"publishedAt":980,"seo":981,"stem":982,"tags":983,"todo":988,"unpublished":979,"updatedAt":976,"__hash__":989},"pages/2026-03/2026-03-22/multiplication-slideshow-vue.md","React TSXの掛け算スライドショーをVue.jsに移植した記録",{"type":7,"value":8,"toc":959},"minimark",[9,13,17,21,24,36,184,190,194,197,201,208,211,226,229,239,348,357,361,366,466,476,479,483,497,793,796,851,872,876,883,912,921,924,931,934,942,956],[10,11,5],"h1",{"id":12},"react-tsxの掛け算スライドショーをvuejsに移植した記録",[14,15,16],"p",{},"React TSXで書かれた掛け算の面積図スライドショーを、Nuxt 3のVueページとして動かすところまで持っていった。数値の入力からスライド遷移、P3ピースの回転アニメーションまで一通り移植が完了している。途中、CSSトランジションが効かない問題に2時間ほど手を止められた。",[18,19,20],"h2",{"id":20},"移植の方針",[14,22,23],{},"元のコンポーネントはReact + Tailwind CSSで構成されていた。移植先のmdx-playgroundではTailwindを使っていないため、scoped CSSで書き直す方針を採った。",[14,25,26,27,31,32,35],{},"Nuxt 3のカスタムVueページとして ",[28,29,30],"code",{},"apps/web/app/pages/multiplication-slideshow.vue"," に配置し、",[28,33,34],{},"definePageMeta"," でメタ情報を設定した。",[37,38,43],"pre",{"className":39,"code":40,"language":41,"meta":42,"style":42},"language-vue shiki shiki-themes vitesse-light vitesse-light","\u003Cscript setup lang=\"ts\">\ndefinePageMeta({\n  title: '十の位が1の2桁×2桁 速算スライドショー',\n  publishedAt: '2026-03-22',\n  tags: ['education', 'math'],\n  includeInList: true\n})\n\u003C/script>\n","vue","",[28,44,45,81,90,111,128,157,168,174],{"__ignoreMap":42},[46,47,50,54,58,62,65,68,72,76,78],"span",{"class":48,"line":49},"line",1,[46,51,53],{"class":52},"shFtX","\u003C",[46,55,57],{"class":56},"sHkkW","script",[46,59,61],{"class":60},"s4oTP"," setup",[46,63,64],{"class":60}," lang",[46,66,67],{"class":52},"=",[46,69,71],{"class":70},"sMJiu","\"",[46,73,75],{"class":74},"sdGka","ts",[46,77,71],{"class":70},[46,79,80],{"class":52},">\n",[46,82,84,87],{"class":48,"line":83},2,[46,85,34],{"class":86},"senZ8",[46,88,89],{"class":52},"({\n",[46,91,93,97,100,103,106,108],{"class":48,"line":92},3,[46,94,96],{"class":95},"sz8Xr","  title",[46,98,99],{"class":52},": ",[46,101,102],{"class":70},"'",[46,104,105],{"class":74},"十の位が1の2桁×2桁 速算スライドショー",[46,107,102],{"class":70},[46,109,110],{"class":52},",\n",[46,112,114,117,119,121,124,126],{"class":48,"line":113},4,[46,115,116],{"class":95},"  publishedAt",[46,118,99],{"class":52},[46,120,102],{"class":70},[46,122,123],{"class":74},"2026-03-22",[46,125,102],{"class":70},[46,127,110],{"class":52},[46,129,131,134,137,139,142,144,147,149,152,154],{"class":48,"line":130},5,[46,132,133],{"class":95},"  tags",[46,135,136],{"class":52},": [",[46,138,102],{"class":70},[46,140,141],{"class":74},"education",[46,143,102],{"class":70},[46,145,146],{"class":52},", ",[46,148,102],{"class":70},[46,150,151],{"class":74},"math",[46,153,102],{"class":70},[46,155,156],{"class":52},"],\n",[46,158,160,163,165],{"class":48,"line":159},6,[46,161,162],{"class":95},"  includeInList",[46,164,99],{"class":52},[46,166,167],{"class":56},"true\n",[46,169,171],{"class":48,"line":170},7,[46,172,173],{"class":52},"})\n",[46,175,177,180,182],{"class":48,"line":176},8,[46,178,179],{"class":52},"\u003C/",[46,181,57],{"class":56},[46,183,80],{"class":52},[14,185,186,189],{},[28,187,188],{},"includeInList: true"," を指定することで、トップページの記事一覧にも表示される。",[18,191,193],{"id":192},"cssトランジションが動かない","CSSトランジションが動かない",[14,195,196],{},"移植自体はスムーズに進んだが、P3ピースの回転アニメーションで壁にぶつかった。",[198,199,200],"h3",{"id":200},"症状",[14,202,203,204,207],{},"スライドを切り替えると、P3ピースが回転アニメーションなしで一瞬で位置が変わる。他のピース（P1, P2, P4）は ",[28,205,206],{},"transition: all 0.7s ease-in-out"," で滑らかに移動するのに、P3だけ瞬間移動する。",[198,209,210],{"id":210},"原因を追う",[14,212,213,214,217,218,221,222,225],{},"最初はCSSの書き方を疑った。",[28,215,216],{},"transform: rotate(90deg)"," をインラインスタイルで当てているので、",[28,219,220],{},"transition"," プロパティに ",[28,223,224],{},"transform"," が含まれているか確認した。含まれている。",[14,227,228],{},"次に、Vue DevToolsでDOM要素の再生成が起きていないか確認した。ここで原因が見えた。",[14,230,231,234,235,238],{},[28,232,233],{},"v-for"," のキーに ",[28,236,237],{},"currentSlide"," を含めていた。",[37,240,242],{"className":39,"code":241,"language":41,"meta":42,"style":42},"\u003C!-- NG: スライドが変わるたびにDOM要素が再生成される -->\n\u003Cdiv\n  v-for=\"(piece, index) in pieces\"\n  :key=\"`piece-${index}-${currentSlide}`\"\n  class=\"piece\"\n>\n",[28,243,244,250,257,291,331,344],{"__ignoreMap":42},[46,245,246],{"class":48,"line":49},[46,247,249],{"class":248},"sxvE3","\u003C!-- NG: スライドが変わるたびにDOM要素が再生成される -->\n",[46,251,252,254],{"class":48,"line":83},[46,253,53],{"class":52},[46,255,256],{"class":56},"div\n",[46,258,259,262,264,266,269,272,275,278,281,285,288],{"class":48,"line":92},[46,260,261],{"class":56},"  v-for",[46,263,67],{"class":52},[46,265,71],{"class":52},[46,267,268],{"class":52},"(",[46,270,271],{"class":60},"piece",[46,273,274],{"class":52},",",[46,276,277],{"class":60}," index",[46,279,280],{"class":52},")",[46,282,284],{"class":283},"stQ0i"," in",[46,286,287],{"class":60}," pieces",[46,289,290],{"class":52},"\"\n",[46,292,293,296,299,301,303,306,309,312,315,318,321,323,325,327,329],{"class":48,"line":113},[46,294,295],{"class":52},"  :",[46,297,298],{"class":86},"key",[46,300,67],{"class":52},[46,302,71],{"class":52},[46,304,305],{"class":70},"`",[46,307,308],{"class":74},"piece-",[46,310,311],{"class":56},"${",[46,313,314],{"class":74},"index",[46,316,317],{"class":56},"}",[46,319,320],{"class":74},"-",[46,322,311],{"class":56},[46,324,237],{"class":74},[46,326,317],{"class":56},[46,328,305],{"class":70},[46,330,290],{"class":52},[46,332,333,336,338,340,342],{"class":48,"line":130},[46,334,335],{"class":60},"  class",[46,337,67],{"class":52},[46,339,71],{"class":70},[46,341,271],{"class":74},[46,343,290],{"class":70},[46,345,346],{"class":48,"line":159},[46,347,80],{"class":52},[14,349,350,353,354,356],{},[28,351,352],{},":key"," に ",[28,355,237],{}," が入っているので、スライドを切り替えるたびにVueはDOM要素を破棄して新しく作り直す。新しいDOM要素には前の状態がないから、CSSトランジションの「from」が存在しない。結果、アニメーションなしで最終状態がいきなり描画される。",[198,358,360],{"id":359},"解決-安定したキーに変更","解決: 安定したキーに変更",[14,362,363,365],{},[28,364,352],{}," をピース固有のIDに変更した。",[37,367,369],{"className":39,"code":368,"language":41,"meta":42,"style":42},"\u003C!-- OK: DOM要素が再利用され、CSSトランジションが効く -->\n\u003Cdiv\n  v-for=\"(meta, index) in piecesMeta\"\n  :key=\"meta.id\"\n  class=\"piece\"\n  :style=\"getPieceStyle(index)\"\n>\n",[28,370,371,376,382,408,428,440,462],{"__ignoreMap":42},[46,372,373],{"class":48,"line":49},[46,374,375],{"class":248},"\u003C!-- OK: DOM要素が再利用され、CSSトランジションが効く -->\n",[46,377,378,380],{"class":48,"line":83},[46,379,53],{"class":52},[46,381,256],{"class":56},[46,383,384,386,388,390,392,395,397,399,401,403,406],{"class":48,"line":92},[46,385,261],{"class":56},[46,387,67],{"class":52},[46,389,71],{"class":52},[46,391,268],{"class":52},[46,393,394],{"class":60},"meta",[46,396,274],{"class":52},[46,398,277],{"class":60},[46,400,280],{"class":52},[46,402,284],{"class":283},[46,404,405],{"class":60}," piecesMeta",[46,407,290],{"class":52},[46,409,410,412,414,416,418,420,423,426],{"class":48,"line":113},[46,411,295],{"class":52},[46,413,298],{"class":86},[46,415,67],{"class":52},[46,417,71],{"class":52},[46,419,394],{"class":60},[46,421,422],{"class":52},".",[46,424,425],{"class":60},"id",[46,427,290],{"class":52},[46,429,430,432,434,436,438],{"class":48,"line":130},[46,431,335],{"class":60},[46,433,67],{"class":52},[46,435,71],{"class":70},[46,437,271],{"class":74},[46,439,290],{"class":70},[46,441,442,444,447,449,451,454,456,458,460],{"class":48,"line":159},[46,443,295],{"class":52},[46,445,446],{"class":86},"style",[46,448,67],{"class":52},[46,450,71],{"class":52},[46,452,453],{"class":86},"getPieceStyle",[46,455,268],{"class":52},[46,457,314],{"class":60},[46,459,280],{"class":52},[46,461,290],{"class":52},[46,463,464],{"class":48,"line":170},[46,465,80],{"class":52},[14,467,468,471,472,475],{},[28,469,470],{},"piecesMeta"," はスライドによらない静的な情報（ID、色、ラベル）を持つ配列で、キーが変わらないのでDOM要素が再利用される。スタイルの変更はリアクティブな ",[28,473,474],{},"computed"," で計算し、CSSトランジションが補間してくれる。",[14,477,478],{},"この変更を入れた瞬間、P3ピースが90度回転しながら移動するアニメーションが動いた。",[18,480,482],{"id":481},"p3回転の実装構造","P3回転の実装構造",[14,484,485,486,489,490,493,494,496],{},"P3ピースは初期配置では ",[28,487,488],{},"a x 10"," の縦長だが、並び替え後は ",[28,491,492],{},"10 x a"," の横長として上部グループに組み込まれる。CSS ",[28,495,216],{}," で見た目の回転を実現し、内部テキストは逆回転で正立を保つ。",[37,498,502],{"className":499,"code":500,"language":501,"meta":42,"style":42},"language-typescript shiki shiki-themes vitesse-light vitesse-light","// ピースのスタイル計算（P3は回転あり）\nconst getPieceStyle = (index: number) => {\n  const style: Record\u003Cstring, string> = {\n    left: `${positions.value[index].x}px`,\n    top: `${positions.value[index].y}px`,\n    width: `${pieceWidths.value[index] * SCALE}px`,\n    height: `${pieceHeights.value[index] * SCALE}px`\n  }\n  if (index === 2 && currentSlide.value >= 1) {\n    style.transform = 'rotate(90deg)'\n  }\n  return style\n}\n","typescript",[28,503,504,509,538,564,603,637,676,711,716,752,773,778,787],{"__ignoreMap":42},[46,505,506],{"class":48,"line":49},[46,507,508],{"class":248},"// ピースのスタイル計算（P3は回転あり）\n",[46,510,511,514,516,519,522,524,526,530,532,535],{"class":48,"line":83},[46,512,513],{"class":283},"const ",[46,515,453],{"class":86},[46,517,518],{"class":52}," =",[46,520,521],{"class":52}," (",[46,523,314],{"class":60},[46,525,99],{"class":52},[46,527,529],{"class":528},"sSkh3","number",[46,531,280],{"class":52},[46,533,534],{"class":52}," =>",[46,536,537],{"class":52}," {\n",[46,539,540,543,545,547,550,552,555,557,559,562],{"class":48,"line":92},[46,541,542],{"class":283},"  const ",[46,544,446],{"class":60},[46,546,99],{"class":52},[46,548,549],{"class":528},"Record",[46,551,53],{"class":52},[46,553,554],{"class":528},"string",[46,556,146],{"class":52},[46,558,554],{"class":528},[46,560,561],{"class":52},"> =",[46,563,537],{"class":52},[46,565,566,569,571,573,575,578,580,583,586,588,591,594,596,599,601],{"class":48,"line":113},[46,567,568],{"class":95},"    left",[46,570,99],{"class":52},[46,572,305],{"class":70},[46,574,311],{"class":56},[46,576,577],{"class":74},"positions",[46,579,422],{"class":52},[46,581,582],{"class":74},"value",[46,584,585],{"class":52},"[",[46,587,314],{"class":74},[46,589,590],{"class":52},"].",[46,592,593],{"class":74},"x",[46,595,317],{"class":56},[46,597,598],{"class":74},"px",[46,600,305],{"class":70},[46,602,110],{"class":52},[46,604,605,608,610,612,614,616,618,620,622,624,626,629,631,633,635],{"class":48,"line":130},[46,606,607],{"class":95},"    top",[46,609,99],{"class":52},[46,611,305],{"class":70},[46,613,311],{"class":56},[46,615,577],{"class":74},[46,617,422],{"class":52},[46,619,582],{"class":74},[46,621,585],{"class":52},[46,623,314],{"class":74},[46,625,590],{"class":52},[46,627,628],{"class":74},"y",[46,630,317],{"class":56},[46,632,598],{"class":74},[46,634,305],{"class":70},[46,636,110],{"class":52},[46,638,639,642,644,646,648,651,653,655,657,659,662,665,668,670,672,674],{"class":48,"line":159},[46,640,641],{"class":95},"    width",[46,643,99],{"class":52},[46,645,305],{"class":70},[46,647,311],{"class":56},[46,649,650],{"class":74},"pieceWidths",[46,652,422],{"class":52},[46,654,582],{"class":74},[46,656,585],{"class":52},[46,658,314],{"class":74},[46,660,661],{"class":52},"]",[46,663,664],{"class":283}," *",[46,666,667],{"class":74}," SCALE",[46,669,317],{"class":56},[46,671,598],{"class":74},[46,673,305],{"class":70},[46,675,110],{"class":52},[46,677,678,681,683,685,687,690,692,694,696,698,700,702,704,706,708],{"class":48,"line":170},[46,679,680],{"class":95},"    height",[46,682,99],{"class":52},[46,684,305],{"class":70},[46,686,311],{"class":56},[46,688,689],{"class":74},"pieceHeights",[46,691,422],{"class":52},[46,693,582],{"class":74},[46,695,585],{"class":52},[46,697,314],{"class":74},[46,699,661],{"class":52},[46,701,664],{"class":283},[46,703,667],{"class":74},[46,705,317],{"class":56},[46,707,598],{"class":74},[46,709,710],{"class":70},"`\n",[46,712,713],{"class":48,"line":176},[46,714,715],{"class":52},"  }\n",[46,717,719,722,724,726,729,733,736,738,740,742,745,748,750],{"class":48,"line":718},9,[46,720,721],{"class":56},"  if",[46,723,521],{"class":52},[46,725,314],{"class":60},[46,727,728],{"class":283}," === ",[46,730,732],{"class":731},"sM54T","2",[46,734,735],{"class":283}," && ",[46,737,237],{"class":60},[46,739,422],{"class":52},[46,741,582],{"class":60},[46,743,744],{"class":52}," >=",[46,746,747],{"class":731}," 1",[46,749,280],{"class":52},[46,751,537],{"class":52},[46,753,755,758,760,762,764,767,770],{"class":48,"line":754},10,[46,756,757],{"class":60},"    style",[46,759,422],{"class":52},[46,761,224],{"class":60},[46,763,518],{"class":52},[46,765,766],{"class":70}," '",[46,768,769],{"class":74},"rotate(90deg)",[46,771,772],{"class":70},"'\n",[46,774,776],{"class":48,"line":775},11,[46,777,715],{"class":52},[46,779,781,784],{"class":48,"line":780},12,[46,782,783],{"class":56},"  return",[46,785,786],{"class":60}," style\n",[46,788,790],{"class":48,"line":789},13,[46,791,792],{"class":52},"}\n",[14,794,795],{},"CSSは1行だけ。",[37,797,801],{"className":798,"code":799,"language":800,"meta":42,"style":42},"language-css shiki shiki-themes vitesse-light vitesse-light",".piece {\n  position: absolute;\n  transition: all 0.7s ease-in-out;\n}\n","css",[28,802,803,811,826,847],{"__ignoreMap":42},[46,804,805,807,809],{"class":48,"line":49},[46,806,422],{"class":52},[46,808,271],{"class":60},[46,810,537],{"class":52},[46,812,813,816,819,823],{"class":48,"line":83},[46,814,815],{"class":95},"  position",[46,817,818],{"class":52},":",[46,820,822],{"class":821},"snbK4"," absolute",[46,824,825],{"class":52},";\n",[46,827,828,831,833,836,839,842,845],{"class":48,"line":92},[46,829,830],{"class":95},"  transition",[46,832,818],{"class":52},[46,834,835],{"class":821}," all",[46,837,838],{"class":731}," 0.7",[46,840,841],{"class":283},"s",[46,843,844],{"class":821}," ease-in-out",[46,846,825],{"class":52},[46,848,849],{"class":48,"line":113},[46,850,792],{"class":52},[14,852,853,856,857,146,860,146,863,146,866,146,869,871],{},[28,854,855],{},"transition: all"," が ",[28,858,859],{},"left",[28,861,862],{},"top",[28,864,865],{},"width",[28,867,868],{},"height",[28,870,224],{}," をすべて補間するので、位置移動と回転が同時に滑らかに動く。",[18,873,875],{"id":874},"worktree環境でのpnpm-install問題","worktree環境でのpnpm install問題",[14,877,878,879,882],{},"今回の作業はworktreeブランチで進めていた。devコンテナ内で ",[28,880,881],{},"pnpm dev"," を実行しようとしたところ、2つの問題が発生した。",[884,885,886,898],"ol",{},[887,888,889,893,894,897],"li",{},[890,891,892],"strong",{},"pnpmが見つからない",": devコンテナのPATHにpnpmが含まれていなかった。",[28,895,896],{},"npm install -g pnpm"," で解決",[887,899,900,903,904,907,908,911],{},[890,901,902],{},"node_modulesの権限混在",": ホスト側（vscodeユーザー）とコンテナ側（rootユーザー）で作成されたファイルが混在し、パーミッションエラーが出た。",[28,905,906],{},"node_modules"," を削除して ",[28,909,910],{},"pnpm install"," をやり直して解決",[14,913,914,915,917,918,920],{},"worktreeで新しいブランチを切った場合、",[28,916,906],{}," は共有されないので ",[28,919,910],{}," が毎回必要になる。この注意事項をCLAUDE.mdにも追記した。",[18,922,923],{"id":923},"トップページへのリンク追加",[14,925,926,927,930],{},"移植が完了した後、トップページの「学習・クイズ」セクションにスライドショーへのリンクを追加した。",[28,928,929],{},"/multiplication-slideshow"," で直接アクセスできる。",[18,932,933],{"id":933},"振り返り",[14,935,936,938,939,941],{},[28,937,352],{}," の設計ミスでCSSトランジションが無効化されるパターンは、Reactの ",[28,940,298],{}," propでも同じことが起きる。「アニメーションさせたいならDOM要素を再生成しない」という原則は、フレームワークを問わず共通している。",[14,943,944,945,948,949,952,953,955],{},"今回の移植でReactとVueの差異を改めて体感した。Reactでは ",[28,946,947],{},"useState"," + JSXで書いていた部分が、Vueでは ",[28,950,951],{},"ref"," + ",[28,954,474],{}," + テンプレートに分かれる。ロジックの分離という点ではVueの方が構造が見えやすいと感じた。一方でJSXの自由度が恋しくなる場面もあり、どちらが良いとは言い切れない。",[446,957,958],{},"html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .sSkh3, html code.shiki .sSkh3{--shiki-default:#2E8F82;--shiki-dark:#2E8F82}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}",{"title":42,"searchDepth":83,"depth":83,"links":960},[961,962,967,968,969,970],{"id":20,"depth":83,"text":20},{"id":192,"depth":83,"text":193,"children":963},[964,965,966],{"id":200,"depth":92,"text":200},{"id":210,"depth":92,"text":210},{"id":359,"depth":92,"text":360},{"id":481,"depth":83,"text":482},{"id":874,"depth":83,"text":875},{"id":923,"depth":83,"text":923},{"id":933,"depth":83,"text":933},"dev","React TSX製の面積図アニメーションスライドショーをNuxt 3のVueページに変換。CSSトランジションの:key問題やworktree環境でのpnpm問題を解決した過程を記録。","md",{},true,null,"/multiplication-slideshow-vue","mdx-playground",false,"2026-03-22T00:00:00.000Z",{"title":5,"description":972},"2026-03/2026-03-22/multiplication-slideshow-vue",[41,984,985,986,987],"nuxt3","css-transition","animation","react-migration","memo","nagFuO9fvvg8xV_wjA3Yf3X1sMKU2EXS7eq52hZ2Hpg",[],"https://log.eurekapu.com/og/blog/multiplication-slideshow-vue.png?v=2026-03-22T00%3A00%3A00.000Z&title=React%20TSX%E3%81%AE%E6%8E%9B%E3%81%91%E7%AE%97%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E3%82%B7%E3%83%A7%E3%83%BC%E3%82%92Vue.js%E3%81%AB%E7%A7%BB%E6%A4%8D%E3%81%97%E3%81%9F%E8%A8%98%E9%8C%B2&author=Kei%20Komatsu&sig=a83b49d21f796890",1782528819914]