{"id":4469,"date":"2025-08-09T16:07:03","date_gmt":"2025-08-09T16:07:03","guid":{"rendered":"https:\/\/uplatz.com\/blog\/?p=4469"},"modified":"2025-08-09T16:07:03","modified_gmt":"2025-08-09T16:07:03","slug":"vue-js-pocket-book","status":"publish","type":"post","link":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/","title":{"rendered":"Vue.js Pocket Book"},"content":{"rendered":"<p><!-- Vue.js Pocket Book \u2014 Uplatz (50 Cards, Wide Layout, Readable Code, Scoped Styles) --><\/p>\n<div style=\"margin:16px 0;\">\n<style>\n    .wp-vue-pb { font-family: Arial, sans-serif; max-width: 1320px; margin:0 auto; }\n    .wp-vue-pb .heading{\n      background: linear-gradient(135deg, #e0f2fe, #f0fdf4); \/* light blue -> light green *\/\n      color:#0f172a; padding:22px 24px; border-radius:14px;\n      text-align:center; margin-bottom:18px; box-shadow:0 8px 20px rgba(0,0,0,.08);\n      border:1px solid #cbd5e1;\n    }\n    .wp-vue-pb .heading h2{ margin:0; font-size:2.1rem; letter-spacing:.2px; }\n    .wp-vue-pb .heading p{ margin:6px 0 0; font-size:1.02rem; opacity:.9; }<\/p>\n<p>    \/* Wide, dense grid *\/\n    .wp-vue-pb .grid{\n      display:grid; gap:14px;\n      grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));\n    }\n    @media (min-width:1200px){\n      .wp-vue-pb .grid{ grid-template-columns: repeat(3, 1fr); }\n    }<\/p>\n<p>    .wp-vue-pb .section-title{\n      grid-column:1\/-1; background:#f8fafc; border-left:8px solid #10b981; \/* green *\/\n      padding:12px 16px; border-radius:10px; font-weight:700; color:#0f172a; font-size:1.08rem;\n      box-shadow:0 2px 8px rgba(0,0,0,.05); border:1px solid #e2e8f0;\n    }\n    .wp-vue-pb .card{\n      background:#ffffff; border-left:6px solid #10b981;\n      padding:18px; border-radius:12px;\n      box-shadow:0 6px 14px rgba(0,0,0,.06);\n      transition:transform .12s ease, box-shadow .12s ease;\n      border:1px solid #e5e7eb;\n    }\n    .wp-vue-pb .card:hover{ transform: translateY(-3px); box-shadow:0 10px 22px rgba(0,0,0,.08); }\n    .wp-vue-pb .card h3{ margin:0 0 10px; font-size:1.12rem; color:#0f172a; }\n    .wp-vue-pb .card p{ margin:0; font-size:.96rem; color:#334155; line-height:1.62; }<\/p>\n<p>    \/* Color helpers *\/\n    .bg-blue { border-left-color:#0ea5e9 !important; background:#eef6ff !important; }\n    .bg-green{ border-left-color:#10b981 !important; background:#f0fdf4 !important; }\n    .bg-amber{ border-left-color:#f59e0b !important; background:#fffbeb !important; }\n    .bg-violet{ border-left-color:#8b5cf6 !important; background:#f5f3ff !important; }\n    .bg-rose{ border-left-color:#ef4444 !important; background:#fff1f2 !important; }\n    .bg-cyan{ border-left-color:#06b6d4 !important; background:#ecfeff !important; }\n    .bg-lime{ border-left-color:#22c55e !important; background:#ecfdf5 !important; }\n    .bg-orange{ border-left-color:#f97316 !important; background:#fff7ed !important; }\n    .bg-indigo{ border-left-color:#6366f1 !important; background:#eef2ff !important; }\n    .bg-emerald{ border-left-color:#059669 !important; background:#ecfdf5 !important; }\n    .bg-slate{ border-left-color:#334155 !important; background:#f8fafc !important; }<\/p>\n<p>    \/* Utilities & code *\/\n    .tight ul{ margin:0; padding-left:18px; }\n    .tight li{ margin:4px 0; }\n    .mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; }\n    .wp-vue-pb code{ background:#f1f5f9; padding:0 4px; border-radius:4px; border:1px solid #e2e8f0; }\n    .wp-vue-pb pre{\n      background:#f5f5f5; color:#111827; border:1px solid #e5e7eb;\n      padding:12px; border-radius:8px; overflow:auto; font-size:.92rem; line-height:1.55;\n    }\n    .q{font-weight:700;}\n    .qa p{ margin:8px 0; }\n  <\/style>\n<div class=\"wp-vue-pb\">\n<div class=\"heading\">\n<h2>Vue.js Pocket Book \u2014 Uplatz<\/h2>\n<p>50 in-depth cards \u2022 Wide layout \u2022 Readable examples \u2022 20-question interview Q&amp;A included<\/p>\n<\/p><\/div>\n<div class=\"grid\">\n      <!-- ===================== SECTION 1: CORE FOUNDATIONS (1\u201310) ===================== --><\/p>\n<div class=\"section-title\">Section 1 \u2014 Core Foundations<\/div>\n<div class=\"card bg-green\">\n<h3>1) What is Vue.js?<\/h3>\n<p>Vue is a progressive framework for building UIs. It combines a reactive data system, declarative templates, and component composition. Vue 3 introduced the Composition API, the new reactivity system (Proxies), and better TypeScript support.<\/p>\n<pre><code class=\"mono\">&lt;!-- CDN quick start --&gt;\r\n&lt;script src=\"https:\/\/unpkg.com\/vue@3\"&gt;&lt;\/script&gt;\r\n&lt;div id=\"app\"&gt;Hello {{ msg }}&lt;\/div&gt;\r\n&lt;script&gt;\r\nconst { createApp, ref } = Vue;\r\ncreateApp({ setup(){ const msg=ref('Vue'); return { msg } } }).mount('#app');\r\n&lt;\/script&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>2) Declarative Templates<\/h3>\n<p>Vue templates compile to efficient render functions. Use directives like <code>v-bind<\/code>, <code>v-on<\/code>, <code>v-if<\/code>, <code>v-for<\/code>, and modifiers (<code>.prevent<\/code>, <code>.stop<\/code>) for expressive UIs.<\/p>\n<pre><code class=\"mono\">&lt;button :title=\"hint\" @click.prevent=\"save\"&gt;Save&lt;\/button&gt;\r\n&lt;li v-for=\"(u,i) in users\" :key=\"u.id\"&gt;{{ i+1 }}. {{ u.name }}&lt;\/li&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>3) Reactivity Basics<\/h3>\n<p><code>ref()<\/code> wraps a reactive primitive; <code>reactive()<\/code> turns objects reactive. Access\/assign via <code>.value<\/code> for refs; objects unwrap in templates.<\/p>\n<pre><code class=\"mono\">const n = ref(0); const state = reactive({ open:false });\r\nwatch(n, (nv, ov) =&gt; console.log('changed', ov, '\u2192', nv));<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-violet\">\n<h3>4) Single File Components (SFC)<\/h3>\n<p><code>.vue<\/code> SFCs bundle template, script, and style. Use <code>&lt;script setup&gt;<\/code> to get concise Composition API syntax and better treeshaking.<\/p>\n<pre><code class=\"mono\">&lt;template&gt;&lt;button @click=\"count++\"&gt;{{ count }}&lt;\/button&gt;&lt;\/template&gt;\r\n&lt;script setup&gt;import { ref } from 'vue'; const count = ref(0);&lt;\/script&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>5) Props &#038; Emits<\/h3>\n<p>Define props and emitted events for parent-child communication. Validate props with types; declare emits for better DX.<\/p>\n<pre><code class=\"mono\">&lt;script setup&gt;\r\ndefineProps({ label:String, modelValue:Boolean });\r\nconst emit = defineEmits(['update:modelValue']);\r\nconst toggle = () =&gt; emit('update:modelValue', !modelValue);\r\n&lt;\/script&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan\">\n<h3>6) Computed &#038; Watch<\/h3>\n<p><code>computed()<\/code> caches derived values until dependencies change. <code>watch()<\/code> reacts to changes with side-effects. Use <code>watchEffect()<\/code> for autoruns.<\/p>\n<pre><code class=\"mono\">const full = computed(() =&gt; `${first.value} ${last.value}`);\r\nwatch(search, debounce(fetchList, 300));<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-lime\">\n<h3>7) Directives Deep Dive<\/h3>\n<p>Built-ins: <code>v-if<\/code>, <code>v-show<\/code>, <code>v-for<\/code>, <code>v-model<\/code>. Custom directives encapsulate low-level DOM effects (e.g., autofocus, lazy-load). Prefer components for complex logic.<\/p>\n<pre><code class=\"mono\">app.directive('focus', { mounted(el){ el.focus(); } })<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>8) Lifecycle Hooks<\/h3>\n<p>Key Composition hooks: <code>onMounted<\/code>, <code>onUpdated<\/code>, <code>onUnmounted<\/code>, <code>onBeforeRouteLeave<\/code> (router). Avoid async race conditions by canceling work on unmount.<\/p>\n<pre><code class=\"mono\">onMounted(() =&gt; fetchData()); onUnmounted(() =&gt; abortCtl.abort());<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>9) Slots &#038; Provide\/Inject<\/h3>\n<p>Slots compose content; scoped slots pass data down. Use provide\/inject for deep dependency passing (theme, i18n), but keep it limited for clarity.<\/p>\n<pre><code class=\"mono\">&lt;slot name=\"footer\" :count=\"items.length\"&gt;&lt;\/slot&gt;\r\nprovide('theme', ref('light'))<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald\">\n<h3>10) Q&amp;A \u2014 \u201cWhen to use watch vs computed?\u201d<\/h3>\n<p><span class=\"q\">Answer:<\/span> Use <b>computed<\/b> for pure derivations used in templates or other code; use <b>watch<\/b> for side effects (fetching, logging, imperative DOM). If you\u2019re assigning to state based on other state, try computed first.<\/p>\n<\/p><\/div>\n<p>      <!-- ===================== SECTION 2: COMPOSITION API & PATTERNS (11\u201320) ===================== --><\/p>\n<div class=\"section-title\">Section 2 \u2014 Composition API, Patterns &#038; Reuse<\/div>\n<div class=\"card bg-green\">\n<h3>11) Composables (useX)<\/h3>\n<p>Extract reusable logic into composable functions that return reactive state, methods, and computed values. Share across components without inheritance.<\/p>\n<pre><code class=\"mono\">\/\/ useFetch.ts\r\nexport function useFetch(url){\r\n  const data = ref(null), error = ref(null), loading = ref(false);\r\n  const run = async() =&gt; { loading.value=true; try{ data.value=await (await fetch(url)).json() } catch(e){ error.value=e } finally{ loading.value=false } };\r\n  onMounted(run); return { data, error, loading, run };\r\n}<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>12) Script Setup Essentials<\/h3>\n<p><code>&lt;script setup&gt;<\/code> runs once per SFC and auto-exposes top-level bindings to the template. Use <code>defineProps\/defineEmits<\/code>, <code>defineExpose<\/code>, and <code>withDefaults<\/code> for ergonomics.<\/p>\n<pre><code class=\"mono\">&lt;script setup lang=\"ts\"&gt;\r\ninterface P{ size?:'sm'|'md'|'lg' }\r\nconst props = withDefaults(defineProps&lt;P&gt;(), { size:'md' })\r\ndefineExpose({ focus: () =&gt; input.value?.focus() })\r\n&lt;\/script&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>13) Refs vs Reactive<\/h3>\n<p>Prefer <code>ref<\/code> for primitives and <code>reactive<\/code> for objects. When destructuring reactive, use <code>toRefs()<\/code> to keep reactivity.<\/p>\n<pre><code class=\"mono\">const state = reactive({ a:1, b:2 }); const { a, b } = toRefs(state);<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-violet\">\n<h3>14) v-model on Components<\/h3>\n<p>Support two-way binding by accepting <code>modelValue<\/code> and emitting <code>update:modelValue<\/code>. You can have multiple models with arguments.<\/p>\n<pre><code class=\"mono\">&lt;Child v-model=\"open\" \/&gt; &lt;!-- maps to modelValue --&gt;\r\n&lt;Child v-model:title=\"title\" v-model:count=\"n\" \/&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>15) Teleport &#038; Suspense<\/h3>\n<p><b>Teleport<\/b> renders children elsewhere in the DOM (modals\/portals). <b>Suspense<\/b> coordinates async components and fallbacks.<\/p>\n<pre><code class=\"mono\">&lt;teleport to=\"body\"&gt;&lt;Modal v-if=\"open\" \/&gt;&lt;\/teleport&gt;\r\n&lt;Suspense&gt;&lt;AsyncChart \/&gt;&lt;template #fallback&gt;Loading\u2026&lt;\/template&gt;&lt;\/Suspense&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan\">\n<h3>16) Transitions<\/h3>\n<p>Animate enter\/leave with the <code>&lt;transition&gt;<\/code> component. Works with CSS classes or JS hooks; great for modal fades, list moves.<\/p>\n<pre><code class=\"mono\">&lt;transition name=\"fade\"&gt;&lt;div v-if=\"show\"&gt;Hi&lt;\/div&gt;&lt;\/transition&gt;\r\n&lt;style&gt;.fade-enter-active,.fade-leave-active{transition:opacity .2s}.fade-enter-from,.fade-leave-to{opacity:0}&lt;\/style&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-lime\">\n<h3>17) Error Handling<\/h3>\n<p>Use <code>errorCaptured<\/code> to catch child errors and provide fallbacks. For global errors, wrap app-level try\/catch and log.<\/p>\n<pre><code class=\"mono\">onErrorCaptured((err, inst, info) =&gt; { console.error(info, err); return false })<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>18) Performance Patterns<\/h3>\n<p>Prefer computed over watch, use <code>v-memo<\/code>\/<code>keep-alive<\/code> for caching, and avoid large reactive objects; split stores and lazy routes.<\/p>\n<pre><code class=\"mono\">&lt;keep-alive include=\"UserList\"&gt;&lt;router-view \/&gt;&lt;\/keep-alive&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>19) Accessibility<\/h3>\n<p>Manage focus on route changes, use semantic tags, ARIA roles for custom widgets, and keyboard shortcuts. Teleport modals should trap focus.<\/p>\n<pre><code class=\"mono\">onMounted(() =&gt; document.getElementById('main')?.focus())<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald\">\n<h3>20) Q&amp;A \u2014 \u201cWhen to create a composable vs component?\u201d<\/h3>\n<p><span class=\"q\">Answer:<\/span> If the reuse is logic-only (fetching, timers, state), use a <b>composable<\/b>. If you need UI + logic reusable together, use a <b>component<\/b>. Combine both by using composables inside components.<\/p>\n<\/p><\/div>\n<p>      <!-- ===================== SECTION 3: ROUTER, STATE & DATA (21\u201330) ===================== --><\/p>\n<div class=\"section-title\">Section 3 \u2014 Routing, State Management &#038; Data<\/div>\n<div class=\"card bg-green\">\n<h3>21) Vue Router Basics<\/h3>\n<p>Define routes, nested routes, and dynamic params. Use <code>router.push<\/code> for navigation and navigation guards for auth.<\/p>\n<pre><code class=\"mono\">const router = createRouter({\r\n  history: createWebHistory(),\r\n  routes:[ { path:'\/', component:Home }, { path:'\/user\/:id', component:User } ]\r\n});<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>22) Route Guards<\/h3>\n<p>Global (<code>beforeEach<\/code>), per-route (<code>beforeEnter<\/code>), and in-component guards (<code>onBeforeRouteLeave<\/code>). Check auth, preload data, or cancel navigation.<\/p>\n<pre><code class=\"mono\">router.beforeEach((to,from,next)=&gt; auth() ? next() : next('\/login'))<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>23) Pinia Overview<\/h3>\n<p>Pinia is the official store for Vue. It\u2019s modular (per-store), type-friendly, and works with Composition API. Use actions for async and getters for derived state.<\/p>\n<pre><code class=\"mono\">export const useCart = defineStore('cart',{\r\n  state:()=&gt;({ items:[] }),\r\n  actions:{ add(p){ this.items.push(p) } },\r\n  getters:{ total:(s)=&gt; s.items.length }\r\n})<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-violet\">\n<h3>24) Pinia + Persist<\/h3>\n<p>Persist stores with plugins (e.g., localStorage). Selectively persist keys and version data for migrations.<\/p>\n<pre><code class=\"mono\">pinia.use(({ store }) =&gt; { store.$subscribe((_m, state)=&gt; localStorage.setItem(store.$id, JSON.stringify(state))) })<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>25) Server Cache vs Client State<\/h3>\n<p>Server cache (e.g., fetching layer) stores remote data with lifetimes (stale-while-revalidate). Client state holds UI state and business rules. Don\u2019t mix them.<\/p>\n<pre><code class=\"mono\">\/\/ Keep filters\/sort in Pinia; keep fetched lists in query cache<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan\">\n<h3>26) Fetching Patterns<\/h3>\n<p>Use <code>onMounted<\/code> for initial loads, abort controllers on unmount, and exponential backoff. For SSR, fetch in route or page setup and serialize data.<\/p>\n<pre><code class=\"mono\">const ctl = new AbortController();\r\nonUnmounted(() =&gt; ctl.abort())<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-lime\">\n<h3>27) Forms &#038; v-model<\/h3>\n<p>Use <code>v-model<\/code> for inputs, modifiers (<code>.trim<\/code>, <code>.number<\/code>) for parsing, and custom components with <code>modelValue<\/code>. Validate with Vuelidate or custom composables.<\/p>\n<pre><code class=\"mono\">&lt;input v-model.trim=\"email\" type=\"email\" \/&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>28) Internationalization (i18n)<\/h3>\n<p>Vue I18n provides messages, pluralization, and lazy-loaded locales. Avoid recomputing on every render by memoizing formatters.<\/p>\n<pre><code class=\"mono\">{{ $t('hello_user', { name }) }}<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>29) Accessibility Routing<\/h3>\n<p>Focus the main region on route change, keep landmarks, and announce route changes via ARIA live regions for screen readers.<\/p>\n<pre><code class=\"mono\">&lt;div id=\"main\" tabindex=\"-1\" aria-live=\"polite\"&gt;&lt;router-view \/&gt;&lt;\/div&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald\">\n<h3>30) Q&amp;A \u2014 \u201cPinia vs Vuex?\u201d<\/h3>\n<p><span class=\"q\">Answer:<\/span> Pinia is the modern successor: simpler API, first-class TS support, modular stores, no mutation boilerplate. Use Pinia unless you maintain legacy Vuex codebases.<\/p>\n<\/p><\/div>\n<p>      <!-- ===================== SECTION 4: TOOLING, SSR & TESTING (31\u201340) ===================== --><\/p>\n<div class=\"section-title\">Section 4 \u2014 Tooling, SSR, Build &#038; Testing<\/div>\n<div class=\"card bg-green\">\n<h3>31) Vite Tooling<\/h3>\n<p>Vite gives instant dev server via ES modules and fast HMR. Configure aliases, env vars (<code>import.meta.env<\/code>), and code-splitting by route.<\/p>\n<pre><code class=\"mono\">npm create vite@latest myapp -- --template vue-ts<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>32) TypeScript with Vue<\/h3>\n<p>Use <code>vue-tsc<\/code> for SFC type-checking. Prefer <code>&lt;script setup lang=\"ts\"&gt;<\/code> for clean inference and IDE hints.<\/p>\n<pre><code class=\"mono\">npm i -D vue-tsc; npx vue-tsc --noEmit<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>33) Build Optimization<\/h3>\n<p>Code split by route, prefetch critical chunks, and treeshake unused components. Analyze bundles to spot heavy deps.<\/p>\n<pre><code class=\"mono\">npm i -D rollup-plugin-visualizer<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-violet\">\n<h3>34) SSR \/ SSG Concepts<\/h3>\n<p>Server-side render initial HTML for speed\/SEO, then hydrate on client. For content sites, use SSG to pre-generate pages at build time.<\/p>\n<pre><code class=\"mono\">\/\/ Nuxt\/Nitro or custom SSR with @vue\/server-renderer<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>35) Nuxt Overview<\/h3>\n<p>Nuxt is a meta-framework for Vue: file-based routing, server\/data fetching, SSR\/SSG, and conventions for SEO and performance.<\/p>\n<pre><code class=\"mono\">\/\/ pages\/index.vue, server\/api\/*.ts for endpoints<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan\">\n<h3>36) Testing: Unit<\/h3>\n<p>Use Vitest\/Jest + Vue Test Utils for component tests. Mount components with props, simulate events, assert DOM output.<\/p>\n<pre><code class=\"mono\">import { mount } from '@vue\/test-utils'\r\nexpect(mount(Counter).text()).toContain('0')<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-lime\">\n<h3>37) Testing: E2E<\/h3>\n<p>Playwright\/Cypress for end-to-end tests. Seed fixture data, test routing, forms, and accessibility.<\/p>\n<pre><code class=\"mono\">\/\/ cy.visit('\/'); cy.findByRole('button', {name:\/save\/i}).click()<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>38) Linting &#038; Formatting<\/h3>\n<p>ESLint + @vue\/eslint-config, Prettier for consistent style. Enforce <code>defineProps<\/code> types and component naming rules.<\/p>\n<pre><code class=\"mono\">npm i -D eslint @vue\/eslint-config-typescript prettier<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>39) CI\/CD<\/h3>\n<p>Run type checks, unit\/E2E tests, and build previews on every PR. Cache node_modules and Vite cache for speed.<\/p>\n<pre><code class=\"mono\"># GitHub Actions: setup-node, cache, npm ci, npm run build, npm test<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald\">\n<h3>40) Q&amp;A \u2014 \u201cWhen pick Nuxt over Vite-only?\u201d<\/h3>\n<p><span class=\"q\">Answer:<\/span> Choose Nuxt if you need SSR\/SSG, file-based routing, server APIs, and SEO out-of-the-box. Use Vite-only for SPAs or when you want minimal scaffolding and full control.<\/p>\n<\/p><\/div>\n<p>      <!-- ===================== SECTION 5: RECIPES, PITFALLS & INTERVIEW (41\u201350) ===================== --><\/p>\n<div class=\"section-title\">Section 5 \u2014 Recipes, Pitfalls &#038; Interview Q&amp;A<\/div>\n<div class=\"card bg-green\">\n<h3>41) Recipe: Fetch + Cache Composable<\/h3>\n<p>A simple stale-while-revalidate approach: return cached data immediately, then refresh in background and notify dependents.<\/p>\n<pre><code class=\"mono\">const cache = reactive(new Map());\r\nexport function useCache(key, loader){\r\n  const data = ref(cache.get(key)); const loading = ref(!data.value);\r\n  const refresh = async() =&gt; { loading.value=true; const v = await loader(); cache.set(key, v); data.value=v; loading.value=false; };\r\n  onMounted(refresh); return { data, loading, refresh };\r\n}<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>42) Recipe: Debounced Input<\/h3>\n<p>Debounce queries to reduce chatter; cancel stale requests on new input.<\/p>\n<pre><code class=\"mono\">const q = ref(''); watch(q, debounce(runSearch, 300));<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>43) Recipe: Modal with Teleport<\/h3>\n<p>Portal modal to <code>body<\/code>, trap focus, and restore on close.<\/p>\n<pre><code class=\"mono\">&lt;teleport to=\"body\"&gt;&lt;Modal v-if=\"open\" @close=\"open=false\" \/&gt;&lt;\/teleport&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-violet\">\n<h3>44) Recipe: Infinite List<\/h3>\n<p>Use IntersectionObserver composable to fetch next page and append items; show skeletons while loading.<\/p>\n<pre><code class=\"mono\">const loadMore = async()=&gt;{ page.value++; items.value.push(...await api(page.value)) }<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>45) Common Pitfalls<\/h3>\n<p>Mutating props, deep reactive structures causing perf issues, forgetting <code>.value<\/code> on refs, heavy watchers, and global CSS leakage. Fix with computed, shallowRef\/shallowReactive, and scoped CSS.<\/p>\n<pre><code class=\"mono\">\/\/ Don't mutate props; emit updates instead<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan\">\n<h3>46) Security Basics<\/h3>\n<p>Sanitize user HTML, prefer server-side session cookies, protect API keys, and validate data before rendering. Vue escapes by default\u2014avoid <code>v-html<\/code> unless sanitized.<\/p>\n<pre><code class=\"mono\">&lt;div v-html=\"safeHtml\"&gt;&lt;\/div&gt; &lt;!-- safeHtml must be sanitized --&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-lime\">\n<h3>47) Accessibility Checklist<\/h3>\n<p>Labels for inputs, keyboard nav, focus styles, high contrast, and ARIA roles for composites (tabs, dialog). Test with screen reader + keyboard only.<\/p>\n<pre><code class=\"mono\">&lt;button aria-expanded=\"open\" :aria-controls=\"id\"&gt;Toggle&lt;\/button&gt;<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>48) Production Checklist<\/h3>\n<p>Type-check, lint, test, analyze bundle, enable gzip\/brotli, configure caching headers, handle errors\/logging, and monitor Web Vitals.<\/p>\n<pre><code class=\"mono\">import.meta.env.PROD \/\/ feature flags per env<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>49) Migration Tips (Vue 2 \u2192 3)<\/h3>\n<p>Use the migration build, replace filters with computed\/methods, move to Composition API gradually, update plugins to Vue 3 equivalents, and retest directives.<\/p>\n<pre><code class=\"mono\">\/\/ Vue 2 filters \u2192 Vue 3 computed\/formatters<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald qa\">\n<h3>50) Interview Q&amp;A \u2014 20 Practical Questions (Expanded)<\/h3>\n<p><b>1) Options vs Composition API?<\/b> Options organizes by option type (data, methods); Composition organizes by feature logic via composables\u2014better for scaling and TS.<\/p>\n<p><b>2) When computed over watch?<\/b> Use computed for pure derivations; watch for side effects or async flows.<\/p>\n<p><b>3) Props down, events up?<\/b> Parents pass props; children emit events back. For deep trees, consider provide\/inject or a store (Pinia).<\/p>\n<p><b>4) What does &lt;script setup&gt; do?<\/b> Syntactic sugar for Composition API with better treeshaking and less boilerplate; top-level bindings are template-available.<\/p>\n<p><b>5) How v-model works on components?<\/b> It maps to <code>modelValue<\/code> prop and <code>update:modelValue<\/code> event; supports multiple arguments (e.g., <code>v-model:title<\/code>).<\/p>\n<p><b>6) Key differences Vue vs React?<\/b> Vue uses templates with reactivity system and directives; React uses JSX and a different state model. Vue\u2019s reactivity is automatic; React relies on state setters and reconciliation.<\/p>\n<p><b>7) Why Pinia over Vuex?<\/b> Simpler API, no mutations, first-class TS, modular stores; official recommendation for Vue 3.<\/p>\n<p><b>8) Teleport use cases?<\/b> Modals, tooltips, dropdowns that must escape overflow\/stacking context.<\/p>\n<p><b>9) Preventing unnecessary updates?<\/b> Use computed, <code>shallowRef<\/code> for large objects, <code>v-memo<\/code> hints, and avoid creating new objects in templates.<\/p>\n<p><b>10) SSR benefits?<\/b> Faster first paint, SEO, and predictable content. Requires hydration and careful side-effect handling.<\/p>\n<p><b>11) How to type props\/emits?<\/b> Use TS generics with <code>defineProps&lt;T&gt;<\/code> and <code>defineEmits&lt;{ (e:'save', id:number):void }&gt;()<\/code>.<\/p>\n<p><b>12) Watch vs watchEffect?<\/b> <code>watch<\/code> tracks explicit sources; <code>watchEffect<\/code> tracks dependencies automatically (good for quick reactive effects).<\/p>\n<p><b>13) Handling async in setup?<\/b> Run in hooks (<code>onMounted<\/code>) or use async setup with Suspense; cancel on unmount.<\/p>\n<p><b>14) Global state options?<\/b> Pinia for app state; provide\/inject for simple shared deps; avoid event buses for complex apps.<\/p>\n<p><b>15) What is reactive caveat?<\/b> Destructuring reactive objects breaks reactivity\u2014use <code>toRefs()<\/code> or keep as object.<\/p>\n<p><b>16) Optimize lists?<\/b> Always use stable <code>:key<\/code>, virtualize long lists, and avoid heavy work in item components.<\/p>\n<p><b>17) Handling forms?<\/b> <code>v-model<\/code> with modifiers, validation composables, and debounced submits; keep source of truth in component or store by need.<\/p>\n<p><b>18) Error boundaries?<\/b> Use <code>errorCaptured<\/code> in parent; provide fallback UI and logging. For global, app-level handlers.<\/p>\n<p><b>19) Security with v-html?<\/b> Vue escapes by default; <code>v-html<\/code> does not\u2014sanitize and trust only safe sources.<\/p>\n<p><b>20) When to choose Nuxt?<\/b> For SSR\/SSG, SEO, conventions, server API integration, and DX with file-based routing. Otherwise Vite SPA is fine.<\/p>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Vue.js Pocket Book \u2014 Uplatz 50 in-depth cards \u2022 Wide layout \u2022 Readable examples \u2022 20-question interview Q&amp;A included Section 1 \u2014 Core Foundations 1) What is Vue.js? Vue is <span class=\"readmore\"><a href=\"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/\">Read More &#8230;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2462,2475],"tags":[],"class_list":["post-4469","post","type-post","status-publish","format-standard","hentry","category-pocket-book","category-vue-js"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Vue.js Pocket Book | Uplatz Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Vue.js Pocket Book | Uplatz Blog\" \/>\n<meta property=\"og:description\" content=\"Vue.js Pocket Book \u2014 Uplatz 50 in-depth cards \u2022 Wide layout \u2022 Readable examples \u2022 20-question interview Q&amp;A included Section 1 \u2014 Core Foundations 1) What is Vue.js? Vue is Read More ...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/\" \/>\n<meta property=\"og:site_name\" content=\"Uplatz Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Uplatz-1077816825610769\/\" \/>\n<meta property=\"article:published_time\" content=\"2025-08-09T16:07:03+00:00\" \/>\n<meta name=\"author\" content=\"uplatzblog\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@uplatz_global\" \/>\n<meta name=\"twitter:site\" content=\"@uplatz_global\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"uplatzblog\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/vue-js-pocket-book\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/vue-js-pocket-book\\\/\"},\"author\":{\"name\":\"uplatzblog\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#\\\/schema\\\/person\\\/8ecae69a21d0757bdb2f776e67d2645e\"},\"headline\":\"Vue.js Pocket Book\",\"datePublished\":\"2025-08-09T16:07:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/vue-js-pocket-book\\\/\"},\"wordCount\":1453,\"publisher\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#organization\"},\"articleSection\":[\"Pocket Book\",\"Vue.js\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/vue-js-pocket-book\\\/\",\"url\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/vue-js-pocket-book\\\/\",\"name\":\"Vue.js Pocket Book | Uplatz Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#website\"},\"datePublished\":\"2025-08-09T16:07:03+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/vue-js-pocket-book\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/uplatz.com\\\/blog\\\/vue-js-pocket-book\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/vue-js-pocket-book\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Vue.js Pocket Book\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/\",\"name\":\"Uplatz Blog\",\"description\":\"Uplatz is a global IT Training &amp; Consulting company\",\"publisher\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#organization\",\"name\":\"uplatz.com\",\"url\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/11\\\/Uplatz-Logo-Copy-2.png\",\"contentUrl\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/11\\\/Uplatz-Logo-Copy-2.png\",\"width\":1280,\"height\":800,\"caption\":\"uplatz.com\"},\"image\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/Uplatz-1077816825610769\\\/\",\"https:\\\/\\\/x.com\\\/uplatz_global\",\"https:\\\/\\\/www.instagram.com\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/7956715?trk=tyah&amp;amp;amp;amp;trkInfo=clickedVertical:company,clickedEntityId:7956715,idx:1-1-1,tarId:1464353969447,tas:uplatz\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#\\\/schema\\\/person\\\/8ecae69a21d0757bdb2f776e67d2645e\",\"name\":\"uplatzblog\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g\",\"caption\":\"uplatzblog\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Vue.js Pocket Book | Uplatz Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/","og_locale":"en_US","og_type":"article","og_title":"Vue.js Pocket Book | Uplatz Blog","og_description":"Vue.js Pocket Book \u2014 Uplatz 50 in-depth cards \u2022 Wide layout \u2022 Readable examples \u2022 20-question interview Q&amp;A included Section 1 \u2014 Core Foundations 1) What is Vue.js? Vue is Read More ...","og_url":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/","og_site_name":"Uplatz Blog","article_publisher":"https:\/\/www.facebook.com\/Uplatz-1077816825610769\/","article_published_time":"2025-08-09T16:07:03+00:00","author":"uplatzblog","twitter_card":"summary_large_image","twitter_creator":"@uplatz_global","twitter_site":"@uplatz_global","twitter_misc":{"Written by":"uplatzblog"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/#article","isPartOf":{"@id":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/"},"author":{"name":"uplatzblog","@id":"https:\/\/uplatz.com\/blog\/#\/schema\/person\/8ecae69a21d0757bdb2f776e67d2645e"},"headline":"Vue.js Pocket Book","datePublished":"2025-08-09T16:07:03+00:00","mainEntityOfPage":{"@id":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/"},"wordCount":1453,"publisher":{"@id":"https:\/\/uplatz.com\/blog\/#organization"},"articleSection":["Pocket Book","Vue.js"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/","url":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/","name":"Vue.js Pocket Book | Uplatz Blog","isPartOf":{"@id":"https:\/\/uplatz.com\/blog\/#website"},"datePublished":"2025-08-09T16:07:03+00:00","breadcrumb":{"@id":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/uplatz.com\/blog\/vue-js-pocket-book\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/uplatz.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Vue.js Pocket Book"}]},{"@type":"WebSite","@id":"https:\/\/uplatz.com\/blog\/#website","url":"https:\/\/uplatz.com\/blog\/","name":"Uplatz Blog","description":"Uplatz is a global IT Training &amp; Consulting company","publisher":{"@id":"https:\/\/uplatz.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/uplatz.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/uplatz.com\/blog\/#organization","name":"uplatz.com","url":"https:\/\/uplatz.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/uplatz.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/uplatz.com\/blog\/wp-content\/uploads\/2016\/11\/Uplatz-Logo-Copy-2.png","contentUrl":"https:\/\/uplatz.com\/blog\/wp-content\/uploads\/2016\/11\/Uplatz-Logo-Copy-2.png","width":1280,"height":800,"caption":"uplatz.com"},"image":{"@id":"https:\/\/uplatz.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Uplatz-1077816825610769\/","https:\/\/x.com\/uplatz_global","https:\/\/www.instagram.com\/","https:\/\/www.linkedin.com\/company\/7956715?trk=tyah&amp;amp;amp;amp;trkInfo=clickedVertical:company,clickedEntityId:7956715,idx:1-1-1,tarId:1464353969447,tas:uplatz"]},{"@type":"Person","@id":"https:\/\/uplatz.com\/blog\/#\/schema\/person\/8ecae69a21d0757bdb2f776e67d2645e","name":"uplatzblog","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g","caption":"uplatzblog"}}]}},"_links":{"self":[{"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/posts\/4469","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/comments?post=4469"}],"version-history":[{"count":1,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/posts\/4469\/revisions"}],"predecessor-version":[{"id":4470,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/posts\/4469\/revisions\/4470"}],"wp:attachment":[{"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/media?parent=4469"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/categories?post=4469"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/tags?post=4469"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}