[{"data":1,"prerenderedAt":1911},["ShallowReactive",2],{"i-mdi:close":3,"i-bx:menu":8,"i-ph:translate":10,"i-flag:br-4x3":13,"i-flag:us-4x3":17,"post-learning-tea":19},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z\"/>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"currentColor\" d=\"M4 6h16v2H4zm0 5h16v2H4zm0 5h16v2H4z\"/>",{"left":4,"top":4,"width":11,"height":11,"rotate":4,"vFlip":6,"hFlip":6,"body":12},256,"\u003Cpath fill=\"currentColor\" d=\"m247.15 212.42l-56-112a8 8 0 0 0-14.31 0l-21.71 43.43A88 88 0 0 1 108 126.93A103.65 103.65 0 0 0 135.69 64H160a8 8 0 0 0 0-16h-56V32a8 8 0 0 0-16 0v16H32a8 8 0 0 0 0 16h87.63A87.76 87.76 0 0 1 96 116.35a87.7 87.7 0 0 1-19-31a8 8 0 1 0-15.08 5.34A103.6 103.6 0 0 0 84 127a87.55 87.55 0 0 1-52 17a8 8 0 0 0 0 16a103.46 103.46 0 0 0 64-22.08a104.2 104.2 0 0 0 51.44 21.31l-26.6 53.19a8 8 0 0 0 14.31 7.16L148.94 192h70.11l13.79 27.58A8 8 0 0 0 240 224a8 8 0 0 0 7.15-11.58M156.94 176L184 121.89L211.05 176Z\"/>",{"left":4,"top":4,"width":14,"height":15,"rotate":4,"vFlip":6,"hFlip":6,"body":16},640,480,"\u003Cg stroke-width=\"1pt\">\u003Cpath fill=\"#229e45\" fill-rule=\"evenodd\" d=\"M0 0h640v480H0z\"/>\u003Cpath fill=\"#f8e509\" fill-rule=\"evenodd\" d=\"m321.4 436l301.5-195.7L319.6 44L17.1 240.7z\"/>\u003Cpath fill=\"#2b49a3\" fill-rule=\"evenodd\" d=\"M452.8 240c0 70.3-57.1 127.3-127.6 127.3A127.4 127.4 0 1 1 452.8 240\"/>\u003Cpath fill=\"#ffffef\" fill-rule=\"evenodd\" d=\"m283.3 316.3l-4-2.3l-4 2l.9-4.5l-3.2-3.4l4.5-.5l2.2-4l1.9 4.2l4.4.8l-3.3 3m86 26.3l-3.9-2.3l-4 2l.8-4.5l-3.1-3.3l4.5-.5l2.1-4.1l2 4.2l4.4.8l-3.4 3.1m-36.2-30l-3.4-2l-3.5 1.8l.8-3.9l-2.8-2.9l4-.4l1.8-3.6l1.6 3.7l3.9.7l-3 2.7m87-8.5l-3.4-2l-3.5 1.8l.8-3.9l-2.7-2.8l3.9-.4l1.8-3.5l1.6 3.6l3.8.7l-2.9 2.6m-87.3-22l-4-2.2l-4 2l.8-4.6l-3.1-3.3l4.5-.5l2.1-4.1l2 4.2l4.4.8l-3.4 3.2m-104.6-35l-4-2.2l-4 2l1-4.6l-3.3-3.3l4.6-.5l2-4.1l2 4.2l4.4.8l-3.3 3.1m13.3 57.2l-4-2.3l-4 2l.9-4.5l-3.2-3.3l4.5-.6l2.1-4l2 4.2l4.4.8l-3.3 3.1m132-67.3l-3.6-2l-3.6 1.8l.8-4l-2.8-3l4-.5l1.9-3.6l1.7 3.8l4 .7l-3 2.7m-6.7 38.3l-2.7-1.6l-2.9 1.4l.6-3.2l-2.2-2.3l3.2-.4l1.5-2.8l1.3 3l3 .5l-2.2 2.2m-142.2 50.4l-2.7-1.5l-2.7 1.3l.6-3l-2.1-2.2l3-.4l1.4-2.7l1.3 2.8l3 .6l-2.3 2M419 299.8l-2.2-1.1l-2.2 1l.5-2.3l-1.7-1.6l2.4-.3l1.2-2l1 2l2.5.5l-1.9 1.5\"/>\u003Cpath fill=\"#ffffef\" fill-rule=\"evenodd\" d=\"m219.3 287.6l-2.7-1.5l-2.7 1.3l.6-3l-2.1-2.2l3-.4l1.4-2.7l1.3 2.8l3 .6l-2.3 2\"/>\u003Cpath fill=\"#ffffef\" fill-rule=\"evenodd\" d=\"m219.3 287.6l-2.7-1.5l-2.7 1.3l.6-3l-2.1-2.2l3-.4l1.4-2.7l1.3 2.8l3 .6l-2.3 2m42.3 3l-2.6-1.4l-2.7 1.3l.6-3l-2.1-2.2l3-.4l1.4-2.7l1.3 2.8l3 .5l-2.3 2.1m-4.8 17l-2.6-1.5l-2.7 1.4l.6-3l-2.1-2.3l3-.4l1.4-2.7l1.3 2.8l3 .6l-2.3 2m87.4-22.2l-2.6-1.6l-2.8 1.4l.6-3l-2-2.3l3-.3l1.4-2.7l1.2 2.8l3 .5l-2.2 2.1m-25.1 3l-2.7-1.5l-2.7 1.4l.6-3l-2-2.3l3-.3l1.4-2.8l1.2 2.9l3 .5l-2.2 2.1m-68.8-5.8l-1.7-1l-1.7.8l.4-1.9l-1.3-1.4l1.9-.2l.8-1.7l.8 1.8l1.9.3l-1.4 1.3m167.8 45.4l-2.6-1.5l-2.7 1.4l.6-3l-2.1-2.3l3-.4l1.4-2.7l1.3 2.8l3 .6l-2.3 2m-20.8 6l-2.2-1.4l-2.3 1.2l.5-2.6l-1.7-1.8l2.5-.3l1.2-2.3l1 2.4l2.5.4l-1.9 1.8m10.4 2.3l-2-1.2l-2.1 1l.4-2.3l-1.6-1.7l2.3-.3l1.1-2l1 2l2.3.5l-1.7 1.6m29.1-22.8l-2-1l-2 1l.5-2.3l-1.6-1.7l2.3-.3l1-2l1 2.1l2.1.4l-1.6 1.6m-38.8 41.8l-2.5-1.4l-2.7 1.2l.6-2.8l-2-2l3-.3l1.3-2.5l1.2 2.6l3 .5l-2.3 1.9m.6 14.2l-2.4-1.4l-2.4 1.3l.6-2.8l-1.9-2l2.7-.4l1.2-2.5l1.1 2.6l2.7.5l-2 2m-19-23.1l-1.9-1.2l-2 1l.4-2.2l-1.5-1.7l2.2-.2l1-2l1 2l2.2.4l-1.6 1.6m-17.8 2.3l-2-1.2l-2 1l.5-2.2l-1.6-1.7l2.3-.2l1-2l1 2l2.1.4l-1.6 1.6m-30.4-24.6l-2-1.1l-2 1l.5-2.3l-1.6-1.6l2.2-.3l1-2l1 2l2.2.5l-1.6 1.5m3.7 57l-1.6-.9l-1.8.9l.4-2l-1.3-1.4l1.9-.2l.9-1.7l.8 1.8l1.9.3l-1.4 1.3m-46.2-86.6l-4-2.3l-4 2l.9-4.5l-3.2-3.3l4.5-.6l2.2-4l1.9 4.2l4.4.8l-3.3 3.1\"/>\u003Cpath fill=\"#fff\" fill-rule=\"evenodd\" d=\"M444.4 285.8a125 125 0 0 0 5.8-19.8c-67.8-59.5-143.3-90-238.7-83.7a125 125 0 0 0-8.5 20.9c113-10.8 196 39.2 241.4 82.6\"/>\u003Cpath fill=\"#309e3a\" d=\"m414 252.4l2.3 1.3a3 3 0 0 0-.3 2.2a3 3 0 0 0 1.4 1.7q1 .8 2 .7q.9 0 1.3-.7l.2-.9l-.5-1l-1.5-1.8a8 8 0 0 1-1.8-3a4 4 0 0 1 2-4.4a4 4 0 0 1 2.3-.2a7 7 0 0 1 2.6 1.2q2.1 1.5 2.6 3.2a4 4 0 0 1-.6 3.3l-2.4-1.5q.5-1 .2-1.7q-.2-.8-1.2-1.4a3 3 0 0 0-1.8-.7a1 1 0 0 0-.9.5q-.3.4-.1 1q.2.8 1.6 2.2t2 2.5a4 4 0 0 1-.3 4.2a4 4 0 0 1-1.9 1.5a4 4 0 0 1-2.4.3q-1.3-.3-2.8-1.3q-2.2-1.5-2.7-3.3a5 5 0 0 1 .6-4zm-11.6-7.6l2.5 1.3a3 3 0 0 0-.2 2.2a3 3 0 0 0 1.4 1.6q1.1.8 2 .6q.9 0 1.3-.8l.2-.8q0-.5-.5-1l-1.6-1.8q-1.7-1.6-2-2.8a4 4 0 0 1 .4-3.1a4 4 0 0 1 1.6-1.4a4 4 0 0 1 2.2-.3a7 7 0 0 1 2.6 1q2.3 1.5 2.7 3.1a4 4 0 0 1-.4 3.4l-2.5-1.4q.5-1 .2-1.7q-.4-1-1.3-1.4a3 3 0 0 0-1.9-.6a1 1 0 0 0-.8.5q-.3.4-.1 1q.3.8 1.7 2.2q1.5 1.5 2 2.4a4 4 0 0 1 0 4.2a4 4 0 0 1-1.8 1.6a4 4 0 0 1-2.4.3a8 8 0 0 1-2.9-1.1a6 6 0 0 1-2.8-3.2a5 5 0 0 1 .4-4m-14.2-3.8l7.3-12l8.8 5.5l-1.2 2l-6.4-4l-1.6 2.7l6 3.7l-1.3 2l-6-3.7l-2 3.3l6.7 4l-1.2 2zm-20.7-17l1.1-2l5.4 2.7l-2.5 5q-1.2.3-3 .2a9 9 0 0 1-3.3-1a8 8 0 0 1-3-2.6a6 6 0 0 1-1-3.5a9 9 0 0 1 1-3.7a8 8 0 0 1 2.6-3a6 6 0 0 1 3.6-1.1q1.4 0 3.2 1q2.4 1.1 3.1 2.8a5 5 0 0 1 .3 3.5l-2.7-.8a3 3 0 0 0-.2-2q-.4-.9-1.6-1.4a4 4 0 0 0-3.1-.3q-1.5.5-2.6 2.6t-.7 3.8a4 4 0 0 0 2 2.4q.8.5 1.7.5h1.8l.8-1.6zm-90.2-22.3l2-14l4.2.7l1.1 9.8l3.9-9l4.2.6l-2 13.8l-2.7-.4l1.7-10.9l-4.4 10.5l-2.7-.4l-1.1-11.3l-1.6 11zm-14.1-1.7l1.3-14l10.3 1l-.2 2.4l-7.5-.7l-.3 3l7 .7l-.3 2.4l-7-.7l-.3 3.8l7.8.7l-.2 2.4z\"/>\u003Cg stroke-opacity=\".5\">\u003Cpath fill=\"#309e3a\" d=\"M216.5 191.3q0-2.2.7-3.6a7 7 0 0 1 1.4-1.9a5 5 0 0 1 1.8-1.2q1.5-.5 3-.5q3.1.1 5 2a7 7 0 0 1 1.6 5.5q0 3.3-2 5.3a7 7 0 0 1-5 1.7a7 7 0 0 1-4.8-2a7 7 0 0 1-1.7-5.3\"/>\u003Cpath fill=\"#f7ffff\" d=\"M219.4 191.3q0 2.3 1 3.6t2.8 1.3a4 4 0 0 0 2.8-1.1q1-1.2 1.1-3.7q.1-2.4-1-3.6a4 4 0 0 0-2.7-1.3a4 4 0 0 0-2.8 1.2q-1.1 1.2-1.2 3.6\"/>\u003C/g>\u003Cg stroke-opacity=\".5\">\u003Cpath fill=\"#309e3a\" d=\"m233 198.5l.2-14h6q2.2 0 3.2.5q1 .3 1.6 1.3c.6 1 .6 1.4.6 2.3a4 4 0 0 1-1 2.6a5 5 0 0 1-2.7 1.2l1.5 1.2q.6.6 1.5 2.3l1.7 2.8h-3.4l-2-3.2l-1.4-2l-.9-.6l-1.4-.2h-.6v5.8z\"/>\u003Cpath fill=\"#fff\" d=\"M236 190.5h2q2.1 0 2.6-.2q.5-.1.8-.5q.4-.6.3-1q0-.9-.4-1.2q-.3-.4-1-.6h-2l-2.3-.1z\"/>\u003C/g>\u003Cg stroke-opacity=\".5\">\u003Cpath fill=\"#309e3a\" d=\"m249 185.2l5.2.3q1.7 0 2.6.3a5 5 0 0 1 2 1.4a6 6 0 0 1 1.2 2.4q.4 1.4.3 3.3a9 9 0 0 1-.5 3q-.6 1.5-1.7 2.4a5 5 0 0 1-2 1q-1 .3-2.5.2l-5.3-.3z\"/>\u003Cpath fill=\"#fff\" d=\"m251.7 187.7l-.5 9.3h3.8q.8 0 1.2-.5q.5-.4.8-1.3t.4-2.6l-.1-2.5a3 3 0 0 0-.8-1.4l-1.2-.7l-2.3-.3z\"/>\u003C/g>\u003Cg stroke-opacity=\".5\">\u003Cpath fill=\"#309e3a\" d=\"m317.6 210.2l3.3-13.6l4.4 1l3.2 1q1.1.6 1.6 1.9t.2 2.8q-.3 1.2-1 2a4 4 0 0 1-3 1.4q-1 0-3-.5l-1.7-.5l-1.2 5.2z\"/>\u003Cpath fill=\"#fff\" d=\"m323 199.6l-.8 3.8l1.5.4q1.6.4 2.2.3a2 2 0 0 0 1.6-1.5q0-.7-.2-1.3a2 2 0 0 0-1-.9l-1.9-.5l-1.3-.3z\"/>\u003C/g>\u003Cg stroke-opacity=\".5\">\u003Cpath fill=\"#309e3a\" d=\"m330.6 214.1l4.7-13.2l5.5 2q2.2.8 3 1.4q.8.7 1 1.8c.2 1.1.2 1.5 0 2.3q-.6 1.5-1.8 2.2q-1.2.6-3 .3q.6.7 1 1.6l.8 2.7l.6 3.1l-3.1-1.1l-1-3.6l-.7-2.4l-.6-.8q-.3-.4-1.3-.7l-.5-.2l-2 5.6z\"/>\u003Cpath fill=\"#fff\" d=\"m336 207.4l1.9.7q2 .7 2.5.7t.9-.3q.5-.3.6-.9q.3-.6 0-1.2l-.8-.9l-2-.7l-2-.7l-1.2 3.3z\"/>\u003C/g>\u003Cg stroke-opacity=\".5\">\u003Cpath fill=\"#309e3a\" d=\"M347 213.6a9 9 0 0 1 1.7-3.2l1.8-1.5l2-.7q1.5-.1 3.1.4a7 7 0 0 1 4.2 3.3q1.2 2.4.2 5.7a7 7 0 0 1-3.4 4.5q-2.3 1.3-5.2.4a7 7 0 0 1-4.2-3.3a7 7 0 0 1-.2-5.6\"/>\u003Cpath fill=\"#fff\" d=\"M349.8 214.4q-.7 2.3 0 3.8c.7 1.5 1.2 1.6 2.3 2q1.5.5 3-.4q1.4-.8 2.1-3.2q.8-2.2 0-3.7a4 4 0 0 0-2.2-2a4 4 0 0 0-3 .3q-1.5.8-2.2 3.2\"/>\u003C/g>\u003Cg stroke-opacity=\".5\">\u003Cpath fill=\"#309e3a\" d=\"m374.3 233.1l6.4-12.4l5.3 2.7a10 10 0 0 1 2.7 1.9q.8.7.8 1.9c0 1.2 0 1.5-.4 2.2a4 4 0 0 1-2 2q-1.5.4-3.1-.2q.6 1 .8 1.7q.3.9.4 2.8l.2 3.2l-3-1.5l-.4-3.7l-.3-2.5l-.5-1l-1.2-.7l-.5-.3l-2.7 5.2z\"/>\u003Cpath fill=\"#fff\" d=\"m380.5 227.2l1.9 1q1.8 1 2.3 1t1-.2q.4-.2.7-.8t.2-1.2l-.7-1l-1.8-1l-2-1z\"/>\u003C/g>\u003Cg stroke-opacity=\".5\">\u003Cpath fill=\"#309e3a\" d=\"M426.1 258.7a9 9 0 0 1 2.5-2.6a7 7 0 0 1 2.2-.9a6 6 0 0 1 2.2 0q1.5.3 2.8 1.2a7 7 0 0 1 3 4.4q.4 2.6-1.4 5.5a7 7 0 0 1-4.5 3.3a7 7 0 0 1-5.2-1.1a7 7 0 0 1-3-4.4q-.4-2.7 1.4-5.4\"/>\u003Cpath fill=\"#fff\" d=\"M428.6 260.3q-1.4 2-1.1 3.6a4 4 0 0 0 1.6 2.5q1.5 1 3 .6t2.9-2.4q1.4-2.1 1.1-3.6t-1.6-2.6c-1.4-1.1-2-.8-3-.5q-1.5.3-3 2.4z\"/>\u003C/g>\u003Cpath fill=\"#309e3a\" d=\"m301.8 204.5l2.3-9.8l7.2 1.7l-.3 1.6l-5.3-1.2l-.5 2.2l4.9 1.1l-.4 1.7l-4.9-1.2l-.6 2.7l5.5 1.3l-.4 1.6z\"/>\u003C/g>",{"left":4,"top":4,"width":14,"height":15,"rotate":4,"vFlip":6,"hFlip":6,"body":18},"\u003Cpath fill=\"#bd3d44\" d=\"M0 0h640v480H0\"/>\u003Cpath stroke=\"#fff\" stroke-width=\"37\" d=\"M0 55.3h640M0 129h640M0 203h640M0 277h640M0 351h640M0 425h640\"/>\u003Cpath fill=\"#192f5d\" d=\"M0 0h364.8v258.5H0\"/>\u003Cmarker id=\"SVGEq3dreKJ\" markerHeight=\"30\" markerWidth=\"30\">\u003Cpath fill=\"#fff\" d=\"m14 0l9 27L0 10h28L5 27z\"/>\u003C/marker>\u003Cpath fill=\"none\" marker-mid=\"url(#SVGEq3dreKJ)\" d=\"m0 0l16 11h61h61h61h61h60L47 37h61h61h60h61L16 63h61h61h61h61h60L47 89h61h61h60h61L16 115h61h61h61h61h60L47 141h61h61h60h61L16 166h61h61h61h61h60L47 192h61h61h60h61L16 218h61h61h61h61h60z\"/>",{"id":20,"title":21,"body":22,"description":69,"description_en":1894,"description_pt":1895,"draft":6,"extension":1896,"meta":1897,"navigation":287,"path":1898,"publishDate":1899,"seo":1900,"slug":1901,"stem":1902,"tags":1903,"title_en":1908,"title_pt":1909,"__hash__":1910},"blog/blog/learning-tea.md","Learning Tea",{"type":23,"value":24,"toc":1882},"minimark",[25,45,63,150,178,201,223,232,245,256,371,383,394,525,530,535,695,721,747,939,969,995,1053,1061,1068,1570,1611,1649,1836,1857,1878],[26,27,29,33,36,39,42],"lang-block",{"lang":28},"en",[30,31,32],"p",{},"This is the first part of a series of articles about writing a TEA-based framework in TypeScript.",[30,34,35],{},"The Elm Architecture is used in many places: Lustre in Gleam, Bubble Tea in Go, and Iced in Rust.",[30,37,38],{},"So let’s learn by creating a small project using The Elm Architecture, which we can later migrate to our own TypeScript framework. After all, there are not enough JavaScript frameworks for the web.",[30,40,41],{},"You don’t need prior Elm knowledge, but you should have a basic understanding of TypeScript and DOM events.",[30,43,44],{},"We can start with a simple Vite project, using the Vanilla template and TypeScript:",[26,46,48,51,54,57,60],{"lang":47},"pt",[30,49,50],{},"Esta é a primeira parte de uma série de artigos sobre como escrever um framework baseado em TEA (The Elm Architecture) em TypeScript.",[30,52,53],{},"A Elm Architecture é utilizada em muitos lugares: Lustre em Gleam, Bubble Tea em Go e Iced em Rust.",[30,55,56],{},"Então vamos aprender criando um pequeno projeto usando a Elm Architecture, que poderemos migrar posteriormente para o nosso próprio framework TypeScript. Afinal, nunca existem frameworks JavaScript suficientes para a web.",[30,58,59],{},"Você não precisa de conhecimento prévio de Elm, mas deve ter um entendimento básico de TypeScript e eventos do DOM.",[30,61,62],{},"Podemos começar com um projeto Vite simples, usando o template Vanilla e TypeScript:",[64,65,70],"pre",{"className":66,"code":67,"language":68,"meta":69,"style":69},"language-sh shiki shiki-themes github-dark github-dark github-light","❯ pnpm create vite\n│\n◇  Project name:\n│  tea\n│\n◇  Select a framework:\n│  Vanilla\n│\n◇  Select a variant:\n│  TypeScript\n│\n◇  Install with pnpm and start now?\n│  Yes\n","sh","",[71,72,73,81,87,93,99,104,110,116,121,127,133,138,144],"code",{"__ignoreMap":69},[74,75,78],"span",{"class":76,"line":77},"line",1,[74,79,80],{},"❯ pnpm create vite\n",[74,82,84],{"class":76,"line":83},2,[74,85,86],{},"│\n",[74,88,90],{"class":76,"line":89},3,[74,91,92],{},"◇  Project name:\n",[74,94,96],{"class":76,"line":95},4,[74,97,98],{},"│  tea\n",[74,100,102],{"class":76,"line":101},5,[74,103,86],{},[74,105,107],{"class":76,"line":106},6,[74,108,109],{},"◇  Select a framework:\n",[74,111,113],{"class":76,"line":112},7,[74,114,115],{},"│  Vanilla\n",[74,117,119],{"class":76,"line":118},8,[74,120,86],{},[74,122,124],{"class":76,"line":123},9,[74,125,126],{},"◇  Select a variant:\n",[74,128,130],{"class":76,"line":129},10,[74,131,132],{},"│  TypeScript\n",[74,134,136],{"class":76,"line":135},11,[74,137,86],{},[74,139,141],{"class":76,"line":140},12,[74,142,143],{},"◇  Install with pnpm and start now?\n",[74,145,147],{"class":76,"line":146},13,[74,148,149],{},"│  Yes\n",[26,151,152,159],{"lang":28},[30,153,154,155,158],{},"For this article we are going to use ",[71,156,157],{},"lit-html"," so we don’t have to implement two key features ourselves: HTML generation and efficient rendering.",[30,160,161,162,165,166,169,170,173,174,177],{},"We can create templates with JavaScript interpolation by using the ",[71,163,164],{},"html"," tag (for example, ",[71,167,168],{},"${...}"," inside the template), and we can bind DOM events with ",[71,171,172],{},"@event"," syntax, similar to Vue, and conceptually similar to ",[71,175,176],{},"onEvent"," props in React.",[26,179,180,186],{"lang":47},[30,181,182,183,185],{},"Para este artigo, vamos usar ",[71,184,157],{}," para não termos que implementar duas funcionalidades principais nós mesmos: geração de HTML e renderização eficiente.",[30,187,188,189,191,192,194,195,197,198,200],{},"Podemos criar templates com interpolação JavaScript usando a tag ",[71,190,164],{}," (por exemplo, ",[71,193,168],{}," dentro do template), e podemos vincular eventos do DOM com a sintaxe ",[71,196,172],{},", semelhante ao Vue, e conceitualmente parecida com as props ",[71,199,176],{}," no React.",[202,203,206,215],"more-info",{"title-en":204,"title-pt":205},"Tip","Dica",[207,208,209],"template",{"v-slot:en":69},[30,210,211,212,214],{},"If you want syntax highlighting inside ",[71,213,164],{}," template literals, install the VS Code plugin for Lit.",[207,216,217],{"v-slot:pt":69},[30,218,219,220,222],{},"Se você quiser realce de sintaxe dentro de literais de template ",[71,221,164],{},", instale o plugin do VS Code para Lit.",[64,224,226],{"className":66,"code":225,"language":68,"meta":69,"style":69},"pnpm add lit-html\n",[71,227,228],{"__ignoreMap":69},[74,229,230],{"class":76,"line":77},[74,231,225],{},[26,233,234],{"lang":28},[30,235,236,237,240,241,244],{},"We remove everything in ",[71,238,239],{},"main.ts"," and write a basic ",[71,242,243],{},"view"," for our app:",[26,246,247],{"lang":47},[30,248,249,250,252,253,255],{},"Removemos tudo no ",[71,251,239],{}," e escrevemos uma ",[71,254,243],{}," básica para o nosso app:",[64,257,261],{"className":258,"code":259,"language":260,"meta":69,"style":69},"language-ts shiki shiki-themes github-dark github-dark github-light","import { html, render } from \"lit-html\";\n\nconst view = html`\n  \u003Ch1>Hello, World\u003C/h1>\n  \u003Cp>Counter is at 0\u003C/p>\n  \u003Cbutton>Click me\u003C/button>\n`;\n\nconst root = document.getElementById(\"app\")!;\nrender(view, root);\n","ts",[71,262,263,283,289,308,313,318,323,330,334,363],{"__ignoreMap":69},[74,264,265,269,273,276,280],{"class":76,"line":77},[74,266,268],{"class":267},"s6ubI","import",[74,270,272],{"class":271},"sAvwS"," { html, render } ",[74,274,275],{"class":267},"from",[74,277,279],{"class":278},"s4Y1p"," \"lit-html\"",[74,281,282],{"class":271},";\n",[74,284,285],{"class":76,"line":83},[74,286,288],{"emptyLinePlaceholder":287},true,"\n",[74,290,291,294,298,301,305],{"class":76,"line":89},[74,292,293],{"class":267},"const",[74,295,297],{"class":296},"sXWYR"," view",[74,299,300],{"class":267}," =",[74,302,304],{"class":303},"s5n6i"," html",[74,306,307],{"class":278},"`\n",[74,309,310],{"class":76,"line":95},[74,311,312],{"class":278},"  \u003Ch1>Hello, World\u003C/h1>\n",[74,314,315],{"class":76,"line":101},[74,316,317],{"class":278},"  \u003Cp>Counter is at 0\u003C/p>\n",[74,319,320],{"class":76,"line":106},[74,321,322],{"class":278},"  \u003Cbutton>Click me\u003C/button>\n",[74,324,325,328],{"class":76,"line":112},[74,326,327],{"class":278},"`",[74,329,282],{"class":271},[74,331,332],{"class":76,"line":118},[74,333,288],{"emptyLinePlaceholder":287},[74,335,336,338,341,343,346,349,352,355,358,361],{"class":76,"line":123},[74,337,293],{"class":267},[74,339,340],{"class":296}," root",[74,342,300],{"class":267},[74,344,345],{"class":271}," document.",[74,347,348],{"class":303},"getElementById",[74,350,351],{"class":271},"(",[74,353,354],{"class":278},"\"app\"",[74,356,357],{"class":271},")",[74,359,360],{"class":267},"!",[74,362,282],{"class":271},[74,364,365,368],{"class":76,"line":129},[74,366,367],{"class":303},"render",[74,369,370],{"class":271},"(view, root);\n",[26,372,373],{"lang":28},[30,374,375,376,379,380,382],{},"We render into ",[71,377,378],{},"#app"," using ",[71,381,157],{},". Next, let’s make this dynamic using interpolation:",[26,384,385],{"lang":47},[30,386,387,388,390,391,393],{},"Renderizamos no ",[71,389,378],{}," usando ",[71,392,157],{},". Em seguida, vamos tornar isso dinâmico usando interpolação:",[64,395,397],{"className":258,"code":396,"language":260,"meta":69,"style":69},"import { html, render } from \"lit-html\";\n\nlet counter = 0;\nconst title = \"Hello, World\";\n\nconst view = html`\n  \u003Ch1>${title}\u003C/h1>\n  \u003Cp>Counter is at ${counter}\u003C/p>\n  \u003Cbutton>Click me\u003C/button>\n`;\n\nconst root = document.getElementById(\"app\")!;\nrender(view, root);\n",[71,398,399,411,415,431,445,449,461,472,483,487,493,497,519],{"__ignoreMap":69},[74,400,401,403,405,407,409],{"class":76,"line":77},[74,402,268],{"class":267},[74,404,272],{"class":271},[74,406,275],{"class":267},[74,408,279],{"class":278},[74,410,282],{"class":271},[74,412,413],{"class":76,"line":83},[74,414,288],{"emptyLinePlaceholder":287},[74,416,417,420,423,426,429],{"class":76,"line":89},[74,418,419],{"class":267},"let",[74,421,422],{"class":271}," counter ",[74,424,425],{"class":267},"=",[74,427,428],{"class":296}," 0",[74,430,282],{"class":271},[74,432,433,435,438,440,443],{"class":76,"line":95},[74,434,293],{"class":267},[74,436,437],{"class":296}," title",[74,439,300],{"class":267},[74,441,442],{"class":278}," \"Hello, World\"",[74,444,282],{"class":271},[74,446,447],{"class":76,"line":101},[74,448,288],{"emptyLinePlaceholder":287},[74,450,451,453,455,457,459],{"class":76,"line":106},[74,452,293],{"class":267},[74,454,297],{"class":296},[74,456,300],{"class":267},[74,458,304],{"class":303},[74,460,307],{"class":278},[74,462,463,466,469],{"class":76,"line":112},[74,464,465],{"class":278},"  \u003Ch1>${",[74,467,468],{"class":271},"title",[74,470,471],{"class":278},"}\u003C/h1>\n",[74,473,474,477,480],{"class":76,"line":118},[74,475,476],{"class":278},"  \u003Cp>Counter is at ${",[74,478,479],{"class":271},"counter",[74,481,482],{"class":278},"}\u003C/p>\n",[74,484,485],{"class":76,"line":123},[74,486,322],{"class":278},[74,488,489,491],{"class":76,"line":129},[74,490,327],{"class":278},[74,492,282],{"class":271},[74,494,495],{"class":76,"line":135},[74,496,288],{"emptyLinePlaceholder":287},[74,498,499,501,503,505,507,509,511,513,515,517],{"class":76,"line":140},[74,500,293],{"class":267},[74,502,340],{"class":296},[74,504,300],{"class":267},[74,506,345],{"class":271},[74,508,348],{"class":303},[74,510,351],{"class":271},[74,512,354],{"class":278},[74,514,357],{"class":271},[74,516,360],{"class":267},[74,518,282],{"class":271},[74,520,521,523],{"class":76,"line":146},[74,522,367],{"class":303},[74,524,370],{"class":271},[26,526,527],{"lang":28},[30,528,529],{},"Now, let’s make a function that increases the counter and bind it to the button:",[26,531,532],{"lang":47},[30,533,534],{},"Agora, vamos criar uma função que aumenta o contador e vinculá-la ao botão:",[64,536,538],{"className":258,"code":537,"language":260,"meta":69,"style":69},"import { html, render } from \"lit-html\";\n\nlet counter = 0;\nconst title = \"Hello, World\";\n\nconst view = html`\n  \u003Ch1>${title}\u003C/h1>\n  \u003Cp>Counter is at ${counter}\u003C/p>\n  \u003Cbutton @click=${increaseCounter}>Click me\u003C/button>\n`;\n\nconst root = document.getElementById(\"app\")!;\nrender(view, root);\n\nfunction increaseCounter() {\n  counter++;\n}\n",[71,539,540,552,556,568,580,584,596,604,612,623,629,633,655,661,666,678,689],{"__ignoreMap":69},[74,541,542,544,546,548,550],{"class":76,"line":77},[74,543,268],{"class":267},[74,545,272],{"class":271},[74,547,275],{"class":267},[74,549,279],{"class":278},[74,551,282],{"class":271},[74,553,554],{"class":76,"line":83},[74,555,288],{"emptyLinePlaceholder":287},[74,557,558,560,562,564,566],{"class":76,"line":89},[74,559,419],{"class":267},[74,561,422],{"class":271},[74,563,425],{"class":267},[74,565,428],{"class":296},[74,567,282],{"class":271},[74,569,570,572,574,576,578],{"class":76,"line":95},[74,571,293],{"class":267},[74,573,437],{"class":296},[74,575,300],{"class":267},[74,577,442],{"class":278},[74,579,282],{"class":271},[74,581,582],{"class":76,"line":101},[74,583,288],{"emptyLinePlaceholder":287},[74,585,586,588,590,592,594],{"class":76,"line":106},[74,587,293],{"class":267},[74,589,297],{"class":296},[74,591,300],{"class":267},[74,593,304],{"class":303},[74,595,307],{"class":278},[74,597,598,600,602],{"class":76,"line":112},[74,599,465],{"class":278},[74,601,468],{"class":271},[74,603,471],{"class":278},[74,605,606,608,610],{"class":76,"line":118},[74,607,476],{"class":278},[74,609,479],{"class":271},[74,611,482],{"class":278},[74,613,614,617,620],{"class":76,"line":123},[74,615,616],{"class":278},"  \u003Cbutton @click=${",[74,618,619],{"class":271},"increaseCounter",[74,621,622],{"class":278},"}>Click me\u003C/button>\n",[74,624,625,627],{"class":76,"line":129},[74,626,327],{"class":278},[74,628,282],{"class":271},[74,630,631],{"class":76,"line":135},[74,632,288],{"emptyLinePlaceholder":287},[74,634,635,637,639,641,643,645,647,649,651,653],{"class":76,"line":140},[74,636,293],{"class":267},[74,638,340],{"class":296},[74,640,300],{"class":267},[74,642,345],{"class":271},[74,644,348],{"class":303},[74,646,351],{"class":271},[74,648,354],{"class":278},[74,650,357],{"class":271},[74,652,360],{"class":267},[74,654,282],{"class":271},[74,656,657,659],{"class":76,"line":146},[74,658,367],{"class":303},[74,660,370],{"class":271},[74,662,664],{"class":76,"line":663},14,[74,665,288],{"emptyLinePlaceholder":287},[74,667,669,672,675],{"class":76,"line":668},15,[74,670,671],{"class":267},"function",[74,673,674],{"class":303}," increaseCounter",[74,676,677],{"class":271},"() {\n",[74,679,681,684,687],{"class":76,"line":680},16,[74,682,683],{"class":271},"  counter",[74,685,686],{"class":267},"++",[74,688,282],{"class":271},[74,690,692],{"class":76,"line":691},17,[74,693,694],{"class":271},"}\n",[26,696,697,700,715],{"lang":28},[30,698,699],{},"But this won’t work. Why?",[30,701,702,703,705,706,708,709,711,712,714],{},"When ",[71,704,619],{}," runs, the ",[71,707,243],{}," was already created and rendered. We update ",[71,710,479],{},", but we don’t create a new ",[71,713,243],{}," or render again.",[30,716,717,718,720],{},"Let’s fix that by making ",[71,719,243],{}," a function that receives state, and re-rendering after each update:",[26,722,723,726,741],{"lang":47},[30,724,725],{},"Mas isso não vai funcionar. Por quê?",[30,727,728,729,731,732,734,735,737,738,740],{},"Quando o ",[71,730,619],{}," é executado, a ",[71,733,243],{}," já foi criada e renderizada. Atualizamos o ",[71,736,479],{},", mas não criamos uma nova ",[71,739,243],{}," nem renderizamos novamente.",[30,742,743,744,746],{},"Vamos corrigir isso tornando a ",[71,745,243],{}," uma função que recebe o estado e renderizando novamente após cada atualização:",[64,748,750],{"className":258,"code":749,"language":260,"meta":69,"style":69},"import { html, render } from \"lit-html\";\n\nlet counter = 0;\nconst title = \"Hello, World\";\n\nfunction view(counterAmount: number) {\n  return html`\n    \u003Ch1>${title}\u003C/h1>\n    \u003Cp>Counter is at ${counterAmount}\u003C/p>\n    \u003Cbutton @click=${increaseCounter}>Click me\u003C/button>\n  `;\n}\n\nconst root = document.getElementById(\"app\")!;\nrender(view(counter), root);\n\nfunction increaseCounter() {\n  counter++;\n  render(view(counter), root);\n}\n",[71,751,752,764,768,780,792,796,817,826,835,844,853,860,864,868,890,901,905,913,922,934],{"__ignoreMap":69},[74,753,754,756,758,760,762],{"class":76,"line":77},[74,755,268],{"class":267},[74,757,272],{"class":271},[74,759,275],{"class":267},[74,761,279],{"class":278},[74,763,282],{"class":271},[74,765,766],{"class":76,"line":83},[74,767,288],{"emptyLinePlaceholder":287},[74,769,770,772,774,776,778],{"class":76,"line":89},[74,771,419],{"class":267},[74,773,422],{"class":271},[74,775,425],{"class":267},[74,777,428],{"class":296},[74,779,282],{"class":271},[74,781,782,784,786,788,790],{"class":76,"line":95},[74,783,293],{"class":267},[74,785,437],{"class":296},[74,787,300],{"class":267},[74,789,442],{"class":278},[74,791,282],{"class":271},[74,793,794],{"class":76,"line":101},[74,795,288],{"emptyLinePlaceholder":287},[74,797,798,800,802,804,808,811,814],{"class":76,"line":106},[74,799,671],{"class":267},[74,801,297],{"class":303},[74,803,351],{"class":271},[74,805,807],{"class":806},"sAzo5","counterAmount",[74,809,810],{"class":267},":",[74,812,813],{"class":296}," number",[74,815,816],{"class":271},") {\n",[74,818,819,822,824],{"class":76,"line":112},[74,820,821],{"class":267},"  return",[74,823,304],{"class":303},[74,825,307],{"class":278},[74,827,828,831,833],{"class":76,"line":118},[74,829,830],{"class":278},"    \u003Ch1>${",[74,832,468],{"class":271},[74,834,471],{"class":278},[74,836,837,840,842],{"class":76,"line":123},[74,838,839],{"class":278},"    \u003Cp>Counter is at ${",[74,841,807],{"class":271},[74,843,482],{"class":278},[74,845,846,849,851],{"class":76,"line":129},[74,847,848],{"class":278},"    \u003Cbutton @click=${",[74,850,619],{"class":271},[74,852,622],{"class":278},[74,854,855,858],{"class":76,"line":135},[74,856,857],{"class":278},"  `",[74,859,282],{"class":271},[74,861,862],{"class":76,"line":140},[74,863,694],{"class":271},[74,865,866],{"class":76,"line":146},[74,867,288],{"emptyLinePlaceholder":287},[74,869,870,872,874,876,878,880,882,884,886,888],{"class":76,"line":663},[74,871,293],{"class":267},[74,873,340],{"class":296},[74,875,300],{"class":267},[74,877,345],{"class":271},[74,879,348],{"class":303},[74,881,351],{"class":271},[74,883,354],{"class":278},[74,885,357],{"class":271},[74,887,360],{"class":267},[74,889,282],{"class":271},[74,891,892,894,896,898],{"class":76,"line":668},[74,893,367],{"class":303},[74,895,351],{"class":271},[74,897,243],{"class":303},[74,899,900],{"class":271},"(counter), root);\n",[74,902,903],{"class":76,"line":680},[74,904,288],{"emptyLinePlaceholder":287},[74,906,907,909,911],{"class":76,"line":691},[74,908,671],{"class":267},[74,910,674],{"class":303},[74,912,677],{"class":271},[74,914,916,918,920],{"class":76,"line":915},18,[74,917,683],{"class":271},[74,919,686],{"class":267},[74,921,282],{"class":271},[74,923,925,928,930,932],{"class":76,"line":924},19,[74,926,927],{"class":303},"  render",[74,929,351],{"class":271},[74,931,243],{"class":303},[74,933,900],{"class":271},[74,935,937],{"class":76,"line":936},20,[74,938,694],{"class":271},[26,940,941,944,947,954,963,966],{"lang":28},[30,942,943],{},"Now clicking the button updates the UI again.",[30,945,946],{},"At a high level, this idea appears in many frameworks: UI as a function of state. The details differ (Virtual DOM, fine-grained reactivity, compile-time optimizations), but the core loop is familiar.",[30,948,949,950,953],{},"Now we’ll apply the core ideas from The Elm Architecture but encapsulated in a class, similar to how the ",[71,951,952],{},"iced"," library works in Rust.",[955,956,958,959,962],"h2",{"id":957},"the-counter-application","The ",[71,960,961],{},"Counter"," Application",[30,964,965],{},"Instead of loose functions and variables, we’ll encapsulate our application logic in a class. This class will hold our application state and define how to update and view it.",[30,967,968],{},"First, let's define our state and messages:",[26,970,971,974,977,983,989,992],{"lang":47},[30,972,973],{},"Agora, clicar no botão atualiza a UI novamente.",[30,975,976],{},"Em um nível macro, essa ideia aparece em muitos frameworks: a UI como uma função do estado. Os detalhes diferem (Virtual DOM, reatividade granular, otimizações em tempo de compilação), mas o loop principal é familiar.",[30,978,979,980,982],{},"Agora vamos aplicar as ideias centrais da Elm Architecture, mas encapsuladas em uma classe, semelhante a como a biblioteca ",[71,981,952],{}," funciona em Rust.",[955,984,986,987],{"id":985},"a-aplicação-counter","A Aplicação ",[71,988,961],{},[30,990,991],{},"Em vez de funções e variáveis soltas, vamos encapsular a lógica da nossa aplicação em uma classe. Essa classe manterá o estado da nossa aplicação e definirá como atualizá-lo e visualizá-lo.",[30,993,994],{},"Primeiro, vamos definir nosso estado e mensagens:",[64,996,998],{"className":258,"code":997,"language":260,"meta":69,"style":69},"type State = {\n  value: number;\n};\n\ntype Message = \"Increment\" | \"Decrement\";\n",[71,999,1000,1013,1024,1029,1033],{"__ignoreMap":69},[74,1001,1002,1005,1008,1010],{"class":76,"line":77},[74,1003,1004],{"class":267},"type",[74,1006,1007],{"class":303}," State",[74,1009,300],{"class":267},[74,1011,1012],{"class":271}," {\n",[74,1014,1015,1018,1020,1022],{"class":76,"line":83},[74,1016,1017],{"class":806},"  value",[74,1019,810],{"class":267},[74,1021,813],{"class":296},[74,1023,282],{"class":271},[74,1025,1026],{"class":76,"line":89},[74,1027,1028],{"class":271},"};\n",[74,1030,1031],{"class":76,"line":95},[74,1032,288],{"emptyLinePlaceholder":287},[74,1034,1035,1037,1040,1042,1045,1048,1051],{"class":76,"line":101},[74,1036,1004],{"class":267},[74,1038,1039],{"class":303}," Message",[74,1041,300],{"class":267},[74,1043,1044],{"class":278}," \"Increment\"",[74,1046,1047],{"class":267}," |",[74,1049,1050],{"class":278}," \"Decrement\"",[74,1052,282],{"class":271},[26,1054,1055],{"lang":28},[30,1056,1057,1058,1060],{},"Now, let's create the ",[71,1059,961],{}," class:",[26,1062,1063],{"lang":47},[30,1064,1065,1066,810],{},"Agora, vamos criar a classe ",[71,1067,961],{},[64,1069,1071],{"className":258,"code":1070,"language":260,"meta":69,"style":69},"import { html, render } from \"lit-html\";\n\nclass Counter {\n  // We use an internal state object\n  state: State = {\n    value: 0,\n  };\n\n  // The update method describes how state changes in response to messages\n  update(message: Message) {\n    // We capture a snapshot of the current state before the update logic starts.\n    let state = this.state;\n\n    switch (message) {\n      case \"Increment\":\n        this.state = { ...state, value: state.value + 1 };\n        break;\n      case \"Decrement\":\n        this.state = { ...state, value: state.value - 1 };\n        break;\n    }\n  }\n\n  // The view method describes how the UI should look based on the current state\n  view() {\n    return html`\n      \u003Ch1>Counter App\u003C/h1>\n      \u003Cp>Count: ${this.state.value}\u003C/p>\n      \u003Cbutton @click=${() => this.dispatch(\"Increment\")}>+\u003C/button>\n      \u003Cbutton @click=${() => this.dispatch(\"Decrement\")}>-\u003C/button>\n    `;\n  }\n\n  // The runtime logic\n  private root = document.getElementById(\"app\")!;\n\n  dispatch(message: Message) {\n    this.update(message);\n    this.render();\n  }\n\n  render() {\n    render(this.view(), this.root);\n  }\n}\n\nconst app = new Counter();\napp.render();\n",[71,1072,1073,1085,1089,1099,1105,1118,1129,1134,1138,1143,1159,1164,1180,1184,1192,1202,1230,1237,1245,1266,1272,1278,1284,1289,1294,1302,1312,1318,1340,1369,1394,1402,1407,1412,1418,1442,1447,1463,1477,1489,1494,1499,1506,1528,1533,1538,1543,1560],{"__ignoreMap":69},[74,1074,1075,1077,1079,1081,1083],{"class":76,"line":77},[74,1076,268],{"class":267},[74,1078,272],{"class":271},[74,1080,275],{"class":267},[74,1082,279],{"class":278},[74,1084,282],{"class":271},[74,1086,1087],{"class":76,"line":83},[74,1088,288],{"emptyLinePlaceholder":287},[74,1090,1091,1094,1097],{"class":76,"line":89},[74,1092,1093],{"class":267},"class",[74,1095,1096],{"class":303}," Counter",[74,1098,1012],{"class":271},[74,1100,1101],{"class":76,"line":95},[74,1102,1104],{"class":1103},"sxXm1","  // We use an internal state object\n",[74,1106,1107,1110,1112,1114,1116],{"class":76,"line":101},[74,1108,1109],{"class":806},"  state",[74,1111,810],{"class":267},[74,1113,1007],{"class":303},[74,1115,300],{"class":267},[74,1117,1012],{"class":271},[74,1119,1120,1123,1126],{"class":76,"line":106},[74,1121,1122],{"class":271},"    value: ",[74,1124,1125],{"class":296},"0",[74,1127,1128],{"class":271},",\n",[74,1130,1131],{"class":76,"line":112},[74,1132,1133],{"class":271},"  };\n",[74,1135,1136],{"class":76,"line":118},[74,1137,288],{"emptyLinePlaceholder":287},[74,1139,1140],{"class":76,"line":123},[74,1141,1142],{"class":1103},"  // The update method describes how state changes in response to messages\n",[74,1144,1145,1148,1150,1153,1155,1157],{"class":76,"line":129},[74,1146,1147],{"class":303},"  update",[74,1149,351],{"class":271},[74,1151,1152],{"class":806},"message",[74,1154,810],{"class":267},[74,1156,1039],{"class":303},[74,1158,816],{"class":271},[74,1160,1161],{"class":76,"line":135},[74,1162,1163],{"class":1103},"    // We capture a snapshot of the current state before the update logic starts.\n",[74,1165,1166,1169,1172,1174,1177],{"class":76,"line":140},[74,1167,1168],{"class":267},"    let",[74,1170,1171],{"class":271}," state ",[74,1173,425],{"class":267},[74,1175,1176],{"class":296}," this",[74,1178,1179],{"class":271},".state;\n",[74,1181,1182],{"class":76,"line":146},[74,1183,288],{"emptyLinePlaceholder":287},[74,1185,1186,1189],{"class":76,"line":663},[74,1187,1188],{"class":267},"    switch",[74,1190,1191],{"class":271}," (message) {\n",[74,1193,1194,1197,1199],{"class":76,"line":668},[74,1195,1196],{"class":267},"      case",[74,1198,1044],{"class":278},[74,1200,1201],{"class":271},":\n",[74,1203,1204,1207,1210,1212,1215,1218,1221,1224,1227],{"class":76,"line":680},[74,1205,1206],{"class":296},"        this",[74,1208,1209],{"class":271},".state ",[74,1211,425],{"class":267},[74,1213,1214],{"class":271}," { ",[74,1216,1217],{"class":267},"...",[74,1219,1220],{"class":271},"state, value: state.value ",[74,1222,1223],{"class":267},"+",[74,1225,1226],{"class":296}," 1",[74,1228,1229],{"class":271}," };\n",[74,1231,1232,1235],{"class":76,"line":691},[74,1233,1234],{"class":267},"        break",[74,1236,282],{"class":271},[74,1238,1239,1241,1243],{"class":76,"line":915},[74,1240,1196],{"class":267},[74,1242,1050],{"class":278},[74,1244,1201],{"class":271},[74,1246,1247,1249,1251,1253,1255,1257,1259,1262,1264],{"class":76,"line":924},[74,1248,1206],{"class":296},[74,1250,1209],{"class":271},[74,1252,425],{"class":267},[74,1254,1214],{"class":271},[74,1256,1217],{"class":267},[74,1258,1220],{"class":271},[74,1260,1261],{"class":267},"-",[74,1263,1226],{"class":296},[74,1265,1229],{"class":271},[74,1267,1268,1270],{"class":76,"line":936},[74,1269,1234],{"class":267},[74,1271,282],{"class":271},[74,1273,1275],{"class":76,"line":1274},21,[74,1276,1277],{"class":271},"    }\n",[74,1279,1281],{"class":76,"line":1280},22,[74,1282,1283],{"class":271},"  }\n",[74,1285,1287],{"class":76,"line":1286},23,[74,1288,288],{"emptyLinePlaceholder":287},[74,1290,1291],{"class":76,"line":5},[74,1292,1293],{"class":1103},"  // The view method describes how the UI should look based on the current state\n",[74,1295,1297,1300],{"class":76,"line":1296},25,[74,1298,1299],{"class":303},"  view",[74,1301,677],{"class":271},[74,1303,1305,1308,1310],{"class":76,"line":1304},26,[74,1306,1307],{"class":267},"    return",[74,1309,304],{"class":303},[74,1311,307],{"class":278},[74,1313,1315],{"class":76,"line":1314},27,[74,1316,1317],{"class":278},"      \u003Ch1>Counter App\u003C/h1>\n",[74,1319,1321,1324,1327,1330,1333,1335,1338],{"class":76,"line":1320},28,[74,1322,1323],{"class":278},"      \u003Cp>Count: ${",[74,1325,1326],{"class":296},"this",[74,1328,1329],{"class":278},".",[74,1331,1332],{"class":271},"state",[74,1334,1329],{"class":278},[74,1336,1337],{"class":271},"value",[74,1339,482],{"class":278},[74,1341,1343,1346,1349,1352,1354,1356,1359,1361,1364,1366],{"class":76,"line":1342},29,[74,1344,1345],{"class":278},"      \u003Cbutton @click=${",[74,1347,1348],{"class":278},"() ",[74,1350,1351],{"class":267},"=>",[74,1353,1176],{"class":296},[74,1355,1329],{"class":278},[74,1357,1358],{"class":303},"dispatch",[74,1360,351],{"class":278},[74,1362,1363],{"class":278},"\"Increment\"",[74,1365,357],{"class":278},[74,1367,1368],{"class":278},"}>+\u003C/button>\n",[74,1370,1372,1374,1376,1378,1380,1382,1384,1386,1389,1391],{"class":76,"line":1371},30,[74,1373,1345],{"class":278},[74,1375,1348],{"class":278},[74,1377,1351],{"class":267},[74,1379,1176],{"class":296},[74,1381,1329],{"class":278},[74,1383,1358],{"class":303},[74,1385,351],{"class":278},[74,1387,1388],{"class":278},"\"Decrement\"",[74,1390,357],{"class":278},[74,1392,1393],{"class":278},"}>-\u003C/button>\n",[74,1395,1397,1400],{"class":76,"line":1396},31,[74,1398,1399],{"class":278},"    `",[74,1401,282],{"class":271},[74,1403,1405],{"class":76,"line":1404},32,[74,1406,1283],{"class":271},[74,1408,1410],{"class":76,"line":1409},33,[74,1411,288],{"emptyLinePlaceholder":287},[74,1413,1415],{"class":76,"line":1414},34,[74,1416,1417],{"class":1103},"  // The runtime logic\n",[74,1419,1421,1424,1426,1428,1430,1432,1434,1436,1438,1440],{"class":76,"line":1420},35,[74,1422,1423],{"class":267},"  private",[74,1425,340],{"class":806},[74,1427,300],{"class":267},[74,1429,345],{"class":271},[74,1431,348],{"class":303},[74,1433,351],{"class":271},[74,1435,354],{"class":278},[74,1437,357],{"class":271},[74,1439,360],{"class":267},[74,1441,282],{"class":271},[74,1443,1445],{"class":76,"line":1444},36,[74,1446,288],{"emptyLinePlaceholder":287},[74,1448,1450,1453,1455,1457,1459,1461],{"class":76,"line":1449},37,[74,1451,1452],{"class":303},"  dispatch",[74,1454,351],{"class":271},[74,1456,1152],{"class":806},[74,1458,810],{"class":267},[74,1460,1039],{"class":303},[74,1462,816],{"class":271},[74,1464,1466,1469,1471,1474],{"class":76,"line":1465},38,[74,1467,1468],{"class":296},"    this",[74,1470,1329],{"class":271},[74,1472,1473],{"class":303},"update",[74,1475,1476],{"class":271},"(message);\n",[74,1478,1480,1482,1484,1486],{"class":76,"line":1479},39,[74,1481,1468],{"class":296},[74,1483,1329],{"class":271},[74,1485,367],{"class":303},[74,1487,1488],{"class":271},"();\n",[74,1490,1492],{"class":76,"line":1491},40,[74,1493,1283],{"class":271},[74,1495,1497],{"class":76,"line":1496},41,[74,1498,288],{"emptyLinePlaceholder":287},[74,1500,1502,1504],{"class":76,"line":1501},42,[74,1503,927],{"class":303},[74,1505,677],{"class":271},[74,1507,1509,1512,1514,1516,1518,1520,1523,1525],{"class":76,"line":1508},43,[74,1510,1511],{"class":303},"    render",[74,1513,351],{"class":271},[74,1515,1326],{"class":296},[74,1517,1329],{"class":271},[74,1519,243],{"class":303},[74,1521,1522],{"class":271},"(), ",[74,1524,1326],{"class":296},[74,1526,1527],{"class":271},".root);\n",[74,1529,1531],{"class":76,"line":1530},44,[74,1532,1283],{"class":271},[74,1534,1536],{"class":76,"line":1535},45,[74,1537,694],{"class":271},[74,1539,1541],{"class":76,"line":1540},46,[74,1542,288],{"emptyLinePlaceholder":287},[74,1544,1546,1548,1551,1553,1556,1558],{"class":76,"line":1545},47,[74,1547,293],{"class":267},[74,1549,1550],{"class":296}," app",[74,1552,300],{"class":267},[74,1554,1555],{"class":267}," new",[74,1557,1096],{"class":303},[74,1559,1488],{"class":271},[74,1561,1563,1566,1568],{"class":76,"line":1562},48,[74,1564,1565],{"class":271},"app.",[74,1567,367],{"class":303},[74,1569,1488],{"class":271},[26,1571,1572,1576,1589,1599,1602,1608],{"lang":28},[955,1573,1575],{"id":1574},"why-avoid-mutation","Why avoid mutation?",[30,1577,1578,1579,1581,1582,1585,1586,1329],{},"In the ",[71,1580,1473],{}," method, notice we didn't do ",[71,1583,1584],{},"this.state.value++",". Instead, we created a whole new object: ",[71,1587,1588],{},"this.state = { ...state, value: state.value + 1 }",[30,1590,1591,1592,1594,1595,1329],{},"By reassigning the ",[71,1593,1332],{}," instead of mutating its properties, we preserve the previous state in memory (as long as something holds a reference to it). This is the foundation for features like ",[1596,1597,1598],"strong",{},"Time Traveling",[955,1600,1598],{"id":1601},"time-traveling",[30,1603,1604,1605,1607],{},"Because our ",[71,1606,1473],{}," logic is based on transition from one immutable state to another, we can easily keep track of every state our application has ever been in.",[30,1609,1610],{},"Imagine adding a history array to our class:",[26,1612,1613,1617,1628,1637,1640,1646],{"lang":47},[955,1614,1616],{"id":1615},"por-que-evitar-mutação","Por que evitar mutação?",[30,1618,1619,1620,1622,1623,1625,1626,1329],{},"No método ",[71,1621,1473],{},", observe que não fizemos ",[71,1624,1584],{},". Em vez disso, criamos um objeto totalmente novo: ",[71,1627,1588],{},[30,1629,1630,1631,1633,1634,1636],{},"Ao reatribuir o ",[71,1632,1332],{}," em vez de mutar suas propriedades, preservamos o estado anterior na memória (desde que algo mantenha uma referência a ele). Esta é a base para funcionalidades como ",[1596,1635,1598],{}," (Viagem no Tempo).",[955,1638,1598],{"id":1639},"time-traveling-1",[30,1641,1642,1643,1645],{},"Como nossa lógica de ",[71,1644,1473],{}," é baseada na transição de um estado imutável para outro, podemos facilmente rastrear todos os estados em que nossa aplicação já esteve.",[30,1647,1648],{},"Imagine adicionar um array de histórico à nossa classe:",[64,1650,1652],{"className":258,"code":1651,"language":260,"meta":69,"style":69},"class Counter {\n  state: State = { value: 0 };\n  history: State[] = [];\n\n  dispatch(message: Message) {\n    // Save current state to history before updating\n    this.history.push(this.state);\n\n    this.update(message);\n    this.render();\n  }\n\n  undo() {\n    const previousState = this.history.pop();\n    if (previousState) {\n      this.state = previousState;\n      this.render();\n    }\n  }\n}\n",[71,1653,1654,1662,1679,1696,1700,1714,1719,1736,1740,1750,1760,1764,1768,1775,1794,1802,1814,1824,1828,1832],{"__ignoreMap":69},[74,1655,1656,1658,1660],{"class":76,"line":77},[74,1657,1093],{"class":267},[74,1659,1096],{"class":303},[74,1661,1012],{"class":271},[74,1663,1664,1666,1668,1670,1672,1675,1677],{"class":76,"line":83},[74,1665,1109],{"class":806},[74,1667,810],{"class":267},[74,1669,1007],{"class":303},[74,1671,300],{"class":267},[74,1673,1674],{"class":271}," { value: ",[74,1676,1125],{"class":296},[74,1678,1229],{"class":271},[74,1680,1681,1684,1686,1688,1691,1693],{"class":76,"line":89},[74,1682,1683],{"class":806},"  history",[74,1685,810],{"class":267},[74,1687,1007],{"class":303},[74,1689,1690],{"class":271},"[] ",[74,1692,425],{"class":267},[74,1694,1695],{"class":271}," [];\n",[74,1697,1698],{"class":76,"line":95},[74,1699,288],{"emptyLinePlaceholder":287},[74,1701,1702,1704,1706,1708,1710,1712],{"class":76,"line":101},[74,1703,1452],{"class":303},[74,1705,351],{"class":271},[74,1707,1152],{"class":806},[74,1709,810],{"class":267},[74,1711,1039],{"class":303},[74,1713,816],{"class":271},[74,1715,1716],{"class":76,"line":106},[74,1717,1718],{"class":1103},"    // Save current state to history before updating\n",[74,1720,1721,1723,1726,1729,1731,1733],{"class":76,"line":112},[74,1722,1468],{"class":296},[74,1724,1725],{"class":271},".history.",[74,1727,1728],{"class":303},"push",[74,1730,351],{"class":271},[74,1732,1326],{"class":296},[74,1734,1735],{"class":271},".state);\n",[74,1737,1738],{"class":76,"line":118},[74,1739,288],{"emptyLinePlaceholder":287},[74,1741,1742,1744,1746,1748],{"class":76,"line":123},[74,1743,1468],{"class":296},[74,1745,1329],{"class":271},[74,1747,1473],{"class":303},[74,1749,1476],{"class":271},[74,1751,1752,1754,1756,1758],{"class":76,"line":129},[74,1753,1468],{"class":296},[74,1755,1329],{"class":271},[74,1757,367],{"class":303},[74,1759,1488],{"class":271},[74,1761,1762],{"class":76,"line":135},[74,1763,1283],{"class":271},[74,1765,1766],{"class":76,"line":140},[74,1767,288],{"emptyLinePlaceholder":287},[74,1769,1770,1773],{"class":76,"line":146},[74,1771,1772],{"class":303},"  undo",[74,1774,677],{"class":271},[74,1776,1777,1780,1783,1785,1787,1789,1792],{"class":76,"line":663},[74,1778,1779],{"class":267},"    const",[74,1781,1782],{"class":296}," previousState",[74,1784,300],{"class":267},[74,1786,1176],{"class":296},[74,1788,1725],{"class":271},[74,1790,1791],{"class":303},"pop",[74,1793,1488],{"class":271},[74,1795,1796,1799],{"class":76,"line":668},[74,1797,1798],{"class":267},"    if",[74,1800,1801],{"class":271}," (previousState) {\n",[74,1803,1804,1807,1809,1811],{"class":76,"line":680},[74,1805,1806],{"class":296},"      this",[74,1808,1209],{"class":271},[74,1810,425],{"class":267},[74,1812,1813],{"class":271}," previousState;\n",[74,1815,1816,1818,1820,1822],{"class":76,"line":691},[74,1817,1806],{"class":296},[74,1819,1329],{"class":271},[74,1821,367],{"class":303},[74,1823,1488],{"class":271},[74,1825,1826],{"class":76,"line":915},[74,1827,1277],{"class":271},[74,1829,1830],{"class":76,"line":924},[74,1831,1283],{"class":271},[74,1833,1834],{"class":76,"line":936},[74,1835,694],{"class":271},[26,1837,1838,1841,1845,1851,1854],{"lang":28},[30,1839,1840],{},"With this pattern, implementing \"Undo\" or a full \"Time Travel Debugger\" becomes trivial. You can just store an array of states and jump between them.",[955,1842,1844],{"id":1843},"recap","Recap",[30,1846,1847,1848,1850],{},"At this point, we have a single class as the source of truth for app state and logic. We apply changes by reassigning an immutable state object, and ",[71,1849,1358],{}," acts as the central loop.",[30,1852,1853],{},"This should give you a practical overview of how The Elm Architecture works in a more structured, object-oriented way.",[30,1855,1856],{},"In the next article, we’ll build on this with more realistic examples (form input, async data, and composition patterns).",[26,1858,1859,1862,1866,1872,1875],{"lang":47},[30,1860,1861],{},"Com esse padrão, implementar \"Desfazer\" (Undo) ou um \"Depurador de Viagem no Tempo\" completo torna-se trivial. Você pode apenas armazenar um array de estados e saltar entre eles.",[955,1863,1865],{"id":1864},"recapitulação","Recapitulação",[30,1867,1868,1869,1871],{},"Neste ponto, temos uma única classe como fonte da verdade para o estado e a lógica do app. Aplicamos mudanças reatribuindo um objeto de estado imutável, e o ",[71,1870,1358],{}," atua como o loop central.",[30,1873,1874],{},"Isso deve te dar uma visão prática de como a Elm Architecture funciona de uma maneira mais estruturada e orientada a objetos.",[30,1876,1877],{},"No próximo artigo, construiremos sobre isso com exemplos mais realistas (input de formulário, dados assíncronos e padrões de composição).",[1879,1880,1881],"style",{},"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 .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .s6ubI, html code.shiki .s6ubI{--shiki-default:#F97583;--shiki-dark:#F97583;--shiki-light:#D73A49}html pre.shiki code .sAvwS, html code.shiki .sAvwS{--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8;--shiki-light:#24292E}html pre.shiki code .s4Y1p, html code.shiki .s4Y1p{--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF;--shiki-light:#032F62}html pre.shiki code .sXWYR, html code.shiki .sXWYR{--shiki-default:#79B8FF;--shiki-dark:#79B8FF;--shiki-light:#005CC5}html pre.shiki code .s5n6i, html code.shiki .s5n6i{--shiki-default:#B392F0;--shiki-dark:#B392F0;--shiki-light:#6F42C1}html pre.shiki code .sAzo5, html code.shiki .sAzo5{--shiki-default:#FFAB70;--shiki-dark:#FFAB70;--shiki-light:#E36209}html pre.shiki code .sxXm1, html code.shiki .sxXm1{--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-light:#6A737D}",{"title":69,"searchDepth":83,"depth":83,"links":1883},[1884,1886,1888,1889,1890,1891,1892,1893],{"id":957,"depth":83,"text":1885},"The Counter Application",{"id":985,"depth":83,"text":1887},"A Aplicação Counter",{"id":1574,"depth":83,"text":1575},{"id":1601,"depth":83,"text":1598},{"id":1615,"depth":83,"text":1616},{"id":1639,"depth":83,"text":1598},{"id":1843,"depth":83,"text":1844},{"id":1864,"depth":83,"text":1865},"Learn the core ideas of The Elm Architecture in TypeScript with lit-html: model, view, update, messages, and commands.","Aprenda as ideias centrais da Elm Architecture em TypeScript com lit-html: model, view, update, messages e commands.","md",{},"/blog/learning-tea","2026-05-01",{"title":21,"description":69},"learning-tea","blog/learning-tea",[1904,1905,1906,1907],"javascript","typescript","elm","functional programming","Learning and understanding The Elm Architecture","Aprendendo e entendendo a Elm Architecture","z7xFqAbJnwXUXYOZoZEZ20T1RrH5EFDm_Qma2BE_QTg",1777685535871]