[{"data":1,"prerenderedAt":1727},["ShallowReactive",2],{"blog-react-vue":3},{"id":4,"title":5,"author":6,"authorSlug":7,"body":8,"date":1715,"description":1716,"extension":1717,"faq":7,"featured":1718,"image":1719,"meta":1720,"navigation":461,"path":1721,"readTime":7,"seo":1722,"stem":1723,"tags":1724,"__hash__":1726},"blog\u002Fblog\u002Freact-vue.md","React vs Vue: Common Patterns Between Frameworks","Epicmax Team",null,{"type":9,"value":10,"toc":1704},"minimark",[11,15,18,21,38,43,46,49,52,158,162,165,248,251,356,359,363,366,614,617,822,841,845,848,873,876,905,908,974,977,1112,1116,1119,1158,1161,1197,1204,1289,1293,1295,1353,1355,1397,1400,1404,1406,1452,1454,1522,1525,1571,1574,1580,1644,1647,1679,1685,1689,1692,1695,1700],[12,13,14],"p",{},"After six years of working with React, I transitioned to Vue about a year ago. Since then, I've built everything from UI libraries to full-scale applications using Vue.",[12,16,17],{},"This article is meant to help React developers understand key patterns and how they translate into Vue. If you're looking to expand your frontend skills or explore another popular JavaScript framework, this React-to-Vue comparison should make the transition smoother.",[12,19,20],{},"If you are coming from a React background and already have basic knowledge of Vue, you might benefit from more detailed articles on advanced techniques:",[22,23,24,32],"ul",{},[25,26,27],"li",{},[28,29,31],"a",{"href":30},"\u002Fblog\u002Ffixing-vue-sfc-templates-for-react","Fixing Vue SFC templates for React developers",[25,33,34],{},[28,35,37],{"href":36},"\u002Fblog\u002Fusing-jsx-with-vue","Using JSX with Vue",[39,40,42],"h2",{"id":41},"overview-react-vs-vue","Overview: React vs Vue",[12,44,45],{},"React and Vue.js are two of the most popular frontend frameworks for building user interfaces. While they share similar goals, they differ in syntax and architectural philosophy.",[12,47,48],{},"Teams planning to upgrade or migrate projects may benefit from guidance from a Vue.js migration company to ensure best practices and a seamless transition.",[12,50,51],{},"This guide compares common React patterns to their Vue counterparts so that React developers can quickly understand Vue's approach. Here is a comparison table of React features and their equivalents in Vue:",[53,54,55,71],"table",{},[56,57,58],"thead",{},[59,60,61,65,68],"tr",{},[62,63,64],"th",{},"Concern",[62,66,67],{},"React",[62,69,70],{},"Vue",[72,73,74,86,97,108,119,130,141],"tbody",{},[59,75,76,80,83],{},[77,78,79],"td",{},"Defining markup to render",[77,81,82],{},"JSX",[77,84,85],{},"Templates",[59,87,88,91,94],{},[77,89,90],{},"Reuse logic between components",[77,92,93],{},"Hooks",[77,95,96],{},"Composables",[59,98,99,102,105],{},[77,100,101],{},"Passing data between components",[77,103,104],{},"Callback props",[77,106,107],{},"Events",[59,109,110,113,116],{},[77,111,112],{},"Passing content to render",[77,114,115],{},"JSX as a prop",[77,117,118],{},"Slots",[59,120,121,124,127],{},[77,122,123],{},"Rendering content based on data",[77,125,126],{},"Render props",[77,128,129],{},"Scoped slots",[59,131,132,135,138],{},[77,133,134],{},"Sharing state deeply",[77,136,137],{},"Context",[77,139,140],{},"Provide \u002F inject",[59,142,143,146,153],{},[77,144,145],{},"Polymorphic components",[77,147,148,152],{},[149,150,151],"code",{},"as"," prop",[77,154,155],{},[149,156,157],{},"\u003Ccomponent :is=\"...\" >",[39,159,161],{"id":160},"jsx-vs-templates-in-vue","JSX vs templates in Vue",[12,163,164],{},"React uses JSX to define markup directly in JavaScript:",[166,167,172],"pre",{"className":168,"code":169,"language":170,"meta":171,"style":171},"language-jsx shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Component.jsx\nexport default function Component({ greeting }) {\n  return \u003Cp>{greeting}\u003C\u002Fp>;\n}\n","jsx","",[149,173,174,183,215,242],{"__ignoreMap":171},[175,176,179],"span",{"class":177,"line":178},"line",1,[175,180,182],{"class":181},"sHwdD","\u002F\u002F Component.jsx\n",[175,184,186,190,193,197,201,205,209,212],{"class":177,"line":185},2,[175,187,189],{"class":188},"s7zQu","export",[175,191,192],{"class":188}," default",[175,194,196],{"class":195},"spNyl"," function",[175,198,200],{"class":199},"s2Zo4"," Component",[175,202,204],{"class":203},"sMK4o","({",[175,206,208],{"class":207},"sHdIc"," greeting",[175,210,211],{"class":203}," })",[175,213,214],{"class":203}," {\n",[175,216,218,221,224,227,230,234,237,239],{"class":177,"line":217},3,[175,219,220],{"class":188},"  return",[175,222,223],{"class":203}," \u003C",[175,225,12],{"class":226},"swJcz",[175,228,229],{"class":203},">{",[175,231,233],{"class":232},"sTEyZ","greeting",[175,235,236],{"class":203},"}\u003C\u002F",[175,238,12],{"class":226},[175,240,241],{"class":203},">;\n",[175,243,245],{"class":177,"line":244},4,[175,246,247],{"class":203},"}\n",[12,249,250],{},"Vue uses HTML-based templates in Single-File Components (SFCs):",[166,252,256],{"className":253,"code":254,"language":255,"meta":171,"style":171},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!-- Component.vue -->\n\u003Cscript setup>\nconst props = defineProps(['greeting']);\n\u003C\u002Fscript>\n\u003Ctemplate>\n  \u003Cp>{{ greeting }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n","vue",[149,257,258,263,277,308,317,327,347],{"__ignoreMap":171},[175,259,260],{"class":177,"line":178},[175,261,262],{"class":181},"\u003C!-- Component.vue -->\n",[175,264,265,268,271,274],{"class":177,"line":185},[175,266,267],{"class":203},"\u003C",[175,269,270],{"class":226},"script",[175,272,273],{"class":195}," setup",[175,275,276],{"class":203},">\n",[175,278,279,282,285,288,291,294,297,300,302,305],{"class":177,"line":217},[175,280,281],{"class":195},"const",[175,283,284],{"class":232}," props ",[175,286,287],{"class":203},"=",[175,289,290],{"class":199}," defineProps",[175,292,293],{"class":232},"([",[175,295,296],{"class":203},"'",[175,298,233],{"class":299},"sfazB",[175,301,296],{"class":203},[175,303,304],{"class":232},"])",[175,306,307],{"class":203},";\n",[175,309,310,313,315],{"class":177,"line":244},[175,311,312],{"class":203},"\u003C\u002F",[175,314,270],{"class":226},[175,316,276],{"class":203},[175,318,320,322,325],{"class":177,"line":319},5,[175,321,267],{"class":203},[175,323,324],{"class":226},"template",[175,326,276],{"class":203},[175,328,330,333,335,338,341,343,345],{"class":177,"line":329},6,[175,331,332],{"class":203},"  \u003C",[175,334,12],{"class":226},[175,336,337],{"class":203},">",[175,339,340],{"class":232},"{{ greeting }}",[175,342,312],{"class":203},[175,344,12],{"class":226},[175,346,276],{"class":203},[175,348,350,352,354],{"class":177,"line":349},7,[175,351,312],{"class":203},[175,353,324],{"class":226},[175,355,276],{"class":203},[12,357,358],{},"Although Vue supports JSX, templates are preferred in the Vue ecosystem.",[39,360,362],{"id":361},"react-hooks-vs-vue-composables","React hooks vs Vue composables",[12,364,365],{},"Hooks and composables are both ways to reuse logic. React example:",[166,367,371],{"className":368,"code":369,"language":370,"meta":171,"style":171},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","function useFetch(url) {\n  const [data, setData] = useState(null);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    fetch(url)\n      .then(res => res.json())\n      .then(json => {\n        setData(json);\n        setLoading(false);\n      });\n  }, [url]);\n\n  return { data, loading };\n}\n","javascript",[149,372,373,392,427,457,463,478,490,517,532,546,561,571,585,590,609],{"__ignoreMap":171},[175,374,375,378,381,384,387,390],{"class":177,"line":178},[175,376,377],{"class":195},"function",[175,379,380],{"class":199}," useFetch",[175,382,383],{"class":203},"(",[175,385,386],{"class":207},"url",[175,388,389],{"class":203},")",[175,391,214],{"class":203},[175,393,394,397,400,403,406,409,412,415,418,420,423,425],{"class":177,"line":185},[175,395,396],{"class":195},"  const",[175,398,399],{"class":203}," [",[175,401,402],{"class":232},"data",[175,404,405],{"class":203},",",[175,407,408],{"class":232}," setData",[175,410,411],{"class":203},"]",[175,413,414],{"class":203}," =",[175,416,417],{"class":199}," useState",[175,419,383],{"class":226},[175,421,422],{"class":203},"null",[175,424,389],{"class":226},[175,426,307],{"class":203},[175,428,429,431,433,436,438,441,443,445,447,449,453,455],{"class":177,"line":217},[175,430,396],{"class":195},[175,432,399],{"class":203},[175,434,435],{"class":232},"loading",[175,437,405],{"class":203},[175,439,440],{"class":232}," setLoading",[175,442,411],{"class":203},[175,444,414],{"class":203},[175,446,417],{"class":199},[175,448,383],{"class":226},[175,450,452],{"class":451},"sfNiH","true",[175,454,389],{"class":226},[175,456,307],{"class":203},[175,458,459],{"class":177,"line":244},[175,460,462],{"emptyLinePlaceholder":461},true,"\n",[175,464,465,468,470,473,476],{"class":177,"line":319},[175,466,467],{"class":199},"  useEffect",[175,469,383],{"class":226},[175,471,472],{"class":203},"()",[175,474,475],{"class":195}," =>",[175,477,214],{"class":203},[175,479,480,483,485,487],{"class":177,"line":329},[175,481,482],{"class":199},"    fetch",[175,484,383],{"class":226},[175,486,386],{"class":232},[175,488,489],{"class":226},")\n",[175,491,492,495,498,500,503,505,508,511,514],{"class":177,"line":349},[175,493,494],{"class":203},"      .",[175,496,497],{"class":199},"then",[175,499,383],{"class":226},[175,501,502],{"class":207},"res",[175,504,475],{"class":195},[175,506,507],{"class":232}," res",[175,509,510],{"class":203},".",[175,512,513],{"class":199},"json",[175,515,516],{"class":226},"())\n",[175,518,520,522,524,526,528,530],{"class":177,"line":519},8,[175,521,494],{"class":203},[175,523,497],{"class":199},[175,525,383],{"class":226},[175,527,513],{"class":207},[175,529,475],{"class":195},[175,531,214],{"class":203},[175,533,535,538,540,542,544],{"class":177,"line":534},9,[175,536,537],{"class":199},"        setData",[175,539,383],{"class":226},[175,541,513],{"class":232},[175,543,389],{"class":226},[175,545,307],{"class":203},[175,547,549,552,554,557,559],{"class":177,"line":548},10,[175,550,551],{"class":199},"        setLoading",[175,553,383],{"class":226},[175,555,556],{"class":451},"false",[175,558,389],{"class":226},[175,560,307],{"class":203},[175,562,564,567,569],{"class":177,"line":563},11,[175,565,566],{"class":203},"      }",[175,568,389],{"class":226},[175,570,307],{"class":203},[175,572,574,577,579,581,583],{"class":177,"line":573},12,[175,575,576],{"class":203},"  },",[175,578,399],{"class":226},[175,580,386],{"class":232},[175,582,304],{"class":226},[175,584,307],{"class":203},[175,586,588],{"class":177,"line":587},13,[175,589,462],{"emptyLinePlaceholder":461},[175,591,593,595,598,601,603,606],{"class":177,"line":592},14,[175,594,220],{"class":188},[175,596,597],{"class":203}," {",[175,599,600],{"class":232}," data",[175,602,405],{"class":203},[175,604,605],{"class":232}," loading",[175,607,608],{"class":203}," };\n",[175,610,612],{"class":177,"line":611},15,[175,613,247],{"class":203},[12,615,616],{},"Vue composable:",[166,618,620],{"className":368,"code":619,"language":370,"meta":171,"style":171},"import { ref, onMounted } from 'vue';\n\nfunction useFetch(url) {\n  const data = ref(null);\n  const loading = ref(true);\n\n  onMounted(async () => {\n    const response = await fetch(url);\n    data.value = await response.json();\n    loading.value = false;\n  });\n\n  return { data, loading };\n}\n",[149,621,622,652,656,670,688,706,710,727,751,775,791,800,804,818],{"__ignoreMap":171},[175,623,624,627,629,632,634,637,640,643,646,648,650],{"class":177,"line":178},[175,625,626],{"class":188},"import",[175,628,597],{"class":203},[175,630,631],{"class":232}," ref",[175,633,405],{"class":203},[175,635,636],{"class":232}," onMounted",[175,638,639],{"class":203}," }",[175,641,642],{"class":188}," from",[175,644,645],{"class":203}," '",[175,647,255],{"class":299},[175,649,296],{"class":203},[175,651,307],{"class":203},[175,653,654],{"class":177,"line":185},[175,655,462],{"emptyLinePlaceholder":461},[175,657,658,660,662,664,666,668],{"class":177,"line":217},[175,659,377],{"class":195},[175,661,380],{"class":199},[175,663,383],{"class":203},[175,665,386],{"class":207},[175,667,389],{"class":203},[175,669,214],{"class":203},[175,671,672,674,676,678,680,682,684,686],{"class":177,"line":244},[175,673,396],{"class":195},[175,675,600],{"class":232},[175,677,414],{"class":203},[175,679,631],{"class":199},[175,681,383],{"class":226},[175,683,422],{"class":203},[175,685,389],{"class":226},[175,687,307],{"class":203},[175,689,690,692,694,696,698,700,702,704],{"class":177,"line":319},[175,691,396],{"class":195},[175,693,605],{"class":232},[175,695,414],{"class":203},[175,697,631],{"class":199},[175,699,383],{"class":226},[175,701,452],{"class":451},[175,703,389],{"class":226},[175,705,307],{"class":203},[175,707,708],{"class":177,"line":329},[175,709,462],{"emptyLinePlaceholder":461},[175,711,712,715,717,720,723,725],{"class":177,"line":349},[175,713,714],{"class":199},"  onMounted",[175,716,383],{"class":226},[175,718,719],{"class":195},"async",[175,721,722],{"class":203}," ()",[175,724,475],{"class":195},[175,726,214],{"class":203},[175,728,729,732,735,737,740,743,745,747,749],{"class":177,"line":519},[175,730,731],{"class":195},"    const",[175,733,734],{"class":232}," response",[175,736,414],{"class":203},[175,738,739],{"class":188}," await",[175,741,742],{"class":199}," fetch",[175,744,383],{"class":226},[175,746,386],{"class":232},[175,748,389],{"class":226},[175,750,307],{"class":203},[175,752,753,756,758,761,763,765,767,769,771,773],{"class":177,"line":534},[175,754,755],{"class":232},"    data",[175,757,510],{"class":203},[175,759,760],{"class":232},"value",[175,762,414],{"class":203},[175,764,739],{"class":188},[175,766,734],{"class":232},[175,768,510],{"class":203},[175,770,513],{"class":199},[175,772,472],{"class":226},[175,774,307],{"class":203},[175,776,777,780,782,784,786,789],{"class":177,"line":548},[175,778,779],{"class":232},"    loading",[175,781,510],{"class":203},[175,783,760],{"class":232},[175,785,414],{"class":203},[175,787,788],{"class":451}," false",[175,790,307],{"class":203},[175,792,793,796,798],{"class":177,"line":563},[175,794,795],{"class":203},"  }",[175,797,389],{"class":226},[175,799,307],{"class":203},[175,801,802],{"class":177,"line":573},[175,803,462],{"emptyLinePlaceholder":461},[175,805,806,808,810,812,814,816],{"class":177,"line":587},[175,807,220],{"class":188},[175,809,597],{"class":203},[175,811,600],{"class":232},[175,813,405],{"class":203},[175,815,605],{"class":232},[175,817,608],{"class":203},[175,819,820],{"class":177,"line":592},[175,821,247],{"class":203},[12,823,824,825,828,829,832,833,836,837,840],{},"Unlike React, which requires explicit hooks like ",[149,826,827],{},"useState"," or ",[149,830,831],{},"useEffect",", Vue's reactivity system is built-in. You use ",[149,834,835],{},"ref"," and ",[149,838,839],{},"reactive"," to declare reactive state, and Vue automatically tracks dependencies and updates.",[39,842,844],{"id":843},"callback-props-vs-events","Callback props vs events",[12,846,847],{},"React pattern:",[166,849,851],{"className":168,"code":850,"language":170,"meta":171,"style":171},"\u003CChildComponent onDataChange={handleDataChange} \u002F>\n",[149,852,853],{"__ignoreMap":171},[175,854,855,857,861,864,867,870],{"class":177,"line":178},[175,856,267],{"class":203},[175,858,860],{"class":859},"sBMFI","ChildComponent",[175,862,863],{"class":195}," onDataChange",[175,865,866],{"class":203},"={",[175,868,869],{"class":232},"handleDataChange",[175,871,872],{"class":203},"} \u002F>\n",[12,874,875],{},"Vue pattern:",[166,877,879],{"className":253,"code":878,"language":255,"meta":171,"style":171},"\u003CChildComponent @data-change=\"handleDataChange\" \u002F>\n",[149,880,881],{"__ignoreMap":171},[175,882,883,885,887,890,893,895,898,900,902],{"class":177,"line":178},[175,884,267],{"class":203},[175,886,860],{"class":226},[175,888,889],{"class":203}," @",[175,891,892],{"class":195},"data-change",[175,894,287],{"class":203},[175,896,897],{"class":203},"\"",[175,899,869],{"class":232},[175,901,897],{"class":203},[175,903,904],{"class":203}," \u002F>\n",[12,906,907],{},"React child:",[166,909,911],{"className":368,"code":910,"language":370,"meta":171,"style":171},"function ChildComponent({ onDataChange }) {\n  return \u003Cbutton onClick={() => onDataChange('New Data')}>Click\u003C\u002Fbutton>;\n}\n",[149,912,913,928,970],{"__ignoreMap":171},[175,914,915,917,920,922,924,926],{"class":177,"line":178},[175,916,377],{"class":195},[175,918,919],{"class":199}," ChildComponent",[175,921,204],{"class":203},[175,923,863],{"class":207},[175,925,211],{"class":203},[175,927,214],{"class":203},[175,929,930,932,934,937,940,943,945,947,949,951,954,956,958,961,964,966,968],{"class":177,"line":185},[175,931,220],{"class":188},[175,933,223],{"class":203},[175,935,936],{"class":226},"button",[175,938,939],{"class":195}," onClick",[175,941,942],{"class":203},"={()",[175,944,475],{"class":195},[175,946,863],{"class":199},[175,948,383],{"class":232},[175,950,296],{"class":203},[175,952,953],{"class":299},"New Data",[175,955,296],{"class":203},[175,957,389],{"class":232},[175,959,960],{"class":203},"}>",[175,962,963],{"class":232},"Click",[175,965,312],{"class":203},[175,967,936],{"class":226},[175,969,241],{"class":203},[175,971,972],{"class":177,"line":217},[175,973,247],{"class":203},[12,975,976],{},"Vue child:",[166,978,980],{"className":253,"code":979,"language":255,"meta":171,"style":171},"\u003Cscript setup>\nconst emit = defineEmits(['data-change']);\n\nfunction changeData() {\n  emit('data-change', 'New Data');\n}\n\u003C\u002Fscript>\n\u003Ctemplate>\n  \u003Cbutton @click=\"changeData\">Click\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n",[149,981,982,992,1016,1020,1031,1056,1060,1068,1076,1104],{"__ignoreMap":171},[175,983,984,986,988,990],{"class":177,"line":178},[175,985,267],{"class":203},[175,987,270],{"class":226},[175,989,273],{"class":195},[175,991,276],{"class":203},[175,993,994,996,999,1001,1004,1006,1008,1010,1012,1014],{"class":177,"line":185},[175,995,281],{"class":195},[175,997,998],{"class":232}," emit ",[175,1000,287],{"class":203},[175,1002,1003],{"class":199}," defineEmits",[175,1005,293],{"class":232},[175,1007,296],{"class":203},[175,1009,892],{"class":299},[175,1011,296],{"class":203},[175,1013,304],{"class":232},[175,1015,307],{"class":203},[175,1017,1018],{"class":177,"line":217},[175,1019,462],{"emptyLinePlaceholder":461},[175,1021,1022,1024,1027,1029],{"class":177,"line":244},[175,1023,377],{"class":195},[175,1025,1026],{"class":199}," changeData",[175,1028,472],{"class":203},[175,1030,214],{"class":203},[175,1032,1033,1036,1038,1040,1042,1044,1046,1048,1050,1052,1054],{"class":177,"line":319},[175,1034,1035],{"class":199},"  emit",[175,1037,383],{"class":226},[175,1039,296],{"class":203},[175,1041,892],{"class":299},[175,1043,296],{"class":203},[175,1045,405],{"class":203},[175,1047,645],{"class":203},[175,1049,953],{"class":299},[175,1051,296],{"class":203},[175,1053,389],{"class":226},[175,1055,307],{"class":203},[175,1057,1058],{"class":177,"line":329},[175,1059,247],{"class":203},[175,1061,1062,1064,1066],{"class":177,"line":349},[175,1063,312],{"class":203},[175,1065,270],{"class":226},[175,1067,276],{"class":203},[175,1069,1070,1072,1074],{"class":177,"line":519},[175,1071,267],{"class":203},[175,1073,324],{"class":226},[175,1075,276],{"class":203},[175,1077,1078,1080,1082,1085,1087,1089,1092,1094,1096,1098,1100,1102],{"class":177,"line":534},[175,1079,332],{"class":203},[175,1081,936],{"class":226},[175,1083,1084],{"class":195}," @click",[175,1086,287],{"class":203},[175,1088,897],{"class":203},[175,1090,1091],{"class":299},"changeData",[175,1093,897],{"class":203},[175,1095,337],{"class":203},[175,1097,963],{"class":232},[175,1099,312],{"class":203},[175,1101,936],{"class":226},[175,1103,276],{"class":203},[175,1105,1106,1108,1110],{"class":177,"line":548},[175,1107,312],{"class":203},[175,1109,324],{"class":226},[175,1111,276],{"class":203},[39,1113,1115],{"id":1114},"jsx-as-prop-vs-vue-slots","JSX as prop vs Vue slots",[12,1117,1118],{},"React:",[166,1120,1122],{"className":168,"code":1121,"language":170,"meta":171,"style":171},"\u003CChildComponent>\n  \u003Ch1>Hello\u003C\u002Fh1>\n\u003C\u002FChildComponent>\n",[149,1123,1124,1132,1150],{"__ignoreMap":171},[175,1125,1126,1128,1130],{"class":177,"line":178},[175,1127,267],{"class":203},[175,1129,860],{"class":859},[175,1131,276],{"class":203},[175,1133,1134,1136,1139,1141,1144,1146,1148],{"class":177,"line":185},[175,1135,332],{"class":203},[175,1137,1138],{"class":226},"h1",[175,1140,337],{"class":203},[175,1142,1143],{"class":232},"Hello",[175,1145,312],{"class":203},[175,1147,1138],{"class":226},[175,1149,276],{"class":203},[175,1151,1152,1154,1156],{"class":177,"line":217},[175,1153,312],{"class":203},[175,1155,860],{"class":859},[175,1157,276],{"class":203},[12,1159,1160],{},"Vue:",[166,1162,1164],{"className":253,"code":1163,"language":255,"meta":171,"style":171},"\u003CChildComponent>\n  \u003Ctemplate #default>\n    \u003Ch1>Hello\u003C\u002Fh1>\n  \u003C\u002Ftemplate>\n\u003C\u002FChildComponent>\n",[149,1165,1166,1174,1179,1184,1189],{"__ignoreMap":171},[175,1167,1168,1170,1172],{"class":177,"line":178},[175,1169,267],{"class":203},[175,1171,860],{"class":226},[175,1173,276],{"class":203},[175,1175,1176],{"class":177,"line":185},[175,1177,1178],{"class":232},"  \u003Ctemplate #default>\n",[175,1180,1181],{"class":177,"line":217},[175,1182,1183],{"class":232},"    \u003Ch1>Hello\u003C\u002Fh1>\n",[175,1185,1186],{"class":177,"line":244},[175,1187,1188],{"class":232},"  \u003C\u002Ftemplate>\n",[175,1190,1191,1193,1195],{"class":177,"line":319},[175,1192,312],{"class":203},[175,1194,860],{"class":226},[175,1196,276],{"class":203},[12,1198,1199,1200,1203],{},"Vue slots are used in templates with ",[149,1201,1202],{},"\u003Cslot>\u003C\u002Fslot>",". Named slots allow multiple insertion points:",[166,1205,1207],{"className":253,"code":1206,"language":255,"meta":171,"style":171},"\u003Ctemplate>\n  \u003Cslot name=\"header\">\u003C\u002Fslot>\n  \u003Cslot>\u003C\u002Fslot> \u003C!-- default -->\n  \u003Cslot name=\"footer\">\u003C\u002Fslot>\n\u003C\u002Ftemplate>\n",[149,1208,1209,1217,1243,1258,1281],{"__ignoreMap":171},[175,1210,1211,1213,1215],{"class":177,"line":178},[175,1212,267],{"class":203},[175,1214,324],{"class":226},[175,1216,276],{"class":203},[175,1218,1219,1221,1224,1227,1229,1231,1234,1236,1239,1241],{"class":177,"line":185},[175,1220,332],{"class":203},[175,1222,1223],{"class":226},"slot",[175,1225,1226],{"class":195}," name",[175,1228,287],{"class":203},[175,1230,897],{"class":203},[175,1232,1233],{"class":299},"header",[175,1235,897],{"class":203},[175,1237,1238],{"class":203},">\u003C\u002F",[175,1240,1223],{"class":226},[175,1242,276],{"class":203},[175,1244,1245,1247,1249,1251,1253,1255],{"class":177,"line":217},[175,1246,332],{"class":203},[175,1248,1223],{"class":226},[175,1250,1238],{"class":203},[175,1252,1223],{"class":226},[175,1254,337],{"class":203},[175,1256,1257],{"class":181}," \u003C!-- default -->\n",[175,1259,1260,1262,1264,1266,1268,1270,1273,1275,1277,1279],{"class":177,"line":244},[175,1261,332],{"class":203},[175,1263,1223],{"class":226},[175,1265,1226],{"class":195},[175,1267,287],{"class":203},[175,1269,897],{"class":203},[175,1271,1272],{"class":299},"footer",[175,1274,897],{"class":203},[175,1276,1238],{"class":203},[175,1278,1223],{"class":226},[175,1280,276],{"class":203},[175,1282,1283,1285,1287],{"class":177,"line":319},[175,1284,312],{"class":203},[175,1286,324],{"class":226},[175,1288,276],{"class":203},[39,1290,1292],{"id":1291},"render-props-vs-scoped-slots","Render props vs scoped slots",[12,1294,1118],{},[166,1296,1298],{"className":168,"code":1297,"language":170,"meta":171,"style":171},"\u003CMouseTracker render={({ x, y }) => \u003Cp>{x}, {y}\u003C\u002Fp>} \u002F>\n",[149,1299,1300],{"__ignoreMap":171},[175,1301,1302,1304,1307,1310,1313,1316,1318,1321,1323,1325,1327,1329,1331,1334,1337,1340,1343,1346,1348,1350],{"class":177,"line":178},[175,1303,267],{"class":203},[175,1305,1306],{"class":859},"MouseTracker",[175,1308,1309],{"class":195}," render",[175,1311,1312],{"class":203},"={({",[175,1314,1315],{"class":207}," x",[175,1317,405],{"class":203},[175,1319,1320],{"class":207}," y",[175,1322,211],{"class":203},[175,1324,475],{"class":195},[175,1326,223],{"class":203},[175,1328,12],{"class":226},[175,1330,229],{"class":203},[175,1332,1333],{"class":232},"x",[175,1335,1336],{"class":203},"}",[175,1338,1339],{"class":232},", ",[175,1341,1342],{"class":203},"{",[175,1344,1345],{"class":232},"y",[175,1347,236],{"class":203},[175,1349,12],{"class":226},[175,1351,1352],{"class":203},">} \u002F>\n",[12,1354,1160],{},[166,1356,1358],{"className":253,"code":1357,"language":255,"meta":171,"style":171},"\u003CMouseTracker v-slot=\"{ position }\">\n  \u003Cp>{{ position.x }}, {{ position.y }}\u003C\u002Fp>\n\u003C\u002FMouseTracker>\n",[149,1359,1360,1384,1389],{"__ignoreMap":171},[175,1361,1362,1364,1366,1369,1371,1373,1375,1378,1380,1382],{"class":177,"line":178},[175,1363,267],{"class":203},[175,1365,1306],{"class":226},[175,1367,1368],{"class":195}," v-slot",[175,1370,287],{"class":203},[175,1372,897],{"class":203},[175,1374,1342],{"class":203},[175,1376,1377],{"class":232}," position ",[175,1379,1336],{"class":203},[175,1381,897],{"class":203},[175,1383,276],{"class":203},[175,1385,1386],{"class":177,"line":185},[175,1387,1388],{"class":232},"  \u003Cp>{{ position.x }}, {{ position.y }}\u003C\u002Fp>\n",[175,1390,1391,1393,1395],{"class":177,"line":217},[175,1392,312],{"class":203},[175,1394,1306],{"class":226},[175,1396,276],{"class":203},[12,1398,1399],{},"Scoped slots let you expose internal data to the parent for full control over rendering.",[39,1401,1403],{"id":1402},"context-api-vs-provideinject","Context API vs provide\u002Finject",[12,1405,1118],{},[166,1407,1409],{"className":168,"code":1408,"language":170,"meta":171,"style":171},"\u003CThemeContext.Provider value={{ theme, setTheme }}>\n  \u003CApp \u002F>\n\u003C\u002FThemeContext.Provider>\n",[149,1410,1411,1435,1444],{"__ignoreMap":171},[175,1412,1413,1415,1418,1421,1424,1427,1429,1432],{"class":177,"line":178},[175,1414,267],{"class":203},[175,1416,1417],{"class":859},"ThemeContext.Provider",[175,1419,1420],{"class":195}," value",[175,1422,1423],{"class":203},"={{",[175,1425,1426],{"class":232}," theme",[175,1428,405],{"class":203},[175,1430,1431],{"class":232}," setTheme ",[175,1433,1434],{"class":203},"}}>\n",[175,1436,1437,1439,1442],{"class":177,"line":185},[175,1438,332],{"class":203},[175,1440,1441],{"class":859},"App",[175,1443,904],{"class":203},[175,1445,1446,1448,1450],{"class":177,"line":217},[175,1447,312],{"class":203},[175,1449,1417],{"class":859},[175,1451,276],{"class":203},[12,1453,1160],{},[166,1455,1457],{"className":253,"code":1456,"language":255,"meta":171,"style":171},"\u003Cscript setup>\nconst theme = ref('light');\nprovide('theme', theme);\n\u003C\u002Fscript>\n",[149,1458,1459,1469,1493,1514],{"__ignoreMap":171},[175,1460,1461,1463,1465,1467],{"class":177,"line":178},[175,1462,267],{"class":203},[175,1464,270],{"class":226},[175,1466,273],{"class":195},[175,1468,276],{"class":203},[175,1470,1471,1473,1476,1478,1480,1482,1484,1487,1489,1491],{"class":177,"line":185},[175,1472,281],{"class":195},[175,1474,1475],{"class":232}," theme ",[175,1477,287],{"class":203},[175,1479,631],{"class":199},[175,1481,383],{"class":232},[175,1483,296],{"class":203},[175,1485,1486],{"class":299},"light",[175,1488,296],{"class":203},[175,1490,389],{"class":232},[175,1492,307],{"class":203},[175,1494,1495,1498,1500,1502,1505,1507,1509,1512],{"class":177,"line":217},[175,1496,1497],{"class":199},"provide",[175,1499,383],{"class":232},[175,1501,296],{"class":203},[175,1503,1504],{"class":299},"theme",[175,1506,296],{"class":203},[175,1508,405],{"class":203},[175,1510,1511],{"class":232}," theme)",[175,1513,307],{"class":203},[175,1515,1516,1518,1520],{"class":177,"line":244},[175,1517,312],{"class":203},[175,1519,270],{"class":226},[175,1521,276],{"class":203},[12,1523,1524],{},"To consume:",[166,1526,1528],{"className":253,"code":1527,"language":255,"meta":171,"style":171},"\u003Cscript setup>\nconst theme = inject('theme');\n\u003C\u002Fscript>\n",[149,1529,1530,1540,1563],{"__ignoreMap":171},[175,1531,1532,1534,1536,1538],{"class":177,"line":178},[175,1533,267],{"class":203},[175,1535,270],{"class":226},[175,1537,273],{"class":195},[175,1539,276],{"class":203},[175,1541,1542,1544,1546,1548,1551,1553,1555,1557,1559,1561],{"class":177,"line":185},[175,1543,281],{"class":195},[175,1545,1475],{"class":232},[175,1547,287],{"class":203},[175,1549,1550],{"class":199}," inject",[175,1552,383],{"class":232},[175,1554,296],{"class":203},[175,1556,1504],{"class":299},[175,1558,296],{"class":203},[175,1560,389],{"class":232},[175,1562,307],{"class":203},[175,1564,1565,1567,1569],{"class":177,"line":217},[175,1566,312],{"class":203},[175,1568,270],{"class":226},[175,1570,276],{"class":203},[39,1572,145],{"id":1573},"polymorphic-components",[12,1575,1576,1577,1579],{},"React pattern using the ",[149,1578,151],{}," prop:",[166,1581,1583],{"className":368,"code":1582,"language":370,"meta":171,"style":171},"function Box({ as: Component = 'div', ...props }) {\n  return \u003CComponent {...props} \u002F>;\n}\n",[149,1584,1585,1623,1640],{"__ignoreMap":171},[175,1586,1587,1589,1592,1594,1597,1600,1602,1604,1606,1609,1611,1613,1616,1619,1621],{"class":177,"line":178},[175,1588,377],{"class":195},[175,1590,1591],{"class":199}," Box",[175,1593,204],{"class":203},[175,1595,1596],{"class":226}," as",[175,1598,1599],{"class":203},":",[175,1601,200],{"class":207},[175,1603,414],{"class":203},[175,1605,645],{"class":203},[175,1607,1608],{"class":299},"div",[175,1610,296],{"class":203},[175,1612,405],{"class":203},[175,1614,1615],{"class":203}," ...",[175,1617,1618],{"class":207},"props",[175,1620,211],{"class":203},[175,1622,214],{"class":203},[175,1624,1625,1627,1629,1632,1635,1637],{"class":177,"line":185},[175,1626,220],{"class":188},[175,1628,223],{"class":203},[175,1630,1631],{"class":859},"Component",[175,1633,1634],{"class":203}," {...",[175,1636,1618],{"class":232},[175,1638,1639],{"class":203},"} \u002F>;\n",[175,1641,1642],{"class":177,"line":217},[175,1643,247],{"class":203},[12,1645,1646],{},"Vue dynamic components:",[166,1648,1650],{"className":253,"code":1649,"language":255,"meta":171,"style":171},"\u003Ccomponent :is=\"as\">\u003C\u002Fcomponent>\n",[149,1651,1652],{"__ignoreMap":171},[175,1653,1654,1656,1659,1662,1665,1667,1669,1671,1673,1675,1677],{"class":177,"line":178},[175,1655,267],{"class":203},[175,1657,1658],{"class":226},"component",[175,1660,1661],{"class":203}," :",[175,1663,1664],{"class":195},"is",[175,1666,287],{"class":203},[175,1668,897],{"class":203},[175,1670,151],{"class":232},[175,1672,897],{"class":203},[175,1674,1238],{"class":203},[175,1676,1658],{"class":226},[175,1678,276],{"class":203},[12,1680,1681,1682,1684],{},"You can pass either an HTML tag name or a component to the ",[149,1683,1664],{}," attribute.",[39,1686,1688],{"id":1687},"conclusion","Conclusion",[12,1690,1691],{},"Migrating from React to Vue is easier when you map familiar patterns. Vue's Composition API and template syntax offer similar flexibility with a different philosophy. This comparison shows that while the syntax differs, most React patterns have Vue equivalents.",[12,1693,1694],{},"Whether you're building your next frontend app or just exploring another JavaScript framework, Vue is a powerful alternative for modern UI development.",[1696,1697],"blog-button",{"label":1698,"to":1699},"Talk to a Vue expert","https:\u002F\u002Fcalendar.app.google\u002FXwRzASZitZRSVLxq6",[1701,1702,1703],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":171,"searchDepth":217,"depth":217,"links":1705},[1706,1707,1708,1709,1710,1711,1712,1713,1714],{"id":41,"depth":185,"text":42},{"id":160,"depth":185,"text":161},{"id":361,"depth":185,"text":362},{"id":843,"depth":185,"text":844},{"id":1114,"depth":185,"text":1115},{"id":1291,"depth":185,"text":1292},{"id":1402,"depth":185,"text":1403},{"id":1573,"depth":185,"text":145},{"id":1687,"depth":185,"text":1688},"2025-06-05","A React-to-Vue comparison for developers switching frameworks: JSX vs templates, hooks vs composables, callback props vs events, context vs provide\u002Finject.","md",false,"\u002Fimages\u002Fblog\u002Freact-vue\u002Fcard.png",{},"\u002Fblog\u002Freact-vue",{"title":5,"description":1716},"blog\u002Freact-vue",[1725,67],"Vue.js","QlQI2tMPjhg1DO0hh4W2BcX5lAOLhBOhnv7KSpKC18c",1784559991785]