[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-en-vue3-composition-api-fundamentals":3},{"id":4,"title":5,"body":6,"category":664,"date":665,"description":666,"extension":667,"image":668,"meta":669,"navigation":89,"path":678,"readTime":149,"seo":679,"stem":680,"__hash__":681},"blog_en/blog/en/vue3-composition-api-fundamentals.md","Vue 3 Composition API Fundamentals",{"type":7,"value":8,"toc":656},"minimark",[9,13,18,21,50,54,205,209,212,377,381,599,603,642,646,649,652],[10,11,12],"p",{},"Vue 3's Composition API represents a major evolution in how we structure and organize component code. In this article, we'll explore the fundamental concepts and best practices.",[14,15,17],"h2",{"id":16},"why-composition-api","Why Composition API?",[10,19,20],{},"The Composition API offers several significant advantages:",[22,23,24,32,38,44],"ul",{},[25,26,27,31],"li",{},[28,29,30],"strong",{},"Better code organization",": Group logic by feature",[25,33,34,37],{},[28,35,36],{},"Improved reusability",": Create easily shareable composables",[25,39,40,43],{},[28,41,42],{},"Native TypeScript",": Full TypeScript support",[25,45,46,49],{},[28,47,48],{},"Flexibility",": More control over component lifecycle",[14,51,53],{"id":52},"the-basics-ref-and-reactive","The basics: ref and reactive",[55,56,61],"pre",{"className":57,"code":58,"language":59,"meta":60,"style":60},"language-typescript shiki shiki-themes github-dark","import { ref, reactive } from 'vue'\n\n// ref for primitive values\nconst count = ref(0)\ncount.value++ // Access via .value\n\n// reactive for objects\nconst state = reactive({\n  name: 'Vue 3',\n  version: 3.4\n})\nstate.name = 'Vue' // Direct access\n","typescript","",[62,63,64,84,91,98,124,136,141,147,163,175,184,190],"code",{"__ignoreMap":60},[65,66,69,73,77,80],"span",{"class":67,"line":68},"line",1,[65,70,72],{"class":71},"snl16","import",[65,74,76],{"class":75},"s95oV"," { ref, reactive } ",[65,78,79],{"class":71},"from",[65,81,83],{"class":82},"sU2Wk"," 'vue'\n",[65,85,87],{"class":67,"line":86},2,[65,88,90],{"emptyLinePlaceholder":89},true,"\n",[65,92,94],{"class":67,"line":93},3,[65,95,97],{"class":96},"sAwPA","// ref for primitive values\n",[65,99,101,104,108,111,115,118,121],{"class":67,"line":100},4,[65,102,103],{"class":71},"const",[65,105,107],{"class":106},"sDLfK"," count",[65,109,110],{"class":71}," =",[65,112,114],{"class":113},"svObZ"," ref",[65,116,117],{"class":75},"(",[65,119,120],{"class":106},"0",[65,122,123],{"class":75},")\n",[65,125,127,130,133],{"class":67,"line":126},5,[65,128,129],{"class":75},"count.value",[65,131,132],{"class":71},"++",[65,134,135],{"class":96}," // Access via .value\n",[65,137,139],{"class":67,"line":138},6,[65,140,90],{"emptyLinePlaceholder":89},[65,142,144],{"class":67,"line":143},7,[65,145,146],{"class":96},"// reactive for objects\n",[65,148,150,152,155,157,160],{"class":67,"line":149},8,[65,151,103],{"class":71},[65,153,154],{"class":106}," state",[65,156,110],{"class":71},[65,158,159],{"class":113}," reactive",[65,161,162],{"class":75},"({\n",[65,164,166,169,172],{"class":67,"line":165},9,[65,167,168],{"class":75},"  name: ",[65,170,171],{"class":82},"'Vue 3'",[65,173,174],{"class":75},",\n",[65,176,178,181],{"class":67,"line":177},10,[65,179,180],{"class":75},"  version: ",[65,182,183],{"class":106},"3.4\n",[65,185,187],{"class":67,"line":186},11,[65,188,189],{"class":75},"})\n",[65,191,193,196,199,202],{"class":67,"line":192},12,[65,194,195],{"class":75},"state.name ",[65,197,198],{"class":71},"=",[65,200,201],{"class":82}," 'Vue'",[65,203,204],{"class":96}," // Direct access\n",[14,206,208],{"id":207},"creating-a-composable","Creating a composable",[10,210,211],{},"Composables are functions that encapsulate and reuse stateful logic:",[55,213,215],{"className":57,"code":214,"language":59,"meta":60,"style":60},"// composables/useCounter.ts\nexport function useCounter(initialValue = 0) {\n  const count = ref(initialValue)\n  \n  const increment = () => count.value++\n  const decrement = () => count.value--\n  const reset = () => count.value = initialValue\n  \n  return {\n    count: readonly(count),\n    increment,\n    decrement,\n    reset\n  }\n}\n",[62,216,217,222,247,261,266,287,305,326,330,338,349,354,359,365,371],{"__ignoreMap":60},[65,218,219],{"class":67,"line":68},[65,220,221],{"class":96},"// composables/useCounter.ts\n",[65,223,224,227,230,233,235,239,241,244],{"class":67,"line":86},[65,225,226],{"class":71},"export",[65,228,229],{"class":71}," function",[65,231,232],{"class":113}," useCounter",[65,234,117],{"class":75},[65,236,238],{"class":237},"s9osk","initialValue",[65,240,110],{"class":71},[65,242,243],{"class":106}," 0",[65,245,246],{"class":75},") {\n",[65,248,249,252,254,256,258],{"class":67,"line":93},[65,250,251],{"class":71},"  const",[65,253,107],{"class":106},[65,255,110],{"class":71},[65,257,114],{"class":113},[65,259,260],{"class":75},"(initialValue)\n",[65,262,263],{"class":67,"line":100},[65,264,265],{"class":75},"  \n",[65,267,268,270,273,275,278,281,284],{"class":67,"line":126},[65,269,251],{"class":71},[65,271,272],{"class":113}," increment",[65,274,110],{"class":71},[65,276,277],{"class":75}," () ",[65,279,280],{"class":71},"=>",[65,282,283],{"class":75}," count.value",[65,285,286],{"class":71},"++\n",[65,288,289,291,294,296,298,300,302],{"class":67,"line":138},[65,290,251],{"class":71},[65,292,293],{"class":113}," decrement",[65,295,110],{"class":71},[65,297,277],{"class":75},[65,299,280],{"class":71},[65,301,283],{"class":75},[65,303,304],{"class":71},"--\n",[65,306,307,309,312,314,316,318,321,323],{"class":67,"line":143},[65,308,251],{"class":71},[65,310,311],{"class":113}," reset",[65,313,110],{"class":71},[65,315,277],{"class":75},[65,317,280],{"class":71},[65,319,320],{"class":75}," count.value ",[65,322,198],{"class":71},[65,324,325],{"class":75}," initialValue\n",[65,327,328],{"class":67,"line":149},[65,329,265],{"class":75},[65,331,332,335],{"class":67,"line":165},[65,333,334],{"class":71},"  return",[65,336,337],{"class":75}," {\n",[65,339,340,343,346],{"class":67,"line":177},[65,341,342],{"class":75},"    count: ",[65,344,345],{"class":113},"readonly",[65,347,348],{"class":75},"(count),\n",[65,350,351],{"class":67,"line":186},[65,352,353],{"class":75},"    increment,\n",[65,355,356],{"class":67,"line":192},[65,357,358],{"class":75},"    decrement,\n",[65,360,362],{"class":67,"line":361},13,[65,363,364],{"class":75},"    reset\n",[65,366,368],{"class":67,"line":367},14,[65,369,370],{"class":75},"  }\n",[65,372,374],{"class":67,"line":373},15,[65,375,376],{"class":75},"}\n",[14,378,380],{"id":379},"watchers-and-computed","Watchers and computed",[55,382,384],{"className":57,"code":383,"language":59,"meta":60,"style":60},"import { computed, watch, watchEffect } from 'vue'\n\nconst firstName = ref('John')\nconst lastName = ref('Doe')\n\n// Computed property\nconst fullName = computed(() => `${firstName.value} ${lastName.value}`)\n\n// Specific watch\nwatch(firstName, (newVal, oldVal) => {\n  console.log(`First name changed from ${oldVal} to ${newVal}`)\n})\n\n// WatchEffect for reactive effects\nwatchEffect(() => {\n  console.log(`Full name: ${fullName.value}`)\n})\n",[62,385,386,397,401,419,437,441,446,490,494,499,523,547,551,555,560,571,594],{"__ignoreMap":60},[65,387,388,390,393,395],{"class":67,"line":68},[65,389,72],{"class":71},[65,391,392],{"class":75}," { computed, watch, watchEffect } ",[65,394,79],{"class":71},[65,396,83],{"class":82},[65,398,399],{"class":67,"line":86},[65,400,90],{"emptyLinePlaceholder":89},[65,402,403,405,408,410,412,414,417],{"class":67,"line":93},[65,404,103],{"class":71},[65,406,407],{"class":106}," firstName",[65,409,110],{"class":71},[65,411,114],{"class":113},[65,413,117],{"class":75},[65,415,416],{"class":82},"'John'",[65,418,123],{"class":75},[65,420,421,423,426,428,430,432,435],{"class":67,"line":100},[65,422,103],{"class":71},[65,424,425],{"class":106}," lastName",[65,427,110],{"class":71},[65,429,114],{"class":113},[65,431,117],{"class":75},[65,433,434],{"class":82},"'Doe'",[65,436,123],{"class":75},[65,438,439],{"class":67,"line":126},[65,440,90],{"emptyLinePlaceholder":89},[65,442,443],{"class":67,"line":138},[65,444,445],{"class":96},"// Computed property\n",[65,447,448,450,453,455,458,461,463,466,469,472,475,478,481,483,485,488],{"class":67,"line":143},[65,449,103],{"class":71},[65,451,452],{"class":106}," fullName",[65,454,110],{"class":71},[65,456,457],{"class":113}," computed",[65,459,460],{"class":75},"(() ",[65,462,280],{"class":71},[65,464,465],{"class":82}," `${",[65,467,468],{"class":75},"firstName",[65,470,471],{"class":82},".",[65,473,474],{"class":75},"value",[65,476,477],{"class":82},"} ${",[65,479,480],{"class":75},"lastName",[65,482,471],{"class":82},[65,484,474],{"class":75},[65,486,487],{"class":82},"}`",[65,489,123],{"class":75},[65,491,492],{"class":67,"line":149},[65,493,90],{"emptyLinePlaceholder":89},[65,495,496],{"class":67,"line":165},[65,497,498],{"class":96},"// Specific watch\n",[65,500,501,504,507,510,513,516,519,521],{"class":67,"line":177},[65,502,503],{"class":113},"watch",[65,505,506],{"class":75},"(firstName, (",[65,508,509],{"class":237},"newVal",[65,511,512],{"class":75},", ",[65,514,515],{"class":237},"oldVal",[65,517,518],{"class":75},") ",[65,520,280],{"class":71},[65,522,337],{"class":75},[65,524,525,528,531,533,536,538,541,543,545],{"class":67,"line":186},[65,526,527],{"class":75},"  console.",[65,529,530],{"class":113},"log",[65,532,117],{"class":75},[65,534,535],{"class":82},"`First name changed from ${",[65,537,515],{"class":75},[65,539,540],{"class":82},"} to ${",[65,542,509],{"class":75},[65,544,487],{"class":82},[65,546,123],{"class":75},[65,548,549],{"class":67,"line":192},[65,550,189],{"class":75},[65,552,553],{"class":67,"line":361},[65,554,90],{"emptyLinePlaceholder":89},[65,556,557],{"class":67,"line":367},[65,558,559],{"class":96},"// WatchEffect for reactive effects\n",[65,561,562,565,567,569],{"class":67,"line":373},[65,563,564],{"class":113},"watchEffect",[65,566,460],{"class":75},[65,568,280],{"class":71},[65,570,337],{"class":75},[65,572,574,576,578,580,583,586,588,590,592],{"class":67,"line":573},16,[65,575,527],{"class":75},[65,577,530],{"class":113},[65,579,117],{"class":75},[65,581,582],{"class":82},"`Full name: ${",[65,584,585],{"class":75},"fullName",[65,587,471],{"class":82},[65,589,474],{"class":75},[65,591,487],{"class":82},[65,593,123],{"class":75},[65,595,597],{"class":67,"line":596},17,[65,598,189],{"class":75},[14,600,602],{"id":601},"best-practices","Best practices",[604,605,606,625,631,636],"ol",{},[25,607,608,615,616,512,619,512,622],{},[28,609,610,611,614],{},"Name your composables with the ",[62,612,613],{},"use"," prefix",": ",[62,617,618],{},"useUser",[62,620,621],{},"useAuth",[62,623,624],{},"useFetch",[25,626,627,630],{},[28,628,629],{},"Return readonly refs"," when possible to avoid accidental modifications",[25,632,633],{},[28,634,635],{},"Document parameters and return values",[25,637,638,641],{},[28,639,640],{},"Keep composables focused"," on a single responsibility",[14,643,645],{"id":644},"conclusion","Conclusion",[10,647,648],{},"Vue 3's Composition API opens new possibilities for structuring your applications in a more maintainable and reusable way. By mastering these fundamentals, you'll be able to create cleaner and more performant components.",[10,650,651],{},"Feel free to share your questions in the comments below!",[653,654,655],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}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 pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":60,"searchDepth":86,"depth":86,"links":657},[658,659,660,661,662,663],{"id":16,"depth":86,"text":17},{"id":52,"depth":86,"text":53},{"id":207,"depth":86,"text":208},{"id":379,"depth":86,"text":380},{"id":601,"depth":86,"text":602},{"id":644,"depth":86,"text":645},"Web Development","2025-12-15T14:00:00+01:00","Discover how to master Vue 3's Composition API and improve code reusability with composables.","md","/images/blog/en/vue3-composition-api-fundamentals.png",{"tags":670,"author":674,"locale":675,"slug":676,"draft":677,"sitemap":89},[671,672,673],"Vue.js","JavaScript","Frontend","Aboubakar Sidik Faha","en","vue3-composition-api-fundamentals",false,"/blog/en/vue3-composition-api-fundamentals",{"title":5,"description":666},"blog/en/vue3-composition-api-fundamentals","muHtQAhPSn4xBIpz927mr1ZWsRxCPNTadyuNW_dx9es"]