[{"data":1,"prerenderedAt":772},["ShallowReactive",2],{"page-\u002Fvue\u002Fpremier-composant":3,"pieces-vue":727,"autour-\u002Fvue\u002Fpremier-composant":752,"prerequis-\u002Fvue\u002Fpremier-composant":757,"plan-vue":761},{"id":4,"title":5,"body":6,"description":697,"extension":698,"ligne":200,"meta":699,"motsCles":700,"navigation":238,"niveau":705,"path":706,"prerequis":707,"ressources":709,"seo":718,"sources":719,"stem":725,"__hash__":726},"docs\u002Fvue\u002F01.premier-composant.md","Ton premier composant Vue",{"type":7,"value":8,"toc":685},"minimark",[9,14,44,48,56,59,74,78,89,114,117,120,123,156,159,172,176,195,391,394,445,451,458,473,484,488,494,582,589,598,602,614,620,624,639,643,682],[10,11,13],"h2",{"id":12},"ce-que-tu-vas-apprendre","Ce que tu vas apprendre",[15,16,17,21,24],"ul",{},[18,19,20],"li",{},"Ce qu'est Vue et à quoi sert un composant.",[18,22,23],{},"Créer un projet Vue 3 et le lancer sur ton ordinateur.",[18,25,26,27,31,32,35,36,39,40,43],{},"Lire un fichier ",[28,29,30],"code",{},".vue"," : ses trois blocs ",[28,33,34],{},"\u003Cscript setup>",", ",[28,37,38],{},"\u003Ctemplate>"," et ",[28,41,42],{},"\u003Cstyle>",".",[10,45,47],{"id":46},"vue-cest-quoi","Vue, c'est quoi ?",[49,50,51,55],"p",{},[52,53,54],"strong",{},"Vue"," est un framework JavaScript qui construit des interfaces web. Tu décris ce que la page doit afficher, et Vue met l'affichage à jour tout seul quand tes données changent.",[49,57,58],{},"Tu n'as plus à chercher des éléments HTML pour modifier leur texte. Tu modifies une variable, et la page suit.",[49,60,61,62,65,66,39,69,71,72,43],{},"Dans tout ce cours, on utilise ",[52,63,64],{},"Vue 3"," avec la ",[52,67,68],{},"Composition API",[28,70,34],{},". C'est la façon d'écrire que la documentation associe aux fichiers ",[28,73,30],{},[10,75,77],{"id":76},"créer-un-projet","Créer un projet",[49,79,80,81,84,85,88],{},"Il te faut Node.js, que tu as croisé avec JavaScript. La documentation demande la version ",[28,82,83],{},"^22.18.0"," ou ",[28,86,87],{},">=24.12.0",". Ensuite, dans un terminal :",[90,91,96],"pre",{"className":92,"code":93,"language":94,"meta":95,"style":95},"language-bash shiki shiki-themes github-light-default github-dark-default github-dark-default","npm create vue@latest\n","bash","",[28,97,98],{"__ignoreMap":95},[99,100,103,107,111],"span",{"class":101,"line":102},"line",1,[99,104,106],{"class":105},"sIXEE","npm",[99,108,110],{"class":109},"shWOn"," create",[99,112,113],{"class":109}," vue@latest\n",[49,115,116],{},"Cette commande lance l'outil officiel de création de projet. Il te demande le nom du projet, puis pose des questions oui ou non : TypeScript, Vue Router, Pinia, tests, ESLint, Prettier...",[49,118,119],{},"Si tu hésites sur une option, la documentation conseille de répondre « non ».",[49,121,122],{},"Pour lancer le projet :",[90,124,126],{"className":92,"code":125,"language":94,"meta":95,"style":95},"cd mon-site-recettes\nnpm install\nnpm run dev\n",[28,127,128,137,145],{"__ignoreMap":95},[99,129,130,134],{"class":101,"line":102},[99,131,133],{"class":132},"s5iOY","cd",[99,135,136],{"class":109}," mon-site-recettes\n",[99,138,140,142],{"class":101,"line":139},2,[99,141,106],{"class":105},[99,143,144],{"class":109}," install\n",[99,146,148,150,153],{"class":101,"line":147},3,[99,149,106],{"class":105},[99,151,152],{"class":109}," run",[99,154,155],{"class":109}," dev\n",[49,157,158],{},"Le terminal affiche une adresse locale. Ouvre-la dans ton navigateur pour voir ton application.",[160,161,162],"note",{},[49,163,164,167,168,171],{},[28,165,166],{},"npm run build"," prépare la version finale du site dans le dossier ",[28,169,170],{},"dist",". Tu n'en as pas besoin pour apprendre.",[10,173,175],{"id":174},"le-composant-monofichier","Le composant monofichier",[49,177,178,179,182,183,186,187,191,192,194],{},"Un ",[52,180,181],{},"composant"," est un morceau d'interface réutilisable : un bouton, une carte de recette, un menu. Vue le range dans un ",[52,184,185],{},"composant monofichier"," (en anglais ",[188,189,190],"em",{},"single-file component",", ou SFC), un fichier ",[28,193,30],{}," qui regroupe la logique, le HTML et le style.",[90,196,201],{"className":197,"code":198,"filename":199,"language":200,"meta":95,"style":95},"language-vue shiki shiki-themes github-light-default github-dark-default github-dark-default","\u003Cscript setup>\nimport { ref } from 'vue'\n\nconst nombre = ref(0)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton @click=\"nombre++\">\n    Recettes aimées : {{ nombre }}\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cstyle scoped>\nbutton {\n  font-weight: bold;\n}\n\u003C\u002Fstyle>\n","src\u002Fcomponents\u002FCompteurRecettes.vue","vue",[28,202,203,219,234,240,265,275,280,290,310,316,326,335,340,353,361,376,382],{"__ignoreMap":95},[99,204,205,209,213,216],{"class":101,"line":102},[99,206,208],{"class":207},"scfrF","\u003C",[99,210,212],{"class":211},"s5JFL","script",[99,214,215],{"class":132}," setup",[99,217,218],{"class":207},">\n",[99,220,221,225,228,231],{"class":101,"line":139},[99,222,224],{"class":223},"sOnC1","import",[99,226,227],{"class":207}," { ref } ",[99,229,230],{"class":223},"from",[99,232,233],{"class":109}," 'vue'\n",[99,235,236],{"class":101,"line":147},[99,237,239],{"emptyLinePlaceholder":238},true,"\n",[99,241,243,246,249,252,256,259,262],{"class":101,"line":242},4,[99,244,245],{"class":223},"const",[99,247,248],{"class":132}," nombre",[99,250,251],{"class":223}," =",[99,253,255],{"class":254},"syCW7"," ref",[99,257,258],{"class":207},"(",[99,260,261],{"class":132},"0",[99,263,264],{"class":207},")\n",[99,266,268,271,273],{"class":101,"line":267},5,[99,269,270],{"class":207},"\u003C\u002F",[99,272,212],{"class":211},[99,274,218],{"class":207},[99,276,278],{"class":101,"line":277},6,[99,279,239],{"emptyLinePlaceholder":238},[99,281,283,285,288],{"class":101,"line":282},7,[99,284,208],{"class":207},[99,286,287],{"class":211},"template",[99,289,218],{"class":207},[99,291,293,296,299,302,305,308],{"class":101,"line":292},8,[99,294,295],{"class":207},"  \u003C",[99,297,298],{"class":211},"button",[99,300,301],{"class":132}," @click",[99,303,304],{"class":207},"=",[99,306,307],{"class":109},"\"nombre++\"",[99,309,218],{"class":207},[99,311,313],{"class":101,"line":312},9,[99,314,315],{"class":207},"    Recettes aimées : {{ nombre }}\n",[99,317,319,322,324],{"class":101,"line":318},10,[99,320,321],{"class":207},"  \u003C\u002F",[99,323,298],{"class":211},[99,325,218],{"class":207},[99,327,329,331,333],{"class":101,"line":328},11,[99,330,270],{"class":207},[99,332,287],{"class":211},[99,334,218],{"class":207},[99,336,338],{"class":101,"line":337},12,[99,339,239],{"emptyLinePlaceholder":238},[99,341,343,345,348,351],{"class":101,"line":342},13,[99,344,208],{"class":207},[99,346,347],{"class":211},"style",[99,349,350],{"class":132}," scoped",[99,352,218],{"class":207},[99,354,356,358],{"class":101,"line":355},14,[99,357,298],{"class":211},[99,359,360],{"class":207}," {\n",[99,362,364,367,370,373],{"class":101,"line":363},15,[99,365,366],{"class":132},"  font-weight",[99,368,369],{"class":207},": ",[99,371,372],{"class":132},"bold",[99,374,375],{"class":207},";\n",[99,377,379],{"class":101,"line":378},16,[99,380,381],{"class":207},"}\n",[99,383,385,387,389],{"class":101,"line":384},17,[99,386,270],{"class":207},[99,388,347],{"class":211},[99,390,218],{"class":207},[49,392,393],{},"Ce fichier contient trois blocs :",[395,396,397,410],"table",{},[398,399,400],"thead",{},[401,402,403,407],"tr",{},[404,405,406],"th",{},"Bloc",[404,408,409],{},"Rôle",[411,412,413,423,432],"tbody",{},[401,414,415,420],{},[416,417,418],"td",{},[28,419,34],{},[416,421,422],{},"La logique : les données et les fonctions du composant.",[401,424,425,429],{},[416,426,427],{},[28,428,38],{},[416,430,431],{},"Le HTML affiché, avec la syntaxe de Vue.",[401,433,434,439],{},[416,435,436],{},[28,437,438],{},"\u003Cstyle scoped>",[416,440,441,442,43],{},"Le CSS, limité à ce composant grâce à ",[28,443,444],{},"scoped",[10,446,448,449],{"id":447},"ce-qui-se-passe-dans-script-setup","Ce qui se passe dans ",[28,450,34],{},[49,452,453,454,457],{},"L'attribut ",[28,455,456],{},"setup"," permet à Vue de transformer le code à la compilation. Les imports et les variables déclarés au premier niveau du script sont utilisables directement dans le template, sans rien exporter.",[49,459,460,461,464,465,468,469,472],{},"Ici, ",[28,462,463],{},"nombre"," est déclaré avec ",[28,466,467],{},"ref(0)",". Un ",[52,470,471],{},"ref"," est une valeur que Vue surveille : quand elle change, l'affichage est mis à jour. On le détaille au chapitre sur la réactivité.",[49,474,475,476,479,480,483],{},"Dans le template, ",[28,477,478],{},"{{ nombre }}"," affiche la valeur et ",[28,481,482],{},"@click=\"nombre++\""," ajoute 1 à chaque clic.",[10,485,487],{"id":486},"utiliser-un-composant-dans-un-autre","Utiliser un composant dans un autre",[49,489,490,491,493],{},"Dans ",[28,492,34],{},", un composant importé est utilisable tout de suite dans le template :",[90,495,498],{"className":197,"code":496,"filename":497,"language":200,"meta":95,"style":95},"\u003Cscript setup>\nimport CompteurRecettes from '.\u002Fcomponents\u002FCompteurRecettes.vue'\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Ch1>Mes recettes\u003C\u002Fh1>\n  \u003CCompteurRecettes \u002F>\n  \u003CCompteurRecettes \u002F>\n\u003C\u002Ftemplate>\n","src\u002FApp.vue",[28,499,500,510,522,530,534,542,556,566,574],{"__ignoreMap":95},[99,501,502,504,506,508],{"class":101,"line":102},[99,503,208],{"class":207},[99,505,212],{"class":211},[99,507,215],{"class":132},[99,509,218],{"class":207},[99,511,512,514,517,519],{"class":101,"line":139},[99,513,224],{"class":223},[99,515,516],{"class":207}," CompteurRecettes ",[99,518,230],{"class":223},[99,520,521],{"class":109}," '.\u002Fcomponents\u002FCompteurRecettes.vue'\n",[99,523,524,526,528],{"class":101,"line":147},[99,525,270],{"class":207},[99,527,212],{"class":211},[99,529,218],{"class":207},[99,531,532],{"class":101,"line":242},[99,533,239],{"emptyLinePlaceholder":238},[99,535,536,538,540],{"class":101,"line":267},[99,537,208],{"class":207},[99,539,287],{"class":211},[99,541,218],{"class":207},[99,543,544,546,549,552,554],{"class":101,"line":277},[99,545,295],{"class":207},[99,547,548],{"class":211},"h1",[99,550,551],{"class":207},">Mes recettes\u003C\u002F",[99,553,548],{"class":211},[99,555,218],{"class":207},[99,557,558,560,563],{"class":101,"line":282},[99,559,295],{"class":207},[99,561,562],{"class":211},"CompteurRecettes",[99,564,565],{"class":207}," \u002F>\n",[99,567,568,570,572],{"class":101,"line":292},[99,569,295],{"class":207},[99,571,562],{"class":211},[99,573,565],{"class":207},[99,575,576,578,580],{"class":101,"line":312},[99,577,270],{"class":207},[99,579,287],{"class":211},[99,581,218],{"class":207},[49,583,584,585,588],{},"Chaque ",[28,586,587],{},"\u003CCompteurRecettes \u002F>"," est une copie indépendante. Cliquer sur l'un ne change pas l'autre : chaque composant garde ses propres données.",[590,591,592],"tip",{},[49,593,594,595,597],{},"Écris le nom d'un composant en PascalCase, avec une majuscule à chaque mot (",[28,596,562],{},"). Tu le distingues ainsi d'une balise HTML normale.",[10,599,601],{"id":600},"les-trois-blocs-dans-la-pratique","Les trois blocs dans la pratique",[49,603,604,605,607,608,610,611,613],{},"Le bloc ",[28,606,438],{}," évite les mauvaises surprises : la règle ",[28,609,298],{}," du composant ci-dessus ne touche pas les boutons des autres composants. Sans ",[28,612,444],{},", le CSS s'appliquerait à toute la page.",[49,615,616,617,619],{},"Garde une règle simple : un fichier ",[28,618,30],{}," par composant, et un composant par idée (une carte de recette, une liste, un formulaire).",[10,621,623],{"id":622},"pour-texercer","Pour t'exercer",[49,625,626,627,630,631,634,635,638],{},"Crée un composant ",[28,628,629],{},"MessageAccueil.vue"," qui affiche un titre et le nombre de recettes d'une variable ",[28,632,633],{},"total",". Importe-le dans ",[28,636,637],{},"App.vue"," et affiche-le deux fois. Tu as alors manipulé tout ce chapitre.",[10,640,642],{"id":641},"à-retenir","À retenir",[15,644,645,648,661,673,679],{},[18,646,647],{},"Vue met l'affichage à jour tout seul quand les données changent.",[18,649,650,653,654,39,657,660],{},[28,651,652],{},"npm create vue@latest"," crée un projet, puis ",[28,655,656],{},"npm install",[28,658,659],{},"npm run dev"," le lancent.",[18,662,663,664,666,667,35,669,39,671,43],{},"Un composant monofichier ",[28,665,30],{}," regroupe ",[28,668,34],{},[28,670,38],{},[28,672,438],{},[18,674,675,676,678],{},"Ce que tu déclares dans ",[28,677,34],{}," est utilisable dans le template.",[18,680,681],{},"On importe un composant, puis on l'écrit comme une balise, en PascalCase.",[347,683,684],{},"html pre.shiki code .sIXEE, html code.shiki .sIXEE{--shiki-light:#953800;--shiki-default:#FFA657;--shiki-dark:#FFA657}html pre.shiki code .shWOn, html code.shiki .shWOn{--shiki-light:#0A3069;--shiki-default:#A5D6FF;--shiki-dark:#A5D6FF}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 .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 .s5iOY, html code.shiki .s5iOY{--shiki-light:#0550AE;--shiki-default:#79C0FF;--shiki-dark:#79C0FF}html pre.shiki code .scfrF, html code.shiki .scfrF{--shiki-light:#1F2328;--shiki-default:#E6EDF3;--shiki-dark:#E6EDF3}html pre.shiki code .s5JFL, html code.shiki .s5JFL{--shiki-light:#116329;--shiki-default:#7EE787;--shiki-dark:#7EE787}html pre.shiki code .sOnC1, html code.shiki .sOnC1{--shiki-light:#CF222E;--shiki-default:#FF7B72;--shiki-dark:#FF7B72}html pre.shiki code .syCW7, html code.shiki .syCW7{--shiki-light:#8250DF;--shiki-default:#D2A8FF;--shiki-dark:#D2A8FF}",{"title":95,"searchDepth":139,"depth":147,"links":686},[687,688,689,690,691,693,694,695,696],{"id":12,"depth":139,"text":13},{"id":46,"depth":139,"text":47},{"id":76,"depth":139,"text":77},{"id":174,"depth":139,"text":175},{"id":447,"depth":139,"text":692},"Ce qui se passe dans \u003Cscript setup>",{"id":486,"depth":139,"text":487},{"id":600,"depth":139,"text":601},{"id":622,"depth":139,"text":623},{"id":641,"depth":139,"text":642},"Créer un projet Vue 3 avec l'outil officiel, découvrir le composant monofichier .vue et la syntaxe script setup.","md",{},[64,181,701,702,703,68,287,704],"fichier .vue","script setup","create-vue","style scoped","debutant","\u002Fvue\u002Fpremier-composant",[708],"\u002Fjs\u002Fpremiers-pas",[710,714],{"nom":711,"url":712,"type":713},"Vue.js, introduction (documentation officielle)","https:\u002F\u002Ffr.vuejs.org\u002Fguide\u002Fintroduction.html","doc",{"nom":715,"url":716,"type":717},"Vue.js, tutoriel interactif (documentation officielle)","https:\u002F\u002Ffr.vuejs.org\u002Ftutorial\u002F","exercice",{"title":5,"description":697},[720,722],{"nom":721,"url":712},"Introduction à Vue (documentation officielle en français)",{"nom":723,"url":724},"Démarrage rapide de Vue (documentation officielle en français)","https:\u002F\u002Ffr.vuejs.org\u002Fguide\u002Fquick-start.html","vue\u002F01.premier-composant","TxGa4nBJyowYrr1iRpZKCm7m0PPR89DC6hCoQk5IAkM",[728,729,733,737,741,745,749],{"path":706,"title":5,"stem":725},{"path":730,"title":731,"stem":732},"\u002Fvue\u002Ftemplate-et-directives","Le template et les directives","vue\u002F02.template-et-directives",{"path":734,"title":735,"stem":736},"\u002Fvue\u002Freactivite","La réactivité","vue\u002F03.reactivite",{"path":738,"title":739,"stem":740},"\u002Fvue\u002Fprops-et-evenements","Props, événements et v-model sur un composant","vue\u002F04.props-et-evenements",{"path":742,"title":743,"stem":744},"\u002Fvue\u002Fslots-watch-et-cycle-de-vie","Slots, watch et cycle de vie","vue\u002F05.slots-watch-et-cycle-de-vie",{"path":746,"title":747,"stem":748},"\u002Fvue\u002Fcomposables","Les composables","vue\u002F06.composables",{"path":750,"title":54,"stem":751},"\u002Fvue","vue\u002Findex",[753,755],{"title":54,"path":750,"stem":751,"description":754,"children":-1},"Le mémo de Vue 3 : création de projet, template, réactivité, props, événements, slots, watch et composables.",{"title":731,"path":730,"stem":732,"description":756,"children":-1},"Afficher des données avec l'interpolation, lier des attributs avec v-bind, réagir aux clics avec v-on, puis afficher selon une condition ou une liste.",[758],{"path":708,"title":759,"ligne":760},"Premiers pas en JavaScript","js",[762,763,764,765,767,768,770],{"path":706,"title":5,"niveau":705,"stem":725},{"path":730,"title":731,"niveau":705,"stem":732},{"path":734,"title":735,"niveau":705,"stem":736},{"path":738,"title":739,"niveau":766,"stem":740},"intermediaire",{"path":742,"title":743,"niveau":766,"stem":744},{"path":746,"title":747,"niveau":769,"stem":748},"avance",{"path":750,"title":54,"niveau":771,"stem":751},"memo",1794583438223]