[{"data":1,"prerenderedAt":4080},["ShallowReactive",2],{"all-posts":3,"post:\u002Fithome-2024-day-22":1210},[4,23,35,46,57,68,80,91,102,114,126,138,149,160,171,182,193,204,215,226,237,248,258,268,278,288,298,308,319,330,341,354,368,380,390,400,411,421,431,441,451,461,471,481,491,501,511,521,531,541,551,561,571,581,591,601,611,621,631,641,651,661,675,691,704,719,731,742,752,762,772,782,792,802,812,822,832,842,852,862,871,881,891,901,911,921,931,941,951,961,971,980,990,1000,1010,1020,1036,1050,1062,1073,1083,1095,1107,1121,1134,1145,1156,1167,1180,1191,1201],{"path":5,"title":6,"description":7,"date":8,"updated":9,"tags":10,"categories":14,"draft":15,"wordCount":16,"readingTime":17,"canonical":18,"series":19},"\u002Fithome-2026-day-30","Day 30：Angular Router Providers 與生命週期管理，路由離開後 Service 會銷毀嗎？","平常在 Angular 中，我們可以透過 providers 決定 Service 的注入範圍。例如註冊在 Root，讓整個 Application 共用同一個實例；或註冊在 Component，讓 Service 隨著…","2026-10-14T14:46:39+08:00",null,[11,12,13],"iThome 鐵人賽","2026 鐵人賽","Angular",[11,13],false,7227,7,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10424222",{"name":20,"url":21,"day":22},"2026 iThome 鐵人賽：Angular 22 Signal 進化論","https:\u002F\u002Fithelp.ithome.com.tw\u002Fusers\u002F20116554\u002Fironman\u002F9939",30,{"path":24,"title":25,"description":26,"date":27,"updated":9,"tags":28,"categories":29,"draft":15,"wordCount":30,"readingTime":31,"canonical":32,"series":33},"\u002Fithome-2026-day-29","Day 29：Angular 也有 VueUse？使用 Signality 整合常見 Browser API","在 Vue 生態系中，VueUse 提供許多 Composables，讓我們可以快速使用瀏覽器功能，例如監聽網路狀態、保存使用者設定，或偵測元素是否進入可視範圍。","2026-10-13T23:14:18+08:00",[11,12,13],[11,13],6387,6,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10424070",{"name":20,"url":21,"day":34},29,{"path":36,"title":37,"description":38,"date":39,"updated":9,"tags":40,"categories":41,"draft":15,"wordCount":42,"readingTime":31,"canonical":43,"series":44},"\u002Fithome-2026-day-28","Day 28：Angular 動態建立 Component，NgComponentOutlet 與 ViewContainerRef","平常在 Angular 中使用 Component，通常會直接在 Template 裡面宣告：","2026-10-12T17:27:41+08:00",[11,12,13],[11,13],6565,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10423641",{"name":20,"url":21,"day":45},28,{"path":47,"title":48,"description":49,"date":50,"updated":9,"tags":51,"categories":52,"draft":15,"wordCount":53,"readingTime":17,"canonical":54,"series":55},"\u002Fithome-2026-day-27","Day 27：NgRx Store vs SignalStore，從 Action、Reducer 到直接更新 State","前幾天我們使用 NgRx SignalStore 實作購物車，透過 withState() 管理商品資料、withComputed() 計算總金額，再利用 withMethods() 與 patchState() 更新 …","2026-10-11T20:06:41+08:00",[11,12,13],[11,13],7308,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10423362",{"name":20,"url":21,"day":56},27,{"path":58,"title":59,"description":60,"date":61,"updated":9,"tags":62,"categories":63,"draft":15,"wordCount":64,"readingTime":17,"canonical":65,"series":66},"\u002Fithome-2026-day-26","Day 26：SignalStore 與 Strategy Pattern，透過 DI 動態切換業務邏輯","昨天我們使用 Angular 原生 Signal 與 NgRx SignalStore 實作購物車，透過 State 管理商品資料，再利用 Computed 計算商品數量與總金額。","2026-10-10T22:01:59+08:00",[11,12,13],[11,13],7347,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10423116",{"name":20,"url":21,"day":67},26,{"path":69,"title":70,"description":71,"date":72,"updated":9,"tags":73,"categories":74,"draft":15,"wordCount":75,"readingTime":76,"canonical":77,"series":78},"\u002Fithome-2026-day-25","Day 25：Angular SignalStore，原生 Signal 不夠用嗎？","在 Angular 開發中，如果資料只會被單一 Component 使用，通常可以直接透過 signal() 管理。但當多個 Component 需要共用同一份資料時，就得考慮狀態應該放在哪裡。","2026-10-09T21:28:45+08:00",[11,12,13],[11,13],9117,9,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10422784",{"name":20,"url":21,"day":79},25,{"path":81,"title":82,"description":83,"date":84,"updated":9,"tags":85,"categories":86,"draft":15,"wordCount":87,"readingTime":31,"canonical":88,"series":89},"\u002Fithome-2026-day-24","Day 24：SPA Router 為什麼不再只靠 History API？","平常使用 Angular Router 時，可以透過 routerLink 或 router.navigate() 切換不同頁面。","2026-10-08T14:30:47+08:00",[11,12,13],[11,13],6330,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10422348",{"name":20,"url":21,"day":90},24,{"path":92,"title":93,"description":94,"date":95,"updated":9,"tags":96,"categories":97,"draft":15,"wordCount":98,"readingTime":17,"canonical":99,"series":100},"\u002Fithome-2026-day-23","Day 23：RouteReuseStrategy，切換路由一定要銷毀 Component 嗎？","在後台系統中，很常會看到頁籤式介面，例如：","2026-10-07T15:58:32+08:00",[11,12,13],[11,13],7361,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10422016",{"name":20,"url":21,"day":101},23,{"path":103,"title":104,"description":105,"date":106,"updated":9,"tags":107,"categories":108,"draft":15,"wordCount":109,"readingTime":110,"canonical":111,"series":112},"\u002Fithome-2026-day-22","Day 22：Angular Render Lifecycle，從 afterNextRender 到 DestroyRef","過去在 Angular 中，只要遇到初始化、View 建立或資源清理，通常會先想到 Lifecycle Hooks：","2026-10-06T23:36:23+08:00",[11,12,13],[11,13],8111,8,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10421810",{"name":20,"url":21,"day":113},22,{"path":115,"title":116,"description":117,"date":118,"updated":9,"tags":119,"categories":120,"draft":15,"wordCount":121,"readingTime":122,"canonical":123,"series":124},"\u002Fithome-2026-day-21","Day 21：Angular Template 還適合呼叫 Method 嗎？從 Pipe、RxJS 到 computed","過去在寫 Angular 時，因為 Template 可以直接呼叫 Method，很容易在專案裡看到大量這樣的寫法。","2026-10-05T23:30:32+08:00",[11,12,13],[11,13],5431,5,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10421425",{"name":20,"url":21,"day":125},21,{"path":127,"title":128,"description":129,"date":130,"updated":9,"tags":131,"categories":132,"draft":15,"wordCount":133,"readingTime":134,"canonical":135,"series":136},"\u002Fithome-2026-day-20","Day 20：Signal Forms 非同步驗證，validateHttp 與 validateAsync","前兩篇介紹了 Signal Forms 的基本驗證，以及需要參考其他欄位的 Cross-field Validation。","2026-10-04T20:56:17+08:00",[11,12,13],[11,13],4278,4,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10420910",{"name":20,"url":21,"day":137},20,{"path":139,"title":140,"description":141,"date":142,"updated":9,"tags":143,"categories":144,"draft":15,"wordCount":145,"readingTime":134,"canonical":146,"series":147},"\u002Fithome-2026-day-19","Day 19：Signal Forms Cross-field Validation 與欄位更新時機","上一篇介紹 Signal Forms 時，已經看到可以透過 Schema 定義欄位驗證，例如 required()、email()、minLength()。","2026-10-03T23:18:26+08:00",[11,12,13],[11,13],3783,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10420631",{"name":20,"url":21,"day":148},19,{"path":150,"title":151,"description":152,"date":153,"updated":9,"tags":154,"categories":155,"draft":15,"wordCount":156,"readingTime":31,"canonical":157,"series":158},"\u002Fithome-2026-day-18","Day 18：Angular Signal Forms 穩定了，跟我們用了這麼久的 Reactive Forms 到底差在哪？","在 Angular 中處理表單，很多專案使用的都是 Reactive Forms。","2026-10-02T23:28:36+08:00",[11,12,13],[11,13],5886,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10420249",{"name":20,"url":21,"day":159},18,{"path":161,"title":162,"description":163,"date":164,"updated":9,"tags":165,"categories":166,"draft":15,"wordCount":167,"readingTime":31,"canonical":168,"series":169},"\u002Fithome-2026-day-17","Day 17：effect() 不是拿來同步 Signal 的，Angular 的 Side Effect 該怎麼寫？","effect() 是 Angular signal 裡很容易被誤用的一個 API。因為寫法直覺，只要讀取 signal，就能在值改變時執行一些事情，所以很常被拿來同步狀態、打 API，甚至再去修改其他 signal。","2026-10-01T21:22:13+08:00",[11,12,13],[11,13],6473,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10419779",{"name":20,"url":21,"day":170},17,{"path":172,"title":173,"description":174,"date":175,"updated":9,"tags":176,"categories":177,"draft":15,"wordCount":178,"readingTime":31,"canonical":179,"series":180},"\u002Fithome-2026-day-16","Day 16：即將登場的 Route Resources，Angular Router 為什麼需要新的資料載入方式？","過去在 Angular Router 中，如果希望進入 Component 前先完成資料載入，可以透過 Resolver，讓資料取得流程在 Component 初始化之前執行。","2026-09-30T23:12:05+08:00",[11,12,13],[11,13],6534,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10419409",{"name":20,"url":21,"day":181},16,{"path":183,"title":184,"description":185,"date":186,"updated":9,"tags":187,"categories":188,"draft":15,"wordCount":189,"readingTime":17,"canonical":190,"series":191},"\u002Fithome-2026-day-15","Day 15：搞懂 Injection Context，從 inject()、runInInjectionContext() 到 injectAsync()","前面提到 Injection Context 時，可能會讓人聯想到先前介紹過的 Reactive Context。我一開始也有點搞混，因此花了一些時間重新理解 Angular 裡這些不同的執行環境。","2026-09-29T13:44:28+08:00",[11,12,13],[11,13],6986,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10418752",{"name":20,"url":21,"day":192},15,{"path":194,"title":195,"description":196,"date":197,"updated":9,"tags":198,"categories":199,"draft":15,"wordCount":200,"readingTime":17,"canonical":201,"series":202},"\u002Fithome-2026-day-14","Day 14：Lazy Loading 不只一種，從 Router Preloading、@defer 到 injectAsync()","當 Client Side Rendering 的應用越來越大時，我們通常會開始思考，能不能把原本一次載入的內容拆得更小，等到真正需要時再下載，避免初始載入過多 JavaScript，拉長畫面呈現的時間。","2026-09-28T22:44:46+08:00",[11,12,13],[11,13],7674,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10418485",{"name":20,"url":21,"day":203},14,{"path":205,"title":206,"description":207,"date":208,"updated":9,"tags":209,"categories":210,"draft":15,"wordCount":211,"readingTime":110,"canonical":212,"series":213},"\u002Fithome-2026-day-13","Day 13：從 Router Event 到 Signal","路由狀態管理在前端開發中比較少被單獨拿出來討論，但在 Angular 裡，一次路由導航其實會經過不少階段，也會在過程中發出不同的 Router Event，例如 NavigationStart、NavigationEnd…","2026-09-27T20:37:55+08:00",[11,12,13],[11,13],7777,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10417948",{"name":20,"url":21,"day":214},13,{"path":216,"title":217,"description":218,"date":219,"updated":9,"tags":220,"categories":221,"draft":15,"wordCount":222,"readingTime":122,"canonical":223,"series":224},"\u002Fithome-2026-day-12","Day 12：從 httpResource 到 TanStack Query，認識 Server State","前面我們花了不少時間討論，為什麼「請求本身的狀態」和「元件的顯示狀態」應該分開處理。","2026-09-26T23:35:12+08:00",[11,12,13],[11,13],5119,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10417614",{"name":20,"url":21,"day":225},12,{"path":227,"title":228,"description":229,"date":230,"updated":9,"tags":231,"categories":232,"draft":15,"wordCount":233,"readingTime":122,"canonical":234,"series":235},"\u002Fithome-2026-day-11","Day 11：用 rxResource 串起 Observable 與 Resource","前面介紹了不少 Resource 到 httpResource() 的應用。不過在 Angular 開發中，Observable 與 RxJS 仍然是很常見的非同步資料處理方式，像是 switchMap、map、debo…","2026-09-25T22:42:04+08:00",[11,12,13],[11,13],4908,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10417143",{"name":20,"url":21,"day":236},11,{"path":238,"title":239,"description":240,"date":241,"updated":9,"tags":242,"categories":243,"draft":15,"wordCount":244,"readingTime":31,"canonical":245,"series":246},"\u002Fithome-2026-day-10","Day 10：linkedSignal 讓相依狀態也能被修改","昨天我們透過 httpResource() 搭配 chain() 處理兩個非同步資料之間的依賴。下游 Request 需要使用上游資料時，會等上游完成後再繼續；當 Request 的來源改變，Resource 的狀態也會…","2026-09-24T23:49:49+08:00",[11,12,13],[11,13],5623,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10416746",{"name":20,"url":21,"day":247},10,{"path":249,"title":250,"description":251,"date":252,"updated":9,"tags":253,"categories":254,"draft":15,"wordCount":255,"readingTime":134,"canonical":256,"series":257},"\u002Fithome-2026-day-09","Day 9：httpResource 實務篇，統一回覆格式與 chain 相依請求","昨天我們透過 Orval 串起 API Contract，了解如何根據 OpenAPI 規格產生前端需要的型別與 API 呼叫方式。","2026-09-23T23:42:40+08:00",[11,12,13],[11,13],4358,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10416227",{"name":20,"url":21,"day":76},{"path":259,"title":260,"description":261,"date":262,"updated":9,"tags":263,"categories":264,"draft":15,"wordCount":265,"readingTime":122,"canonical":266,"series":267},"\u002Fithome-2026-day-08","Day 8：用 Orval 串起 Angular API Contract，同時產生 HttpClient、httpResource 與 Zod","前後端在對接 API 時，常見的問題之一，就是雙方對資料格式的定義逐漸不一致。","2026-09-22T23:48:12+08:00",[11,12,13],[11,13],4451,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10415694",{"name":20,"url":21,"day":110},{"path":269,"title":270,"description":271,"date":272,"updated":9,"tags":273,"categories":274,"draft":15,"wordCount":275,"readingTime":17,"canonical":276,"series":277},"\u002Fithome-2026-day-07","Day 7：從 Resource 到 httpResource，用 Signal 管理 HTTP 資料請求","昨天我們提到，Resource API 本身是一套通用的非同步資料模型，比較適合用在「讀取資料」這類情境，而不是新增、修改或刪除資料這種 Mutation 操作。","2026-09-21T22:13:18+08:00",[11,12,13],[11,13],6735,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10415038",{"name":20,"url":21,"day":17},{"path":279,"title":280,"description":281,"date":282,"updated":9,"tags":283,"categories":284,"draft":15,"wordCount":285,"readingTime":122,"canonical":286,"series":287},"\u002Fithome-2026-day-06","Day 6：Resource API，把非同步資料帶進 Signal","今天來看 Angular Signal 裡一個很重要的非同步資料 API：Resource API。","2026-09-20T19:25:37+08:00",[11,12,13],[11,13],5054,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10414377",{"name":20,"url":21,"day":31},{"path":289,"title":290,"description":291,"date":292,"updated":9,"tags":293,"categories":294,"draft":15,"wordCount":295,"readingTime":134,"canonical":296,"series":297},"\u002Fithome-2026-day-05","Day 5：從 Reactive Graph 到 View Tree，看 Angular 如何找到真正需要更新的畫面","前面我們已經知道，當 Signal 的值發生變化後，Angular 會透過 Reactive Graph 找到受到影響的 Consumer。","2026-09-19T20:19:47+08:00",[11,12,13],[11,13],4364,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10413852",{"name":20,"url":21,"day":122},{"path":299,"title":300,"description":301,"date":302,"updated":9,"tags":303,"categories":304,"draft":15,"wordCount":305,"readingTime":122,"canonical":306,"series":307},"\u002Fithome-2026-day-04","Day 4：Angular 怎麼知道誰正在讀 Signal？從 Reactive Context 理解依賴追蹤","前面我們看過，當 Template 讀取 Signal 時，Angular 會記住「誰依賴了誰」；當 Signal 發生變化後，也會透過 Reactive Graph 通知相關的 Consumer。","2026-09-18T21:58:16+08:00",[11,12,13],[11,13],4894,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10413313",{"name":20,"url":21,"day":134},{"path":309,"title":310,"description":311,"date":312,"updated":9,"tags":313,"categories":314,"draft":15,"wordCount":315,"readingTime":122,"canonical":316,"series":317},"\u002Fithome-2026-day-03","Day 3：從 set()、update() 看懂 Angular Signal 的基本使用與更新機制","昨天我們先試著理解，在 Template 中使用 Signal() 時，Angular 是如何建立依賴關係，並在 Signal 發生變化後，知道哪些 View 可能受到影響。","2026-09-17T23:08:58+08:00",[11,12,13],[11,13],5451,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10412826",{"name":20,"url":21,"day":318},3,{"path":320,"title":321,"description":322,"date":323,"updated":9,"tags":324,"categories":325,"draft":15,"wordCount":326,"readingTime":134,"canonical":327,"series":328},"\u002Fithome-2026-day-02","Day 2：Angular Signal 是什麼？從 Change Detection 理解它的運作原理","傳統 Angular 在監測資料變化時，通常會搭配 zone.js。像是 DOM 事件、Promise、Timer、HTTP 請求這些非同步操作發生時，zone.js 會幫忙攔截。","2026-09-16T20:19:12+08:00",[11,12,13],[11,13],4276,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10411944",{"name":20,"url":21,"day":329},2,{"path":331,"title":332,"description":333,"date":334,"updated":9,"tags":335,"categories":336,"draft":15,"wordCount":337,"readingTime":329,"canonical":338,"series":339},"\u002Fithome-2026-day-01","Day 1：為什麼想聊 Angular Signal？","相信講到前端框架，大家第一時間想到的通常會是 Vue、React，甚至也有人會推薦 Svelte 這類近年討論度很高的框架。但一講到 Angular，很多人的第一印象可能就像看到一座大城堡一樣：東西很多、規則很多，一時之…","2026-09-15T23:56:26+08:00",[11,12,13],[11,13],1478,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10411425",{"name":20,"url":21,"day":340},1,{"path":342,"title":343,"description":344,"date":345,"updated":9,"tags":346,"categories":351,"draft":15,"wordCount":353,"readingTime":134,"canonical":9,"series":9},"\u002FTS-Excess-Property-Checks","TypeScript 踩坑筆記：物件字面量的多餘屬性檢查機制","深入探討 TypeScript 的多餘屬性檢查（Excess Property Checks）機制，解析物件字面量與變數賦值的型別檢查差異，並提供實務開發中避免型別陷阱的最佳實踐方法。","2026-01-31T16:29:23+08:00",[347,348,349,350],"Excess Property Checks","Structural Typing","Type Safety","NestJS",[352],"TypeScript",3551,{"path":355,"title":356,"description":357,"date":358,"updated":9,"tags":359,"categories":361,"draft":15,"wordCount":363,"readingTime":329,"canonical":364,"series":365},"\u002Fithome-2025-day-30","Day 30：開發之旅完結 - 感謝與展望","終於來到鐵人賽的最後一天！這是我第二次參加鐵人賽，今年的主題是 LINE Bot 開發。這個主題源自於我參加的十二週讀書會分享，當時我發現大家對 LINE Bot 很感興趣，而我自己也一直很喜歡這個主題，於是早在六月就定…","2025-10-13T20:11:12+08:00",[11,360],"2025 鐵人賽",[11,362],"Line Bot",1751,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10396850",{"name":366,"url":367,"day":22},"2025 iThome 鐵人賽：Line Bot × NestJS：30 天開發日記","https:\u002F\u002Fithelp.ithome.com.tw\u002Fusers\u002F20116554\u002Fironman\u002F8779",{"path":369,"title":370,"description":371,"date":372,"updated":9,"tags":373,"categories":376,"draft":15,"wordCount":377,"readingTime":31,"canonical":378,"series":379},"\u002Fithome-2025-day-29","Day 29：LIFF 會員註冊 - 信箱驗證與 Swagger 文件整合","延續 Day 28 會員註冊的流程，在實際的會員註冊場景中，電子信箱驗證是確保用戶身份真實性的重要環節。本篇將基於昨天的註冊流程，新增兩個核心 API：發送驗證信與驗證驗證碼，讓會員註冊功能更加完整且安全。","2025-10-12T23:15:00+08:00",[11,360,362,374,350,375],"LIFF","Swagger",[11,362],6089,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10396512",{"name":366,"url":367,"day":34},{"path":381,"title":382,"description":383,"date":384,"updated":9,"tags":385,"categories":386,"draft":15,"wordCount":387,"readingTime":122,"canonical":388,"series":389},"\u002Fithome-2025-day-28","Day 28：LIFF 會員註冊 - ID Token 驗證與資料庫整合","今天的開發重點是建立會員卡系統，將 LIFF 前端與 NestJS 後端完整串接。","2025-10-11T22:57:29+08:00",[11,360,362,374,350],[11,362],5254,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10396146",{"name":366,"url":367,"day":45},{"path":391,"title":392,"description":393,"date":394,"updated":9,"tags":395,"categories":396,"draft":15,"wordCount":397,"readingTime":318,"canonical":398,"series":399},"\u002Fithome-2025-day-27","Day 27：群組事件與檔案訊息接收","今天主要補充 LINE Bot 在群組中的專屬特性，包括群組限定的 Webhook 事件，以及前面提到但尚未說明的第 7 種訊息類型 file 檔案訊息。","2025-10-10T21:01:52+08:00",[11,360,362,350],[11,362],2888,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10395785",{"name":366,"url":367,"day":56},{"path":401,"title":402,"description":403,"date":404,"updated":9,"tags":405,"categories":407,"draft":15,"wordCount":408,"readingTime":122,"canonical":409,"series":410},"\u002Fithome-2025-day-26","Day 26：LINE Pay 線上付款","LINE Pay 提供兩種付款方式：線上付款與實體付款。實體付款主要採用店家出示條碼的模式，顧客掃描後即可輸入金額完成付款。這兩種付款方式都支援在沙盒(Sandbox)環境中進行測試。本文將著重說明線上付款的整合流程。","2025-10-09T23:39:32+08:00",[11,360,406],"Line Pay",[11,362],4876,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10395481",{"name":366,"url":367,"day":67},{"path":412,"title":413,"description":414,"date":415,"updated":9,"tags":416,"categories":417,"draft":15,"wordCount":418,"readingTime":318,"canonical":419,"series":420},"\u002Fithome-2025-day-25","Day 25：優惠券設定與 Coupon Message 實作","LINE Official Account 的「優惠券」是提升顧客互動與忠誠度的重要功能。透過獎勵機制，不僅能吸引新客，更能有效促進回購。","2025-10-08T23:49:32+08:00",[11,360,362,350],[11,362],3207,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10395076",{"name":366,"url":367,"day":79},{"path":422,"title":423,"description":424,"date":425,"updated":9,"tags":426,"categories":427,"draft":15,"wordCount":428,"readingTime":134,"canonical":429,"series":430},"\u002Fithome-2025-day-24","Day 24：LIFF 刮刮樂實戰體驗","在了解 LIFF 的基礎設計流程後，本文將透過「刮刮樂」案例示範 LIFF API 的實際應用。從啟動時檢查權限與執行環境、確認用戶分享功能權限，到刮刮樂結束後發送訊息並關閉 LIFF，完整呈現 LIFF 在互動應用中的…","2025-10-07T22:36:58+08:00",[11,360,362,374],[11,362],4200,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10394618",{"name":366,"url":367,"day":90},{"path":432,"title":433,"description":434,"date":435,"updated":9,"tags":436,"categories":437,"draft":15,"wordCount":438,"readingTime":134,"canonical":439,"series":440},"\u002Fithome-2025-day-23","Day 23：LIFF 網頁應用開發入門","在鐵人賽前半段，我們深入探討了 LINE Bot 的兩大核心功能：Richmenu(選單設置)與各種 Reply Message(回覆訊息)的訊息類型。然而在實務應用中，若要提供更豐富的互動體驗，Line 往往需要搭配 …","2025-10-06T23:06:57+08:00",[11,360,362,374],[11,362],4400,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10394035",{"name":366,"url":367,"day":101},{"path":442,"title":443,"description":444,"date":445,"updated":9,"tags":446,"categories":447,"draft":15,"wordCount":448,"readingTime":329,"canonical":449,"series":450},"\u002Fithome-2025-day-22","Day 22：Render 雲端平台部署 Nest 後端伺服器","今天的目標是將系統正式上線。經過這段時間的開發，我們已完成 Line Message API 的核心功能與日誌處理機制。","2025-10-05T22:52:11+08:00",[11,360,362,350],[11,362],1895,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10393809",{"name":366,"url":367,"day":113},{"path":452,"title":453,"description":454,"date":455,"updated":9,"tags":456,"categories":457,"draft":15,"wordCount":458,"readingTime":318,"canonical":459,"series":460},"\u002Fithome-2025-day-21","Day 21：Nest Pino 整合 Grafana Loki 日誌","Loki 環境變數可參考 Day 20 文章的 Grafana Data Source settings 設定","2025-10-04T17:24:26+08:00",[11,360,362,350],[11,362],2740,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10393305",{"name":366,"url":367,"day":125},{"path":462,"title":463,"description":464,"date":465,"updated":9,"tags":466,"categories":467,"draft":15,"wordCount":468,"readingTime":318,"canonical":469,"series":470},"\u002Fithome-2025-day-20","Day 20：Grafana Loki 日誌服務 - 從申請到 API 串接測試","目前已經理解了 LINE Messaging API 的核心功能，包括如何接收訊息、串接第三方服務，以及發送多種類型的訊息。接下來，我們將把原本架設在 ngrok 的後端伺服器，透過 GitHub 自動化部署到 Rend…","2025-10-03T23:16:16+08:00",[11,360,362,350],[11,362],2461,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10392910",{"name":366,"url":367,"day":137},{"path":472,"title":473,"description":474,"date":475,"updated":9,"tags":476,"categories":477,"draft":15,"wordCount":478,"readingTime":318,"canonical":479,"series":480},"\u002Fithome-2025-day-19","Day 19：Flex Message Carousel 食譜分享","Flex Message 可以分成 bubble(單張卡片) 跟 carousel(多張卡片輪播) 兩種方式，昨天示範了 bubble 格式的電子個人名片後，今天主要展示 carousel 的應用，兩者的基本結構大致相同…","2025-10-02T16:06:17+08:00",[11,360,362,350],[11,362],2267,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10392256",{"name":366,"url":367,"day":148},{"path":482,"title":483,"description":484,"date":485,"updated":9,"tags":486,"categories":487,"draft":15,"wordCount":488,"readingTime":122,"canonical":489,"series":490},"\u002Fithome-2025-day-18","Day 18：Flex Message 設計個人名片","從基礎的文字互動開始，我們逐步探索了六大核心訊息類型的發送機制、Template Message 的結構化設計，以及 ImageMap Message 的互動式體驗。今天，我們將進入 LINE Bot 最具彈性的訊息格式…","2025-10-01T17:57:47+08:00",[11,360,362,350],[11,362],4468,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10391723",{"name":366,"url":367,"day":159},{"path":492,"title":493,"description":494,"date":495,"updated":9,"tags":496,"categories":497,"draft":15,"wordCount":498,"readingTime":122,"canonical":499,"series":500},"\u002Fithome-2025-day-17","Day 17：ImageMap Message  從互動海報到影片嵌入","在 Day 16 文章中，我們使用 Cloudflare Workers 實作了圖片代理功能。到目前為止，我們已經完成以下準備工作:","2025-09-30T11:58:32+08:00",[11,360,362,350],[11,362],4807,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10391164",{"name":366,"url":367,"day":170},{"path":502,"title":503,"description":504,"date":505,"updated":9,"tags":506,"categories":507,"draft":15,"wordCount":508,"readingTime":134,"canonical":509,"series":510},"\u002Fithome-2025-day-16","Day 16：Cloudflare Workers 圖片代理實作","在 Day 15 文章中，我們處理了 ImageMap Message 的背景圖，接著我們遇到了圖片不能出現副檔名及動態路徑支援不同解析度的問題。今天主要會透過 Cloudflare Workers 來解決這兩個問題，讓…","2025-09-29T16:15:41+08:00",[11,360,362,350],[11,362],3412,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10390567",{"name":366,"url":367,"day":181},{"path":512,"title":513,"description":514,"date":515,"updated":9,"tags":516,"categories":517,"draft":15,"wordCount":518,"readingTime":134,"canonical":519,"series":520},"\u002Fithome-2025-day-15","Day 15：共通屬性處理優化及 Imagemap  圖片製作","針對 Day 14 的程式碼架構進行優化。由於 Sender 和 Quick Reply 功能在所有回覆訊息類型中都能使用，我們應該將這些共用屬性抽取為獨立函數進行統一處理。","2025-09-28T21:03:38+08:00",[11,360,362,350],[11,362],4033,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10389697",{"name":366,"url":367,"day":192},{"path":522,"title":523,"description":524,"date":525,"updated":9,"tags":526,"categories":527,"draft":15,"wordCount":528,"readingTime":31,"canonical":529,"series":530},"\u002Fithome-2025-day-14","Day 14：LINE Bot Template Message 訊息回覆","經過前幾天的學習，我們已經成功掌握了 LINE Bot 六大基礎訊息類型的發送技巧，為訊息互動奠定了穩固的基礎。今天，我們將踏入更具挑戰性的進階應用領域！","2025-09-27T15:54:06+08:00",[11,360,362,350],[11,362],6372,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10388976",{"name":366,"url":367,"day":203},{"path":532,"title":533,"description":534,"date":535,"updated":9,"tags":536,"categories":537,"draft":15,"wordCount":538,"readingTime":122,"canonical":539,"series":540},"\u002Fithome-2025-day-13","Day 13：LINE Bot 客製化 Sender 與 Quick Reply 功能實作","LINE Bot 所有回覆訊息類型都具備「共用屬性」功能，這些屬性帶來兩項重要的互動體驗提升：","2025-09-26T11:41:34+08:00",[11,360,362,350],[11,362],4426,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10388037",{"name":366,"url":367,"day":214},{"path":542,"title":543,"description":544,"date":545,"updated":9,"tags":546,"categories":547,"draft":15,"wordCount":548,"readingTime":318,"canonical":549,"series":550},"\u002Fithome-2025-day-12","Day 12：LINE Bot Image、Video、Audio、Location 訊息回覆","Day 11 文章中，我們針對 LINE Bot 可以回覆的Text及Sticker基礎型別進行了封裝，不僅新增了 line-message.ts模組，還讓開發者可以用最少的參數產生 LINE Message 所需要的格…","2025-09-25T18:08:09+08:00",[11,360,362,350],[11,362],2977,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10387598",{"name":366,"url":367,"day":225},{"path":552,"title":553,"description":554,"date":555,"updated":9,"tags":556,"categories":557,"draft":15,"wordCount":558,"readingTime":31,"canonical":559,"series":560},"\u002Fithome-2025-day-11","Day 11：LINE Bot Text Emoji 與 Sticker 訊息回覆","目前我們的 LINE Bot 主要使用 Text 方式回覆訊息。今天將探討 Text 類型的 Emoji 應用，以及 Sticker 回覆方式，基於 Day 8 版本進行改寫。","2025-09-24T23:21:11+08:00",[11,360,350,362],[11,362],5659,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10386993",{"name":366,"url":367,"day":236},{"path":562,"title":563,"description":564,"date":565,"updated":9,"tags":566,"categories":567,"draft":15,"wordCount":568,"readingTime":318,"canonical":569,"series":570},"\u002Fithome-2025-day-10","Day 10：LINE Rich Menu Switch Action 提升使用者體驗","在 Day 9 文章中，我們結合 LINE 平台的功能，將天氣服務與圖片上傳服務整合，打造出第一張 LINE 圖文選單，透過 URI action 的方式觸發平台提供的互動效果。接著，我們使用客製化選單製作出 9 格的客…","2025-09-23T15:02:57+08:00",[11,360,362,350],[11,362],2906,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10386165",{"name":366,"url":367,"day":247},{"path":572,"title":573,"description":574,"date":575,"updated":9,"tags":576,"categories":577,"draft":15,"wordCount":578,"readingTime":318,"canonical":579,"series":580},"\u002Fithome-2025-day-09","Day  9：打造 LINE Rich Menu - 後台設計 vs API 客製化","在 Day8 文章中，我們透過整合雲端服務 Cloudinary，學習如何處理使用者上傳的圖片檔案，並將其儲存至雲端。然而，LINE Bot 除了讓使用者輸入文字回覆的方式之外，更常見的是透過圖文選單(Rich Menu…","2025-09-22T21:54:25+08:00",[11,360,362,350],[11,362],3285,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10385658",{"name":366,"url":367,"day":76},{"path":582,"title":583,"description":584,"date":585,"updated":9,"tags":586,"categories":587,"draft":15,"wordCount":588,"readingTime":17,"canonical":589,"series":590},"\u002Fithome-2025-day-08","Day 8：Cloudinary 雲端圖片儲存整合","在 Day 6 中，我們透過整合 OpenWeatherMap API 與座標位置訊息學習了如何結合第三方服務。今天將探索 Cloudinary 雲端服務，解決 LINE 圖片資源會過期的問題，學習如何透過 LINE M…","2025-09-21T23:13:19+08:00",[11,360,362,350],[11,362],7215,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10384968",{"name":366,"url":367,"day":110},{"path":592,"title":593,"description":594,"date":595,"updated":9,"tags":596,"categories":597,"draft":15,"wordCount":598,"readingTime":122,"canonical":599,"series":600},"\u002Fithome-2025-day-07","Day 7：Joi 環境變數統一驗證，重構 LINE Bot 天氣服務模組","在 Day 6 開發 LINE Bot 結合 OpenWeatherMap API 的過程中，我們採用私有方法將 API 請求處理與資料格式化整合在一起。今天將對 Day 6 的實作進行架構重構，主要目標是建立更完善的環…","2025-09-20T23:07:08+08:00",[11,360,362,350],[11,362],5157,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10384302",{"name":366,"url":367,"day":17},{"path":602,"title":603,"description":604,"date":605,"updated":9,"tags":606,"categories":607,"draft":15,"wordCount":608,"readingTime":134,"canonical":609,"series":610},"\u002Fithome-2025-day-06","Day 6：整合第三方 API 天氣查詢服務","Day 5 帶大家了解 LINE Bot 能接收使用者傳遞的「6+1」種訊息類型。之所以這樣強調，是因為 File 類型僅能在群組聊天中使用，這個限制我自己也經常忘記，所以習慣用「6+1」來提醒自己。","2025-09-19T21:07:47+08:00",[11,360,362,350],[11,362],3892,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10383636",{"name":366,"url":367,"day":31},{"path":612,"title":613,"description":614,"date":615,"updated":9,"tags":616,"categories":617,"draft":15,"wordCount":618,"readingTime":122,"canonical":619,"series":620},"\u002Fithome-2025-day-05","Day 5：整合 Pino Logger 提升 LINE Bot 專案的可維護性","看著專案逐漸成型，現在該開始重視日誌記錄的規劃了。在實際部署時，我們通常會區分 develop(開發環境)和 production(正式環境)兩種不同的執行環境，針對不同環境採用相應的日誌策略。","2025-09-18T23:30:00+08:00",[11,360,362,350],[11,362],4746,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10382298",{"name":366,"url":367,"day":122},{"path":622,"title":623,"description":624,"date":625,"updated":9,"tags":626,"categories":627,"draft":15,"wordCount":628,"readingTime":31,"canonical":629,"series":630},"\u002Fithome-2025-day-04","Day 4：掌握 LINE Bot 七種訊息類型與 NestJS 架構優化","目前我們都只使用 LINE Message Event 中的純文字(text)格式進行回覆，但除了純文字之外，LINE Bot 後端伺服器其實可以接收多種不同類型的訊息。今天就讓我們一起來深入了解這些訊息類型吧！","2025-09-17T22:53:37+08:00",[11,360,362,350],[11,362],5828,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10381651",{"name":366,"url":367,"day":134},{"path":632,"title":633,"description":634,"date":635,"updated":9,"tags":636,"categories":637,"draft":15,"wordCount":638,"readingTime":122,"canonical":639,"series":640},"\u002Fithome-2025-day-03","Day 3：Webhook 簽章驗證與訊息回覆策略(Push & Reply)","上一篇帶大家透過「Webhook 模式」成功架設了專屬的 LINE Bot 代理人。相信大家在體驗基礎功能後，對於 LINE Bot Webhook 還能監聽哪些事件、支援哪些類型的訊息回覆，以及如何確保後端收到的訊息確…","2025-09-16T21:53:39+08:00",[11,360,362,350],[11,362],5360,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10381303",{"name":366,"url":367,"day":318},{"path":642,"title":643,"description":644,"date":645,"updated":9,"tags":646,"categories":647,"draft":15,"wordCount":648,"readingTime":31,"canonical":649,"series":650},"\u002Fithome-2025-day-02","Day 2：從 Webhook 到後端，打造你的專屬機器人","上一篇，帶大家透過「Chat 模式」，讓自身變成客服機器人的方式。這篇會從「Webhook 模式」切入，並以 NestJS 作為後端框架，教你如何在休息時間，也能讓後端伺服器當你的替身幫你解惑使用者的問題。","2025-09-15T21:20:49+08:00",[11,360,362,350],[11,362],6590,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10380524",{"name":366,"url":367,"day":329},{"path":652,"title":653,"description":654,"date":655,"updated":9,"tags":656,"categories":657,"draft":15,"wordCount":658,"readingTime":318,"canonical":659,"series":660},"\u002Fithome-2025-day-01","Day 1：Hello World LINE Bot","每個程式語言的開始通常都會以練習 Hello World！作為一個簡單的起手式，LINE Bot 也不意外。這一系列會著重在 LINE Bot 的相關應用，帶大家用輕鬆的方式一起建立屬於自己的 Line Bot 聊天機器…","2025-09-14T22:48:33+08:00",[11,360,362,350],[11,362],2723,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10379895",{"name":366,"url":367,"day":340},{"path":662,"title":663,"description":664,"date":665,"updated":9,"tags":666,"categories":671,"draft":15,"wordCount":674,"readingTime":134,"canonical":9,"series":9},"\u002Fdbdiagram-tool","關聯式資料庫設計必備 - dbdiagram.io ERD 繪圖工具","還在煩惱如何設計關聯式資料表實體關聯圖嗎？ 使用 dbdiagram.io 加快你與同事之間的距離","2024-11-05T20:18:24+08:00",[667,668,669,670],"ERD","dbdiagram.io","DBML","資料庫設計",[672,673],"Database","開發工具",3982,{"path":676,"title":677,"description":678,"date":679,"updated":9,"tags":680,"categories":687,"draft":15,"wordCount":690,"readingTime":122,"canonical":9,"series":9},"\u002FPostgreSQL-1","前端勇士大闖六角後端體驗營 - 初探 PostgreSQL DML 語法","初步踏入後端的世界，了解何謂後端以及資料庫常見語法 DDL、DML。","2024-10-30T22:43:49+08:00",[681,682,683,684,685,686],"PostgreSQL","SQL","DML","DDL","資料庫","六角學院",[672,688,689],"後端實戰","學習心得",5220,{"path":692,"title":693,"description":694,"date":695,"updated":9,"tags":696,"categories":700,"draft":15,"wordCount":703,"readingTime":329,"canonical":9,"series":9},"\u002Fcss-flex-1","CSS flex 軸線對齊技巧 - 預設屬性","CSS flex 排版技巧你都了解了嗎？回歸學習初心的認識 flex 預設屬性","2024-10-24T20:29:08+08:00",[697,698,699],"Flexbox","前端排版","切版技巧",[701,702],"CSS","前端開發",1856,{"path":705,"title":706,"description":707,"date":708,"updated":9,"tags":709,"categories":712,"draft":15,"wordCount":714,"readingTime":329,"canonical":715,"series":716},"\u002Fithome-2024-day-30","Vue 3 用實作帶你看過核心概念 - Day 30：新手村的鐵人證書 - 完賽心得","花了整整半年左右的時間，每天下班都很用心的準備範例或是看書，這一段旅程對我來說真的很重要。擔心、害怕跟不安的心情一直充斥自己心中，擔心寫錯或是寫不好，想讓自己再多準備久一點再開始，所以拖到中秋連假才開始，想下定決心讓自己…","2024-10-13T12:42:25+08:00",[11,710,711],"2024 鐵人賽","Vue 3",[11,713],"Vue",1381,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10367206",{"name":717,"url":718,"day":22},"2024 iThome 鐵人賽：Vue 3 初學者：用實作帶你看過核心概念","https:\u002F\u002Fithelp.ithome.com.tw\u002Fusers\u002F20116554\u002Fironman\u002F7800",{"path":720,"title":721,"description":722,"date":723,"updated":9,"tags":724,"categories":727,"draft":15,"wordCount":728,"readingTime":134,"canonical":729,"series":730},"\u002Fithome-2024-day-29","Vue 3 用實作帶你看過核心概念 - Day 29：Composables(組合式函數)","Composables是 Vue 3 中的一個重要概念，它是利用 Vue 的 Composition API 來創建和管理可重用的有狀態邏輯的函數。Composables 允許我們將組件邏輯抽象成可重用的函數，使得代碼更…","2024-10-12T15:07:55+08:00",[11,710,711,725,726],"Options API","Composition API",[11,713],4233,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10366865",{"name":717,"url":718,"day":34},{"path":732,"title":733,"description":734,"date":735,"updated":9,"tags":736,"categories":738,"draft":15,"wordCount":739,"readingTime":134,"canonical":740,"series":741},"\u002Fithome-2024-day-28","Vue 3 用實作帶你看過核心概念 - Day 28：官方 Vue Router 的應用與技巧","路由設定方式，一般可以分成兩種：","2024-10-11T17:14:44+08:00",[11,710,711,725,737],"Vue Router",[11,713],4095,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10366520",{"name":717,"url":718,"day":45},{"path":743,"title":744,"description":745,"date":746,"updated":9,"tags":747,"categories":748,"draft":15,"wordCount":749,"readingTime":122,"canonical":750,"series":751},"\u002Fithome-2024-day-27","Vue 3 用實作帶你看過核心概念 - Day 27：VeeValidate 表單驗證工具","在開發 Vue 應用程式時，表單驗證至關重要，它能確保使用者輸入的資料符合預期的格式和要求。今天來介紹一款專門用於 Vue 的表單驗證工具—VeeValidate v4。這個工具不僅能幫助開發者輕鬆實現表單驗證，還提供了…","2024-10-10T21:02:16+08:00",[11,710,711,725],[11,713],4461,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10366165",{"name":717,"url":718,"day":56},{"path":753,"title":754,"description":755,"date":756,"updated":9,"tags":757,"categories":758,"draft":15,"wordCount":759,"readingTime":318,"canonical":760,"series":761},"\u002Fithome-2024-day-26","Vue 3 用實作帶你看過核心概念 - Day 26：KeepAlive 與 Teleport 內置組件","預設情況下，切換組件會導致組件的創建及銷毀，無法保持組件內部的狀態。","2024-10-09T18:50:53+08:00",[11,710,711,725],[11,713],3158,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10365724",{"name":717,"url":718,"day":67},{"path":763,"title":764,"description":765,"date":766,"updated":9,"tags":767,"categories":768,"draft":15,"wordCount":769,"readingTime":318,"canonical":770,"series":771},"\u002Fithome-2024-day-25","Vue 3 用實作帶你看過核心概念 - Day 25：自定義指令(Custom Directives)","Vue不僅提供了豐富的內置指令用於操作DOM元素，還允許開發者創建自定義指令。透過自定義指令，我們可以對DOM元素進行更細緻的控制，並在指令的不同生命週期階段執行特定的邏輯，從而實現更靈活的功能擴展。","2024-10-08T22:05:32+08:00",[11,710,711,725],[11,713],3116,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10365355",{"name":717,"url":718,"day":79},{"path":773,"title":774,"description":775,"date":776,"updated":9,"tags":777,"categories":778,"draft":15,"wordCount":779,"readingTime":329,"canonical":780,"series":781},"\u002Fithome-2024-day-24","Vue 3 用實作帶你看過核心概念 - Day 24：異步加載(Lazy loading)","在大型項目中，我們通常需要將應用拆分為更小的代碼模塊，並僅在需要時才從服務器加載相關組件，以減少初次加載的資源量。Vue 提供了 defineAsyncComponent 方法來實現組件的異步加載，這樣可以有效提高應用的…","2024-10-07T20:28:27+08:00",[11,710,711,725],[11,713],2171,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10364861",{"name":717,"url":718,"day":90},{"path":783,"title":784,"description":785,"date":786,"updated":9,"tags":787,"categories":788,"draft":15,"wordCount":789,"readingTime":318,"canonical":790,"series":791},"\u002Fithome-2024-day-23","Vue 3 用實作帶你看過核心概念 - Day 23：依賴注入( Provide-Inject )","在Dayxx中提到過，父子組件之間的數據傳遞可以通過props來實現。然而，當祖孫層組件需要進行數據傳遞時，中間層級的組件可能並不需要這個props，但卻不得不為了使子組件獲取數據而被迫傳遞。","2024-10-06T15:14:51+08:00",[11,710,711,725],[11,713],3183,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10364252",{"name":717,"url":718,"day":101},{"path":793,"title":794,"description":795,"date":796,"updated":9,"tags":797,"categories":798,"draft":15,"wordCount":799,"readingTime":134,"canonical":800,"series":801},"\u002Fithome-2024-day-22","Vue 3 用實作帶你看過核心概念 - Day 22：v-slot 插槽使用","先前Day 18中提到父組件可以通過props將參數資料傳遞給子組件進行渲染，這樣可以有效地將資料處理與畫面渲染的工作分開。然而，當我們需要更加客製化的呈現內容，由父組件來控制子組件的部分顯示時，可以使用v-slot 指…","2024-10-05T12:32:51+08:00",[11,710,711,725],[11,713],4292,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10363713",{"name":717,"url":718,"day":113},{"path":803,"title":804,"description":805,"date":806,"updated":9,"tags":807,"categories":808,"draft":15,"wordCount":809,"readingTime":329,"canonical":810,"series":811},"\u002Fithome-2024-day-21","Vue 3 用實作帶你看過核心概念 - Day 21： 組件透傳屬性(Attributes)的應用","當父組件向子組件傳遞屬性或監聽器，而這些屬性未在子組件中定義為props或emits時，它們會自動繼承並附加到子組件的根元素上，常見的屬性包括class、style、id等。這些屬性可以透過$attrs屬性訪問並進行操作…","2024-10-04T22:42:54+08:00",[11,710,711,725],[11,713],2146,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10363469",{"name":717,"url":718,"day":125},{"path":813,"title":814,"description":815,"date":816,"updated":9,"tags":817,"categories":818,"draft":15,"wordCount":819,"readingTime":122,"canonical":820,"series":821},"\u002Fithome-2024-day-20","Vue 3 用實作帶你看過核心概念 - Day 20：組件使用 v-model 雙向綁定","在Day 13中，我們介紹了表單元素（例如輸入框）如何處理數據雙向綁定。當需要將表單元素與一個響應式變數綁定時，v-model提供雙向綁定功能。這代表當畫面上表單元素的變動會即時影響Vue數據，同時當Vue數據的值改變時…","2024-10-03T23:40:48+08:00",[11,710,711,725],[11,713],5191,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10362957",{"name":717,"url":718,"day":137},{"path":823,"title":824,"description":825,"date":826,"updated":9,"tags":827,"categories":828,"draft":15,"wordCount":829,"readingTime":318,"canonical":830,"series":831},"\u002Fithome-2024-day-19","Vue 3 用實作帶你看過核心概念 - Day 19：子組件向父組件發射事件 - emits","組件可以通過$emit(functionName, params)自定義事件名稱並傳遞參數。自定義事件名稱建議使用kebab-case來命名自定義事件名稱，以確保命名風格與HTML 屬性一致性。此外，自定義事件還支持事件…","2024-10-02T15:51:16+08:00",[11,710,711,725],[11,713],2877,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10362144",{"name":717,"url":718,"day":148},{"path":833,"title":834,"description":835,"date":836,"updated":9,"tags":837,"categories":838,"draft":15,"wordCount":839,"readingTime":31,"canonical":840,"series":841},"\u002Fithome-2024-day-18","Vue 3 用實作帶你看過核心概念 - Day 18：父組件向子組件傳值 - props","組件之間的傳值必須透過聲明 props 的方式，這樣可以避免與HTML的屬性(attribute)混淆。父組件傳遞參數給子組件的方式有以下兩種方式：","2024-10-01T22:28:48+08:00",[11,710,711,725],[11,713],5782,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10361721",{"name":717,"url":718,"day":159},{"path":843,"title":844,"description":845,"date":846,"updated":9,"tags":847,"categories":848,"draft":15,"wordCount":849,"readingTime":318,"canonical":850,"series":851},"\u002Fithome-2024-day-17","Vue 3 用實作帶你看過核心概念 - Day 17：組件基礎 - 全局註冊與區域註冊","在 Day 5 我們提到可以將應用拆分為根組件和多個組件實例，並將功能模塊化。","2024-09-30T23:30:10+08:00",[11,710,711,725],[11,713],2954,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10361253",{"name":717,"url":718,"day":170},{"path":853,"title":854,"description":855,"date":856,"updated":9,"tags":857,"categories":858,"draft":15,"wordCount":859,"readingTime":122,"canonical":860,"series":861},"\u002Fithome-2024-day-16","Vue 3 用實作帶你看過核心概念 - Day 16：使用 ref 屬性引用模板元素","雖然 Vue 透過模板幫助我們處理了大部分的DOM 操作，但在某些情況下，仍然需要手動操作 DOM。例如，在使用第三方套件（如 Bootstrap 的 Modal）時，或者需要調用像video.play()和video.…","2024-09-29T16:25:45+08:00",[11,710,711,725],[11,713],4608,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10360419",{"name":717,"url":718,"day":181},{"path":863,"title":864,"description":865,"date":866,"updated":9,"tags":867,"categories":868,"draft":15,"wordCount":488,"readingTime":122,"canonical":869,"series":870},"\u002Fithome-2024-day-15","Vue 3 用實作帶你看過核心概念 - Day 15：監聽器(Watchers)","在響應式狀態變化時執行特定操作，需要使用watch 監聽器。這些操作可能包含副作用 (side effects)，如發送請求、調用 API，或更新 DOM 以外的系統狀態，亦或是處理自定義的邏輯。","2024-09-28T18:30:31+08:00",[11,710,711,725],[11,713],"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10359958",{"name":717,"url":718,"day":192},{"path":872,"title":873,"description":874,"date":875,"updated":9,"tags":876,"categories":877,"draft":15,"wordCount":878,"readingTime":134,"canonical":879,"series":880},"\u002Fithome-2024-day-14","Vue 3 用實作帶你看過核心概念 - Day 14：生命週期鉤子(Lifecycle Hooks)","在 Vue 中，當一個組件創建時，它會經歷一系列的流程，這些流程決定了組件從初始化到渲染，再到最終銷毀的過程。","2024-09-27T21:57:32+08:00",[11,710,711,725],[11,713],3780,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10359419",{"name":717,"url":718,"day":203},{"path":882,"title":883,"description":884,"date":885,"updated":9,"tags":886,"categories":887,"draft":15,"wordCount":888,"readingTime":318,"canonical":889,"series":890},"\u002Fithome-2024-day-13","Vue 3 用實作帶你看過核心概念 - Day 13：v-model 雙向綁定控制 - 常用於表單輸入","表單輸入是開發中非常常見的需求，原始方式通常需要手動使用v-bind綁定表單元素的值 (value)，並透過v-on綁定input事件來監聽輸入變化。","2024-09-26T21:49:25+08:00",[11,710,711,725],[11,713],3153,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10358850",{"name":717,"url":718,"day":214},{"path":892,"title":893,"description":894,"date":895,"updated":9,"tags":896,"categories":897,"draft":15,"wordCount":898,"readingTime":134,"canonical":899,"series":900},"\u002Fithome-2024-day-12","Vue 3 用實作帶你看過核心概念 - Day 12：v-on 指令 - 事件處理","在 Vue 中，監聽 HTML DOM 元素的事件變化，可以使用v-on 指令將 JavaScript 事件處理器綁定到對應的DOM 事件上。這個指令的縮寫符號為@，例如：v-on:click，其縮寫方式為@click。","2024-09-25T21:42:59+08:00",[11,710,711,725],[11,713],3808,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10358241",{"name":717,"url":718,"day":225},{"path":902,"title":903,"description":904,"date":905,"updated":9,"tags":906,"categories":907,"draft":15,"wordCount":908,"readingTime":134,"canonical":909,"series":910},"\u002Fithome-2024-day-11","Vue 3 用實作帶你看過核心概念 - Day 11：v-for 指令的基本與進階應用","當數據類型是陣列或物件時，我們不會希望將重複的選項或元素直接硬編碼在模板中。這樣的寫法會導致代碼冗長且不具可維護性。","2024-09-24T23:11:25+08:00",[11,710,711,725],[11,713],4381,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10357705",{"name":717,"url":718,"day":236},{"path":912,"title":913,"description":914,"date":915,"updated":9,"tags":916,"categories":917,"draft":15,"wordCount":918,"readingTime":318,"canonical":919,"series":920},"\u002Fithome-2024-day-10","Vue 3 用實作帶你看過核心概念 - Day 10：條件渲染 - v-if 與 v-show 的區別與應用","開發中遇到需要處理【如果是...就要...】的情境時，Vue 提供了 v-if 指令來幫助我們根據條件進行元素的渲染。這樣可以在特定條件滿足時動態地顯示或隱藏某些元素。","2024-09-23T23:39:24+08:00",[11,710,711,725],[11,713],2827,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10357160",{"name":717,"url":718,"day":247},{"path":922,"title":923,"description":924,"date":925,"updated":9,"tags":926,"categories":927,"draft":15,"wordCount":928,"readingTime":122,"canonical":929,"series":930},"\u002Fithome-2024-day-09","Vue 3 用實作帶你看過核心概念 - Day 9：Class 與 Style 的樣式綁定","v-bind 指令通常用於綁定 HTML 屬性，但在實際開發中，最常見的應用場景之一還是綁定class和 style這兩個 HTML 屬性。","2024-09-22T15:05:53+08:00",[11,710,711,725],[11,713],4630,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10356119",{"name":717,"url":718,"day":76},{"path":932,"title":933,"description":934,"date":935,"updated":9,"tags":936,"categories":937,"draft":15,"wordCount":938,"readingTime":134,"canonical":939,"series":940},"\u002Fithome-2024-day-08","Vue 3 用實作帶你看過核心概念 - Day 8：計算屬性應用與實踐","在 Day 6 在使用 Vue 的Mustache語法時，可以用來放置表達式。不過，這邊建議避免在 Mustache 中撰寫過於複雜的邏輯。這樣的建議主要有兩個原因：","2024-09-21T21:33:29+08:00",[11,710,711,725],[11,713],4060,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10355474",{"name":717,"url":718,"day":110},{"path":942,"title":943,"description":944,"date":945,"updated":9,"tags":946,"categories":947,"draft":15,"wordCount":948,"readingTime":122,"canonical":949,"series":950},"\u002Fithome-2024-day-07","Vue 3 用實作帶你看過核心概念 - Day 7： 響應式基礎 - Options API","前面提到了模板搭配指令及 Mustache 的用法。今天則是要介紹所謂透過getter跟setter取值跟賦值的方式在 JavaScript 是怎麼做到的，這部分會跟 Vue 本身的響應式基礎有很大相關。此外，我也會帶著…","2024-09-20T23:41:42+08:00",[11,710,711],[11,713],4407,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10354781",{"name":717,"url":718,"day":17},{"path":952,"title":953,"description":954,"date":955,"updated":9,"tags":956,"categories":957,"draft":15,"wordCount":958,"readingTime":134,"canonical":959,"series":960},"\u002Fithome-2024-day-06","Vue 3 用實作帶你看過核心概念 - Day 6：數據綁定和模板(Template)","Vue 使用基於 HTML 的模板語法（Template Syntax），將 Vue 實例中的數據綁定到模板中進行顯示。根據綁定的類型不同，數據可以影響元素的內容、屬性或樣式。","2024-09-19T20:39:46+08:00",[11,710,711,725],[11,713],3402,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10354231",{"name":717,"url":718,"day":31},{"path":962,"title":963,"description":964,"date":965,"updated":9,"tags":966,"categories":967,"draft":15,"wordCount":968,"readingTime":318,"canonical":969,"series":970},"\u002Fithome-2024-day-05","Vue 3 用實作帶你看過核心概念 - Day 5：Options API vs Composition API","前面已經詳細說明了 Vue 的環境建置方式，接下來將逐步介紹 Vue 應用說明，並比較Options API與Composition API的撰寫風格。","2024-09-18T22:10:36+08:00",[11,710,711,725,726],[11,713],2902,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10353717",{"name":717,"url":718,"day":122},{"path":972,"title":973,"description":974,"date":975,"updated":9,"tags":976,"categories":977,"draft":15,"wordCount":658,"readingTime":318,"canonical":978,"series":979},"\u002Fithome-2024-day-04","Vue 3 用實作帶你看過核心概念 - Day 4：基於 Vite 建構工具的 Vue 專案結構解析","在 Day 3 的教學中，學習了如何使用 Vue 鷹架工具(Vue project scaffolding tool)來生成一個基於 Vite 環境的專案。今天，我將更進一步地解析這個專案的資料夾結構，幫助大家更好地理解…","2024-09-17T23:27:07+08:00",[11,710,711,725],[11,713],"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10352470",{"name":717,"url":718,"day":134},{"path":981,"title":982,"description":983,"date":984,"updated":9,"tags":985,"categories":986,"draft":15,"wordCount":987,"readingTime":329,"canonical":988,"series":989},"\u002Fithome-2024-day-03","Vue 3 用實作帶你看過核心概念 - Day 3：使用 Vite 建構工具搭建 Vue 專案","⭐ 需要特別注意，需要事先安裝Nodejs。若不確定是否已安裝 Nodejs 也可以開啟終端機，執行以下指令確認版本。","2024-09-16T23:29:45+08:00",[11,710,711,725],[11,713],2100,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10351398",{"name":717,"url":718,"day":318},{"path":991,"title":992,"description":993,"date":994,"updated":9,"tags":995,"categories":996,"draft":15,"wordCount":997,"readingTime":329,"canonical":998,"series":999},"\u002Fithome-2024-day-02","Vue 3 用實作帶你看過核心概念 - Day 2：命令式編程 vs 聲明式編程","還記得我們在使用純 HTML 和 JavaScript 時，如何實現按下按鈕來變更文字顏色嗎？讓我們一起回想一下什麼是命令式宣告。","2024-09-15T22:52:27+08:00",[11,710,711,725,726],[11,713],1881,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10350459",{"name":717,"url":718,"day":329},{"path":1001,"title":1002,"description":1003,"date":1004,"updated":9,"tags":1005,"categories":1006,"draft":15,"wordCount":1007,"readingTime":340,"canonical":1008,"series":1009},"\u002Fithome-2024-day-01","Vue 3 用實作帶你看過核心概念 - Day 1：前言介紹","大家好，我是 Antonio(安東尼奧)，目前是一名 Angular 的新手工程師，同時，也是一名熱愛寫程式的工程師。去年參加六角學院的 Vue 直播班，在那時候就深深著迷著 Vue 的語言，自此這半年多的時間裡，我白天…","2024-09-14T17:32:19+08:00",[11,710,711],[11,713],988,"https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10350457",{"name":717,"url":718,"day":340},{"path":1011,"title":1012,"description":1013,"date":1014,"updated":9,"tags":1015,"categories":1017,"draft":15,"wordCount":1019,"readingTime":329,"canonical":9,"series":9},"\u002Fhexschool-experience","六角學院 - 軟體工程師體驗營","這麼多線上課程? 你不想知道什麼是最吸引我的線上學習課程嗎?","2024-05-31T21:40:05+08:00",[686,1016],"軟體工程師體驗營",[689,1018],"前端成長記",1109,{"path":1021,"title":1022,"description":1023,"date":1024,"updated":9,"tags":1025,"categories":1033,"draft":15,"wordCount":1035,"readingTime":318,"canonical":9,"series":9},"\u002FJS-10","JavaScript：var、let、const之間的差異解析","var、let及const是JavaScript中宣告變數的關鍵字，它們在作用域、對於for迴圈的影響、提升 (Hoisting) 的差異及重複宣告的處理上有所不同。","2023-12-10T23:53:30+08:00",[1026,1027,1028,1029,1030,1031,1032],"ES6","var","let","const","Hoisting","Scope","TDZ",[1034,702],"JavaScript",2873,{"path":1037,"title":1038,"description":1039,"date":1040,"updated":9,"tags":1041,"categories":1048,"draft":15,"wordCount":1049,"readingTime":122,"canonical":9,"series":9},"\u002FJS-9","JavaScript：陣列的常見操作方法","掌握 JavaScript 陣列操作！從forEach、map、filter、findIndex、reduce、sort，深入了解這些方法，使你的程式碼更具靈活性和效率！","2023-12-01T15:01:06+08:00",[1042,1043,1044,1045,1046,1047],"forEach","map","filter","reduce","sort","findIndex",[1034,702],4846,{"path":1051,"title":1052,"description":1053,"date":1054,"updated":9,"tags":1055,"categories":1060,"draft":15,"wordCount":1061,"readingTime":318,"canonical":9,"series":9},"\u002FJS-8","JavaScript：ES module 匯入與匯出","使用\u003C script >標籤讓瀏覽器中的網頁能夠使用 ES 模組功能時，你了解不同的匯入及匯出方法了嗎？","2023-11-30T15:28:23+08:00",[1026,1056,1057,1058,1059],"ES Module","CommonJS","Node.js","模組化開發",[1034,702],2913,{"path":1063,"title":1064,"description":1065,"date":1066,"updated":9,"tags":1067,"categories":1070,"draft":15,"wordCount":1072,"readingTime":134,"canonical":9,"series":9},"\u002FReact-2","React：JSX 是什麼？為何在 React 中使用 JSX？","透過 JSX 語法糖，你能夠在一次 JavaScript 撰寫中包含 HTML 與 CSS 的內容","2023-11-29T16:03:40+08:00",[1068,1034,1069],"JSX","Babel",[1071,702],"React",3595,{"path":1074,"title":1075,"description":1076,"date":1077,"updated":9,"tags":1078,"categories":1081,"draft":15,"wordCount":1082,"readingTime":329,"canonical":9,"series":9},"\u002FReact-1","React：Pure Function 的概念及其在 React 中的應用","探索 Pure Function 概念及其與 React 的相互關係。","2023-11-29T15:50:17+08:00",[1034,1079,1080],"Pure Function","Functional Programming",[1071],1368,{"path":1084,"title":1085,"description":1086,"date":1087,"updated":9,"tags":1088,"categories":1093,"draft":15,"wordCount":1094,"readingTime":122,"canonical":9,"series":9},"\u002FJS-6","JavaScript：深入理解Promise的原理及實際應用","透過Promise，我們能夠有效解決JavaScript中的異步事件，使得程式碼更為清晰和可讀。","2023-11-29T14:49:18+08:00",[1089,1090,1091,1092],"Promise","AsyncAwait","Asynchronous Programming","異步處理",[1034,702],5479,{"path":1096,"title":1097,"description":1098,"date":1099,"updated":9,"tags":1100,"categories":1105,"draft":15,"wordCount":1106,"readingTime":122,"canonical":9,"series":9},"\u002FJS-5","JavaScript：物件傳參考特性(Pass by Reference)","淺拷貝(shallow copy)與深拷貝(deep copy)在JavaScript中的應用與理解","2023-11-29T09:55:50+08:00",[1101,1102,1103,1104],"Pass by Reference","Shallow Copy","Deep Copy","傳值與傳參考",[1034,702],4544,{"path":1108,"title":1109,"description":1110,"date":1111,"updated":9,"tags":1112,"categories":1118,"draft":15,"wordCount":1120,"readingTime":329,"canonical":9,"series":9},"\u002FJS-4","JavaScript：注重關注點的分離","透過關注點分離的設計方式，可顯著提高系統整體的可維護性。","2023-11-29T09:44:29+08:00",[1113,1114,1115,1116,1117],"SoC","MVC","Design Patterns","Clean Code","Refactoring",[1034,1119],"Software Engineering",1977,{"path":1122,"title":1123,"description":1124,"date":1125,"updated":9,"tags":1126,"categories":1132,"draft":15,"wordCount":1133,"readingTime":329,"canonical":9,"series":9},"\u002FJS-3","JavaScript：掌握箭頭函式，優雅簡約的程式寫作","深入解析ES6箭頭函數：揭開與傳統函式的差異。","2023-11-29T01:02:36+08:00",[1127,1128,1129,1130,1131],"Arrow Function","this","Lexical Scoping","Syntactic Sugar","Callback Function",[1034,702],2142,{"path":1135,"title":1136,"description":1137,"date":1138,"updated":9,"tags":1139,"categories":1143,"draft":15,"wordCount":1144,"readingTime":329,"canonical":9,"series":9},"\u002FJS-2","JavaScript：深入了解This的指向與應用","探索JavaScript This 的指向：深入剖析判斷的技巧。","2023-11-28T22:22:45+08:00",[1128,1140,1131,1141,1142],"Execution Context","Binding","Fundamentals",[1034,702],1963,{"path":1146,"title":1147,"description":1148,"date":1149,"updated":9,"tags":1150,"categories":1154,"draft":15,"wordCount":1155,"readingTime":340,"canonical":9,"series":9},"\u002FJS-1","JavaScript：淺談ES6常見縮寫","JavaScript ES6縮寫技巧：輕鬆簡化程式碼，提升效率！。","2023-11-28T13:38:14+08:00",[1026,1151,1152,1153],"Shorthand","Spread Operator","Object",[1034,702],818,{"path":1157,"title":1158,"description":1159,"date":1160,"updated":9,"tags":1161,"categories":1165,"draft":15,"wordCount":1166,"readingTime":340,"canonical":9,"series":9},"\u002FEmmet-1","前端開發神器：使用Emmet提升網頁開發效率","本文將介紹如何利用Emmet來大幅提高前端開發效率，讓你的編碼速度如專家般飛快。","2023-10-31T14:40:54+08:00",[1162,1163,1164],"Emmet","VSCode","HTML",[702,673],865,{"path":1168,"title":1169,"description":1170,"date":1171,"updated":9,"tags":1172,"categories":1177,"draft":15,"wordCount":1179,"readingTime":340,"canonical":9,"series":9},"\u002Fhexo-github-4","建立自己的部落格：了解Hexo指令，更換next部落格主題","今天的你跟我都是Hexo指令指揮官，讓我們將部落格造型大改造一下吧!!!","2023-10-20T14:33:38+08:00",[1173,1174,1175,1176],"Hexo","NexT","git clone","Hexo指令",[1178],"Blog",979,{"path":1181,"title":1182,"description":1183,"date":1184,"updated":9,"tags":1185,"categories":1189,"draft":15,"wordCount":1190,"readingTime":329,"canonical":9,"series":9},"\u002Fhexo-github-3","建立自己的部落格：修改Hexo設定檔中Site，查看其變化","今天的你跟我都是部落格工程師，我們一起來將網頁做一些小小的改變，有一天匯集在一起就會讓你的部落格變的與眾不同。","2023-10-18T20:50:31+08:00",[1173,1163,1186,1187,1188],"Sublime Text","YAML","SEO",[1178],1798,{"path":1192,"title":1193,"description":1194,"date":1195,"updated":9,"tags":1196,"categories":1199,"draft":15,"wordCount":1200,"readingTime":340,"canonical":9,"series":9},"\u002Fhexo-github-2","建立自己的部落格：創建Hexo Blog初始的模板","踏出那關鍵的第一步，從白紙到完整的部落格，一同見證你的部落格誕生的奇妙時刻。","2023-10-17T15:59:37+08:00",[1173,1197,1198],"Hexo-cli","hexo init",[1178],941,{"path":1202,"title":1203,"description":1204,"date":1205,"updated":9,"tags":1206,"categories":1208,"draft":15,"wordCount":1209,"readingTime":340,"canonical":9,"series":9},"\u002Fhexo-github-1","建立自己的部落格：認識Hexo及所其需工具(Nodejs & Git)","打造屬於自己風格的部落格其實不難，讓我們一步步手把手教你如何實現這個目標。","2023-10-16T08:30:27+08:00",[1173,1058,1207],"Git",[1178],790,{"id":1211,"title":794,"body":1212,"canonical":800,"categories":4060,"date":796,"description":795,"draft":15,"extension":4061,"meta":4062,"navigation":2034,"ogImage":9,"path":793,"rawbody":4063,"readingTime":134,"robots":9,"schemaOrg":9,"seo":4064,"series":4065,"sitemap":4066,"slug":4076,"stem":4077,"tags":4078,"updated":9,"wordCount":799,"__hash__":4079},"posts\u002F2024-10-05-ithome-2024-day-22.md",{"type":1213,"value":1214,"toc":4048},"minimark",[1215,1223,1227,1255,1258,1262,1285,1291,1298,1306,1309,1325,1328,1414,1417,1494,1497,1531,1544,1559,1562,1581,1588,1615,1621,1624,1631,1633,1660,1662,1821,1824,1976,1978,1991,1994,2001,2003,2187,2189,2415,2429,2432,2442,2445,2457,2463,2470,2472,2576,2586,2588,2643,2661,2668,2670,2869,2871,3040,3056,3063,3066,3075,3084,3093,3113,3126,3147,3160,3163,3220,3236,3239,3258,3265,3267,3335,3337,3468,3470,3478,3481,3497,3504,3506,3783,3785,3930,3932,3985,3987,3995,4006,4008,4030,4044],[1216,1217,1218],"p",{},[1219,1220],"img",{"alt":1221,"src":1222},"文章背景圖","https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728100231\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002FDay22_v-slot_%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8_i3a0ig.png",[1224,1225,1226],"h2",{"id":1226},"目錄",[1228,1229,1230,1234,1237,1240,1243,1246,1249,1252],"ul",{},[1231,1232,1233],"li",{},"slot 默認內容插槽",[1231,1235,1236],{},"slot 具名插槽",[1231,1238,1239],{},"子組件插槽傳遞參數 - 作用域插槽",[1231,1241,1242],{},"slot 與 props 設計方式比較 - 以切換卡片展示型態為例",[1231,1244,1245],{},"條件插槽 - $slots",[1231,1247,1248],{},"動態插槽",[1231,1250,1251],{},"總結",[1231,1253,1254],{},"小試身手",[1256,1257],"hr",{},[1259,1260,1233],"h3",{"id":1261},"slot-默認內容插槽",[1216,1263,1264,1265,1271,1272,1276,1277,1280,1281,1284],{},"先前",[1266,1267,1270],"a",{"href":840,"rel":1268},[1269],"nofollow","Day 18","中提到父組件可以通過",[1273,1274,1275],"code",{},"props","將參數資料傳遞給子組件進行渲染，這樣可以有效地將資料處理與畫面渲染的工作分開。然而，當我們需要更加客製化的呈現內容，由父組件來控制子組件的部分顯示時，可以使用",[1273,1278,1279],{},"v-slot 指令","，將父組件的",[1273,1282,1283],{},"模板","傳入給子組件，可以更靈活地呈現內容。",[1216,1286,1287],{},[1219,1288],{"alt":1289,"src":1290},"v-slot 指令基本應用區域官方範例圖","https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728100366\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002Fv-slot_%E6%8C%87%E4%BB%A4%E5%9F%BA%E6%9C%AC%E6%87%89%E7%94%A8%E5%8D%80%E5%9F%9F_cyylfp.png",[1216,1292,1293,1294,1297],{},"以下透過一個父組件傳入",[1273,1295,1296],{},"按鈕模板內容","給子組件的案例進行說明：",[1216,1299,1300,1301],{},"👉 ",[1266,1302,1305],{"href":1303,"rel":1304},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FQWebeLj",[1269],"Vue3 Options API slot 默認插槽內容實作連結",[1216,1307,1308],{},"流程說明：",[1310,1311,1312,1315,1318],"ol",{},[1231,1313,1314],{},"父組件區域註冊子組件。",[1231,1316,1317],{},"在子組件使用的標籤內放入父組件要傳入的模板內容。",[1231,1319,1320,1321,1324],{},"子組件使用",[1273,1322,1323],{},"slot","標籤接應父組件要傳入的模板內容。",[1216,1326,1327],{},"父組件 Vue Template：",[1329,1330,1335],"pre",{"className":1331,"code":1332,"language":1333,"meta":1334,"style":1334},"language-html shiki shiki-themes github-light github-dark-dimmed","\u003Cdiv id=\"app\">\n  \u003Cfancy-button>\n    \u003Cbutton type=\"button\">{{ icon }} {{ buttonText }}\u003C\u002Fbutton>\n  \u003C\u002Ffancy-button>\n\u003C\u002Fdiv>\n","html","",[1273,1336,1337,1363,1373,1396,1405],{"__ignoreMap":1334},[1338,1339,1341,1345,1349,1353,1356,1360],"span",{"class":1340,"line":340},"line",[1338,1342,1344],{"class":1343},"sYgZi","\u003C",[1338,1346,1348],{"class":1347},"sIAta","div",[1338,1350,1352],{"class":1351},"sMOND"," id",[1338,1354,1355],{"class":1343},"=",[1338,1357,1359],{"class":1358},"s-HuK","\"app\"",[1338,1361,1362],{"class":1343},">\n",[1338,1364,1365,1368,1371],{"class":1340,"line":329},[1338,1366,1367],{"class":1343},"  \u003C",[1338,1369,1370],{"class":1347},"fancy-button",[1338,1372,1362],{"class":1343},[1338,1374,1375,1378,1381,1384,1386,1389,1392,1394],{"class":1340,"line":318},[1338,1376,1377],{"class":1343},"    \u003C",[1338,1379,1380],{"class":1347},"button",[1338,1382,1383],{"class":1351}," type",[1338,1385,1355],{"class":1343},[1338,1387,1388],{"class":1358},"\"button\"",[1338,1390,1391],{"class":1343},">{{ icon }} {{ buttonText }}\u003C\u002F",[1338,1393,1380],{"class":1347},[1338,1395,1362],{"class":1343},[1338,1397,1398,1401,1403],{"class":1340,"line":134},[1338,1399,1400],{"class":1343},"  \u003C\u002F",[1338,1402,1370],{"class":1347},[1338,1404,1362],{"class":1343},[1338,1406,1407,1410,1412],{"class":1340,"line":122},[1338,1408,1409],{"class":1343},"\u003C\u002F",[1338,1411,1348],{"class":1347},[1338,1413,1362],{"class":1343},[1216,1415,1416],{},"父組件 javascript：",[1329,1418,1422],{"className":1419,"code":1420,"language":1421,"meta":1334,"style":1334},"language-javascript shiki shiki-themes github-light github-dark-dimmed","const rootComponent = {\n  data() {\n    return {\n      buttonText: \"我是按鈕\",\n      icon: \"🐱\"\n    };\n  },\n  components: { FancyButton }\n};\n","javascript",[1273,1423,1424,1439,1448,1455,1466,1474,1479,1484,1489],{"__ignoreMap":1334},[1338,1425,1426,1429,1433,1436],{"class":1340,"line":340},[1338,1427,1029],{"class":1428},"s7YZ4",[1338,1430,1432],{"class":1431},"sviXB"," rootComponent",[1338,1434,1435],{"class":1428}," =",[1338,1437,1438],{"class":1343}," {\n",[1338,1440,1441,1445],{"class":1340,"line":329},[1338,1442,1444],{"class":1443},"sPO5f","  data",[1338,1446,1447],{"class":1343},"() {\n",[1338,1449,1450,1453],{"class":1340,"line":318},[1338,1451,1452],{"class":1428},"    return",[1338,1454,1438],{"class":1343},[1338,1456,1457,1460,1463],{"class":1340,"line":134},[1338,1458,1459],{"class":1343},"      buttonText: ",[1338,1461,1462],{"class":1358},"\"我是按鈕\"",[1338,1464,1465],{"class":1343},",\n",[1338,1467,1468,1471],{"class":1340,"line":122},[1338,1469,1470],{"class":1343},"      icon: ",[1338,1472,1473],{"class":1358},"\"🐱\"\n",[1338,1475,1476],{"class":1340,"line":31},[1338,1477,1478],{"class":1343},"    };\n",[1338,1480,1481],{"class":1340,"line":17},[1338,1482,1483],{"class":1343},"  },\n",[1338,1485,1486],{"class":1340,"line":110},[1338,1487,1488],{"class":1343},"  components: { FancyButton }\n",[1338,1490,1491],{"class":1340,"line":76},[1338,1492,1493],{"class":1343},"};\n",[1216,1495,1496],{},"子組件 Vue Template：",[1329,1498,1500],{"className":1331,"code":1499,"language":1333,"meta":1334,"style":1334},"\u003Cslot>\n  \u003Cp>目前暫時不服務！\u003C\u002Fp>\n\u003C\u002Fslot>\n",[1273,1501,1502,1510,1523],{"__ignoreMap":1334},[1338,1503,1504,1506,1508],{"class":1340,"line":340},[1338,1505,1344],{"class":1343},[1338,1507,1323],{"class":1347},[1338,1509,1362],{"class":1343},[1338,1511,1512,1514,1516,1519,1521],{"class":1340,"line":329},[1338,1513,1367],{"class":1343},[1338,1515,1216],{"class":1347},[1338,1517,1518],{"class":1343},">目前暫時不服務！\u003C\u002F",[1338,1520,1216],{"class":1347},[1338,1522,1362],{"class":1343},[1338,1524,1525,1527,1529],{"class":1340,"line":318},[1338,1526,1409],{"class":1343},[1338,1528,1323],{"class":1347},[1338,1530,1362],{"class":1343},[1216,1532,1533,1534,1536,1537,1540,1541,1543],{},"⭐ 子組件的",[1273,1535,1323],{},"標籤裡面可以放置預設值，當父組件未傳入模板內容的時候就會套用",[1273,1538,1539],{},"\u003Cp>目前暫時不服務！\u003C\u002Fp>","。若父組件有傳入模板內容，則會忽略",[1273,1542,1323],{},"標籤裡面的內容。",[1216,1545,1546,1547,1549,1550,1553,1554],{},"這邊附上父組件透過",[1273,1548,1275],{},"傳入資料，子組件根據資料渲染的案例，讓大家感受一下兩者架構的差異，也可以思考一下再擴增功能上的方向。",[1551,1552],"br",{},"\n👉 ",[1266,1555,1558],{"href":1556,"rel":1557},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FJjgdqBd",[1269],"Vue3 Options API 父組件傳遞 props 資料給子組件實作連結",[1259,1560,1236],{"id":1561},"slot-具名插槽",[1216,1563,1564,1565,1567,1568,1570,1571,1574,1575,1577,1578,1580],{},"子組件使用的",[1273,1566,1323],{},"標籤可以設定不只一個，當使用複數個",[1273,1569,1323],{},"標籤的時候，父組件需要搭配具名插槽加上",[1273,1572,1573],{},"template","標籤使用，才可以明確配對子組件中每個",[1273,1576,1323],{},"標籤要寫入對應的",[1273,1579,1573],{},"是哪一個。",[1216,1582,1583,1584,1587],{},"在說明",[1273,1585,1586],{},"v-slot","縮寫之前，幫大家複習一下之前常用指令的縮寫：",[1228,1589,1590,1600,1608],{},[1231,1591,1592,1596,1597],{},[1593,1594,1595],"strong",{},"v-bind","：縮寫型態",[1273,1598,1599],{},":",[1231,1601,1602,1596,1605],{},[1593,1603,1604],{},"v-on",[1273,1606,1607],{},"@",[1231,1609,1610,1596,1612],{},[1593,1611,1586],{},[1273,1613,1614],{},"#",[1216,1616,1617],{},[1219,1618],{"alt":1619,"src":1620},"slot 具名插槽對應模板名稱官方範例圖","https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728100929\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002FSlot_%E5%85%B7%E5%90%8D%E6%8F%92%E6%A7%BD%E5%AE%98%E6%96%B9%E7%AF%84%E4%BE%8B%E5%9C%96_mm8ej2.png",[1216,1622,1623],{},"以下透過子組件制定網頁版型，並由父組件根據不同區塊傳入模板內容案例說明：",[1216,1625,1300,1626],{},[1266,1627,1630],{"href":1628,"rel":1629},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FKKOdPBG",[1269],"Vue3 Options API slot 具名插槽實作連結",[1216,1632,1308],{},[1310,1634,1635,1650,1653],{},[1231,1636,1637,1638,1641,1642,1645,1646,1649],{},"子組件定出版型架構",[1273,1639,1640],{},"header","、",[1273,1643,1644],{},"main","及",[1273,1647,1648],{},"footer","標籤區域。",[1231,1651,1652],{},"父組件根據不同區域將對應該顯示的模板內容傳入。",[1231,1654,1655,1656,1659],{},"透過",[1273,1657,1658],{},"template name","與具名插槽名稱的對應，使彼此內容互不影響。",[1216,1661,1327],{},[1329,1663,1665],{"className":1331,"code":1664,"language":1333,"meta":1334,"style":1334},"\u003Cdiv id=\"app\">\n  \u003Cbase-layout>\n      \n    \u003Ctemplate v-slot:header>\n      \u003Ch2>這是 header\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n      \n    \u003Ctemplate #main>\n      \u003Ch2>這是 main\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n      \n    \u003Ctemplate #footer>\n      \u003Ch2>這是 footer\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n      \n  \u003C\u002Fbase-layout>\n\u003C\u002Fdiv>\n",[1273,1666,1667,1681,1690,1695,1706,1720,1729,1733,1744,1757,1765,1769,1780,1793,1801,1805,1813],{"__ignoreMap":1334},[1338,1668,1669,1671,1673,1675,1677,1679],{"class":1340,"line":340},[1338,1670,1344],{"class":1343},[1338,1672,1348],{"class":1347},[1338,1674,1352],{"class":1351},[1338,1676,1355],{"class":1343},[1338,1678,1359],{"class":1358},[1338,1680,1362],{"class":1343},[1338,1682,1683,1685,1688],{"class":1340,"line":329},[1338,1684,1367],{"class":1343},[1338,1686,1687],{"class":1347},"base-layout",[1338,1689,1362],{"class":1343},[1338,1691,1692],{"class":1340,"line":318},[1338,1693,1694],{"class":1343},"      \n",[1338,1696,1697,1699,1701,1704],{"class":1340,"line":134},[1338,1698,1377],{"class":1343},[1338,1700,1573],{"class":1347},[1338,1702,1703],{"class":1351}," v-slot:header",[1338,1705,1362],{"class":1343},[1338,1707,1708,1711,1713,1716,1718],{"class":1340,"line":122},[1338,1709,1710],{"class":1343},"      \u003C",[1338,1712,1224],{"class":1347},[1338,1714,1715],{"class":1343},">這是 header\u003C\u002F",[1338,1717,1224],{"class":1347},[1338,1719,1362],{"class":1343},[1338,1721,1722,1725,1727],{"class":1340,"line":31},[1338,1723,1724],{"class":1343},"    \u003C\u002F",[1338,1726,1573],{"class":1347},[1338,1728,1362],{"class":1343},[1338,1730,1731],{"class":1340,"line":17},[1338,1732,1694],{"class":1343},[1338,1734,1735,1737,1739,1742],{"class":1340,"line":110},[1338,1736,1377],{"class":1343},[1338,1738,1573],{"class":1347},[1338,1740,1741],{"class":1351}," #main",[1338,1743,1362],{"class":1343},[1338,1745,1746,1748,1750,1753,1755],{"class":1340,"line":76},[1338,1747,1710],{"class":1343},[1338,1749,1224],{"class":1347},[1338,1751,1752],{"class":1343},">這是 main\u003C\u002F",[1338,1754,1224],{"class":1347},[1338,1756,1362],{"class":1343},[1338,1758,1759,1761,1763],{"class":1340,"line":247},[1338,1760,1724],{"class":1343},[1338,1762,1573],{"class":1347},[1338,1764,1362],{"class":1343},[1338,1766,1767],{"class":1340,"line":236},[1338,1768,1694],{"class":1343},[1338,1770,1771,1773,1775,1778],{"class":1340,"line":225},[1338,1772,1377],{"class":1343},[1338,1774,1573],{"class":1347},[1338,1776,1777],{"class":1351}," #footer",[1338,1779,1362],{"class":1343},[1338,1781,1782,1784,1786,1789,1791],{"class":1340,"line":214},[1338,1783,1710],{"class":1343},[1338,1785,1224],{"class":1347},[1338,1787,1788],{"class":1343},">這是 footer\u003C\u002F",[1338,1790,1224],{"class":1347},[1338,1792,1362],{"class":1343},[1338,1794,1795,1797,1799],{"class":1340,"line":203},[1338,1796,1724],{"class":1343},[1338,1798,1573],{"class":1347},[1338,1800,1362],{"class":1343},[1338,1802,1803],{"class":1340,"line":192},[1338,1804,1694],{"class":1343},[1338,1806,1807,1809,1811],{"class":1340,"line":181},[1338,1808,1400],{"class":1343},[1338,1810,1687],{"class":1347},[1338,1812,1362],{"class":1343},[1338,1814,1815,1817,1819],{"class":1340,"line":170},[1338,1816,1409],{"class":1343},[1338,1818,1348],{"class":1347},[1338,1820,1362],{"class":1343},[1216,1822,1823],{},"子組件 Vue Template",[1329,1825,1827],{"className":1331,"code":1826,"language":1333,"meta":1334,"style":1334},"\u003Ctemplate id=\"child\">\n  \n  \u003Cheader>\n    \u003Cslot name=\"header\">\u003C\u002Fslot>\n  \u003C\u002Fheader>\n  \n  \u003Cmain>\n    \u003Cslot name=\"main\">\u003C\u002Fslot>\n  \u003C\u002Fmain>\n  \n  \u003Cfooter>\n    \u003Cslot name=\"footer\">\u003C\u002Fslot>\n  \u003C\u002Ffooter>\n  \n\u003C\u002Ftemplate>\n",[1273,1828,1829,1844,1849,1857,1878,1886,1890,1898,1917,1925,1929,1937,1956,1964,1968],{"__ignoreMap":1334},[1338,1830,1831,1833,1835,1837,1839,1842],{"class":1340,"line":340},[1338,1832,1344],{"class":1343},[1338,1834,1573],{"class":1347},[1338,1836,1352],{"class":1351},[1338,1838,1355],{"class":1343},[1338,1840,1841],{"class":1358},"\"child\"",[1338,1843,1362],{"class":1343},[1338,1845,1846],{"class":1340,"line":329},[1338,1847,1848],{"class":1343},"  \n",[1338,1850,1851,1853,1855],{"class":1340,"line":318},[1338,1852,1367],{"class":1343},[1338,1854,1640],{"class":1347},[1338,1856,1362],{"class":1343},[1338,1858,1859,1861,1863,1866,1868,1871,1874,1876],{"class":1340,"line":134},[1338,1860,1377],{"class":1343},[1338,1862,1323],{"class":1347},[1338,1864,1865],{"class":1351}," name",[1338,1867,1355],{"class":1343},[1338,1869,1870],{"class":1358},"\"header\"",[1338,1872,1873],{"class":1343},">\u003C\u002F",[1338,1875,1323],{"class":1347},[1338,1877,1362],{"class":1343},[1338,1879,1880,1882,1884],{"class":1340,"line":122},[1338,1881,1400],{"class":1343},[1338,1883,1640],{"class":1347},[1338,1885,1362],{"class":1343},[1338,1887,1888],{"class":1340,"line":31},[1338,1889,1848],{"class":1343},[1338,1891,1892,1894,1896],{"class":1340,"line":17},[1338,1893,1367],{"class":1343},[1338,1895,1644],{"class":1347},[1338,1897,1362],{"class":1343},[1338,1899,1900,1902,1904,1906,1908,1911,1913,1915],{"class":1340,"line":110},[1338,1901,1377],{"class":1343},[1338,1903,1323],{"class":1347},[1338,1905,1865],{"class":1351},[1338,1907,1355],{"class":1343},[1338,1909,1910],{"class":1358},"\"main\"",[1338,1912,1873],{"class":1343},[1338,1914,1323],{"class":1347},[1338,1916,1362],{"class":1343},[1338,1918,1919,1921,1923],{"class":1340,"line":76},[1338,1920,1400],{"class":1343},[1338,1922,1644],{"class":1347},[1338,1924,1362],{"class":1343},[1338,1926,1927],{"class":1340,"line":247},[1338,1928,1848],{"class":1343},[1338,1930,1931,1933,1935],{"class":1340,"line":236},[1338,1932,1367],{"class":1343},[1338,1934,1648],{"class":1347},[1338,1936,1362],{"class":1343},[1338,1938,1939,1941,1943,1945,1947,1950,1952,1954],{"class":1340,"line":225},[1338,1940,1377],{"class":1343},[1338,1942,1323],{"class":1347},[1338,1944,1865],{"class":1351},[1338,1946,1355],{"class":1343},[1338,1948,1949],{"class":1358},"\"footer\"",[1338,1951,1873],{"class":1343},[1338,1953,1323],{"class":1347},[1338,1955,1362],{"class":1343},[1338,1957,1958,1960,1962],{"class":1340,"line":214},[1338,1959,1400],{"class":1343},[1338,1961,1648],{"class":1347},[1338,1963,1362],{"class":1343},[1338,1965,1966],{"class":1340,"line":203},[1338,1967,1848],{"class":1343},[1338,1969,1970,1972,1974],{"class":1340,"line":192},[1338,1971,1409],{"class":1343},[1338,1973,1573],{"class":1347},[1338,1975,1362],{"class":1343},[1256,1977],{},[1216,1979,1980,1981,1983,1984,1987,1988,1990],{},"如果",[1273,1982,1323],{},"標籤未設置名稱，或者使用了預設名稱",[1273,1985,1986],{},"default","，那麼所有無法對應到具名插槽的模板內容都會被放置在這個插槽中。可以將",[1273,1989,1323],{},"標籤想像成一個分類器，負責將父組件傳入的模板內容進行分類。",[1216,1992,1993],{},"延續上面的案例，我們試著透過範例更加了解：",[1216,1995,1300,1996],{},[1266,1997,2000],{"href":1998,"rel":1999},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FjOgbqoQ",[1269],"Vue3 Options API slot 未命名內容插槽與具名插槽的使用實作連結",[1216,2002,1327],{},[1329,2004,2006],{"className":1331,"code":2005,"language":1333,"meta":1334,"style":1334},"\u003Cdiv id=\"app\">\n  \u003Cbase-layout>\n\n    \u003Ctemplate v-slot:header>\n      \u003Ch2>這是 header\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #main>\n      \u003Ch2>這是 main\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #footer>\n      \u003Ch2>這是 footer\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n\n    \u003Cdiv #test1122334455>123\u003C\u002Fdiv>\n    \u003Cp>我是剩餘段落\u003C\u002Fp>\n\n  \u003C\u002Fbase-layout>\n\u003C\u002Fdiv>\n",[1273,2007,2008,2022,2030,2036,2046,2058,2066,2070,2080,2092,2100,2104,2114,2126,2134,2138,2154,2167,2171,2179],{"__ignoreMap":1334},[1338,2009,2010,2012,2014,2016,2018,2020],{"class":1340,"line":340},[1338,2011,1344],{"class":1343},[1338,2013,1348],{"class":1347},[1338,2015,1352],{"class":1351},[1338,2017,1355],{"class":1343},[1338,2019,1359],{"class":1358},[1338,2021,1362],{"class":1343},[1338,2023,2024,2026,2028],{"class":1340,"line":329},[1338,2025,1367],{"class":1343},[1338,2027,1687],{"class":1347},[1338,2029,1362],{"class":1343},[1338,2031,2032],{"class":1340,"line":318},[1338,2033,2035],{"emptyLinePlaceholder":2034},true,"\n",[1338,2037,2038,2040,2042,2044],{"class":1340,"line":134},[1338,2039,1377],{"class":1343},[1338,2041,1573],{"class":1347},[1338,2043,1703],{"class":1351},[1338,2045,1362],{"class":1343},[1338,2047,2048,2050,2052,2054,2056],{"class":1340,"line":122},[1338,2049,1710],{"class":1343},[1338,2051,1224],{"class":1347},[1338,2053,1715],{"class":1343},[1338,2055,1224],{"class":1347},[1338,2057,1362],{"class":1343},[1338,2059,2060,2062,2064],{"class":1340,"line":31},[1338,2061,1724],{"class":1343},[1338,2063,1573],{"class":1347},[1338,2065,1362],{"class":1343},[1338,2067,2068],{"class":1340,"line":17},[1338,2069,2035],{"emptyLinePlaceholder":2034},[1338,2071,2072,2074,2076,2078],{"class":1340,"line":110},[1338,2073,1377],{"class":1343},[1338,2075,1573],{"class":1347},[1338,2077,1741],{"class":1351},[1338,2079,1362],{"class":1343},[1338,2081,2082,2084,2086,2088,2090],{"class":1340,"line":76},[1338,2083,1710],{"class":1343},[1338,2085,1224],{"class":1347},[1338,2087,1752],{"class":1343},[1338,2089,1224],{"class":1347},[1338,2091,1362],{"class":1343},[1338,2093,2094,2096,2098],{"class":1340,"line":247},[1338,2095,1724],{"class":1343},[1338,2097,1573],{"class":1347},[1338,2099,1362],{"class":1343},[1338,2101,2102],{"class":1340,"line":236},[1338,2103,2035],{"emptyLinePlaceholder":2034},[1338,2105,2106,2108,2110,2112],{"class":1340,"line":225},[1338,2107,1377],{"class":1343},[1338,2109,1573],{"class":1347},[1338,2111,1777],{"class":1351},[1338,2113,1362],{"class":1343},[1338,2115,2116,2118,2120,2122,2124],{"class":1340,"line":214},[1338,2117,1710],{"class":1343},[1338,2119,1224],{"class":1347},[1338,2121,1788],{"class":1343},[1338,2123,1224],{"class":1347},[1338,2125,1362],{"class":1343},[1338,2127,2128,2130,2132],{"class":1340,"line":203},[1338,2129,1724],{"class":1343},[1338,2131,1573],{"class":1347},[1338,2133,1362],{"class":1343},[1338,2135,2136],{"class":1340,"line":192},[1338,2137,2035],{"emptyLinePlaceholder":2034},[1338,2139,2140,2142,2144,2147,2150,2152],{"class":1340,"line":181},[1338,2141,1377],{"class":1343},[1338,2143,1348],{"class":1347},[1338,2145,2146],{"class":1351}," #test1122334455",[1338,2148,2149],{"class":1343},">123\u003C\u002F",[1338,2151,1348],{"class":1347},[1338,2153,1362],{"class":1343},[1338,2155,2156,2158,2160,2163,2165],{"class":1340,"line":170},[1338,2157,1377],{"class":1343},[1338,2159,1216],{"class":1347},[1338,2161,2162],{"class":1343},">我是剩餘段落\u003C\u002F",[1338,2164,1216],{"class":1347},[1338,2166,1362],{"class":1343},[1338,2168,2169],{"class":1340,"line":159},[1338,2170,2035],{"emptyLinePlaceholder":2034},[1338,2172,2173,2175,2177],{"class":1340,"line":148},[1338,2174,1400],{"class":1343},[1338,2176,1687],{"class":1347},[1338,2178,1362],{"class":1343},[1338,2180,2181,2183,2185],{"class":1340,"line":137},[1338,2182,1409],{"class":1343},[1338,2184,1348],{"class":1347},[1338,2186,1362],{"class":1343},[1216,2188,1496],{},[1329,2190,2192],{"className":1331,"code":2191,"language":1333,"meta":1334,"style":1334},"\u003Ctemplate id=\"child\">\n\n  \u003Cheader>\n    \u003Cslot name=\"header\">\u003C\u002Fslot>\n  \u003C\u002Fheader>\n\n  \u003Cmain>\n    \u003Cslot name=\"main\">\u003C\u002Fslot>\n  \u003C\u002Fmain>\n\n  \u003Cfooter>\n    \u003Cslot name=\"footer\">\u003C\u002Fslot>\n  \u003C\u002Ffooter>\n\n  \u003Cdiv class=\"container\">\n    \u003Ch2>未命名插槽內容（預設插槽）\u003C\u002Fh2>\n    \u003Cslot>\u003C\u002Fslot>\n    \u003Ch2>具名的預設插槽內容（插槽名稱為 \"default\"）\u003C\u002Fh2>\n    \u003Cslot name=\"default\">\u003C\u002Fslot>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[1273,2193,2194,2208,2212,2220,2238,2246,2250,2258,2276,2284,2288,2296,2314,2322,2326,2342,2355,2367,2380,2399,2407],{"__ignoreMap":1334},[1338,2195,2196,2198,2200,2202,2204,2206],{"class":1340,"line":340},[1338,2197,1344],{"class":1343},[1338,2199,1573],{"class":1347},[1338,2201,1352],{"class":1351},[1338,2203,1355],{"class":1343},[1338,2205,1841],{"class":1358},[1338,2207,1362],{"class":1343},[1338,2209,2210],{"class":1340,"line":329},[1338,2211,2035],{"emptyLinePlaceholder":2034},[1338,2213,2214,2216,2218],{"class":1340,"line":318},[1338,2215,1367],{"class":1343},[1338,2217,1640],{"class":1347},[1338,2219,1362],{"class":1343},[1338,2221,2222,2224,2226,2228,2230,2232,2234,2236],{"class":1340,"line":134},[1338,2223,1377],{"class":1343},[1338,2225,1323],{"class":1347},[1338,2227,1865],{"class":1351},[1338,2229,1355],{"class":1343},[1338,2231,1870],{"class":1358},[1338,2233,1873],{"class":1343},[1338,2235,1323],{"class":1347},[1338,2237,1362],{"class":1343},[1338,2239,2240,2242,2244],{"class":1340,"line":122},[1338,2241,1400],{"class":1343},[1338,2243,1640],{"class":1347},[1338,2245,1362],{"class":1343},[1338,2247,2248],{"class":1340,"line":31},[1338,2249,2035],{"emptyLinePlaceholder":2034},[1338,2251,2252,2254,2256],{"class":1340,"line":17},[1338,2253,1367],{"class":1343},[1338,2255,1644],{"class":1347},[1338,2257,1362],{"class":1343},[1338,2259,2260,2262,2264,2266,2268,2270,2272,2274],{"class":1340,"line":110},[1338,2261,1377],{"class":1343},[1338,2263,1323],{"class":1347},[1338,2265,1865],{"class":1351},[1338,2267,1355],{"class":1343},[1338,2269,1910],{"class":1358},[1338,2271,1873],{"class":1343},[1338,2273,1323],{"class":1347},[1338,2275,1362],{"class":1343},[1338,2277,2278,2280,2282],{"class":1340,"line":76},[1338,2279,1400],{"class":1343},[1338,2281,1644],{"class":1347},[1338,2283,1362],{"class":1343},[1338,2285,2286],{"class":1340,"line":247},[1338,2287,2035],{"emptyLinePlaceholder":2034},[1338,2289,2290,2292,2294],{"class":1340,"line":236},[1338,2291,1367],{"class":1343},[1338,2293,1648],{"class":1347},[1338,2295,1362],{"class":1343},[1338,2297,2298,2300,2302,2304,2306,2308,2310,2312],{"class":1340,"line":225},[1338,2299,1377],{"class":1343},[1338,2301,1323],{"class":1347},[1338,2303,1865],{"class":1351},[1338,2305,1355],{"class":1343},[1338,2307,1949],{"class":1358},[1338,2309,1873],{"class":1343},[1338,2311,1323],{"class":1347},[1338,2313,1362],{"class":1343},[1338,2315,2316,2318,2320],{"class":1340,"line":214},[1338,2317,1400],{"class":1343},[1338,2319,1648],{"class":1347},[1338,2321,1362],{"class":1343},[1338,2323,2324],{"class":1340,"line":203},[1338,2325,2035],{"emptyLinePlaceholder":2034},[1338,2327,2328,2330,2332,2335,2337,2340],{"class":1340,"line":192},[1338,2329,1367],{"class":1343},[1338,2331,1348],{"class":1347},[1338,2333,2334],{"class":1351}," class",[1338,2336,1355],{"class":1343},[1338,2338,2339],{"class":1358},"\"container\"",[1338,2341,1362],{"class":1343},[1338,2343,2344,2346,2348,2351,2353],{"class":1340,"line":181},[1338,2345,1377],{"class":1343},[1338,2347,1224],{"class":1347},[1338,2349,2350],{"class":1343},">未命名插槽內容（預設插槽）\u003C\u002F",[1338,2352,1224],{"class":1347},[1338,2354,1362],{"class":1343},[1338,2356,2357,2359,2361,2363,2365],{"class":1340,"line":170},[1338,2358,1377],{"class":1343},[1338,2360,1323],{"class":1347},[1338,2362,1873],{"class":1343},[1338,2364,1323],{"class":1347},[1338,2366,1362],{"class":1343},[1338,2368,2369,2371,2373,2376,2378],{"class":1340,"line":159},[1338,2370,1377],{"class":1343},[1338,2372,1224],{"class":1347},[1338,2374,2375],{"class":1343},">具名的預設插槽內容（插槽名稱為 \"default\"）\u003C\u002F",[1338,2377,1224],{"class":1347},[1338,2379,1362],{"class":1343},[1338,2381,2382,2384,2386,2388,2390,2393,2395,2397],{"class":1340,"line":148},[1338,2383,1377],{"class":1343},[1338,2385,1323],{"class":1347},[1338,2387,1865],{"class":1351},[1338,2389,1355],{"class":1343},[1338,2391,2392],{"class":1358},"\"default\"",[1338,2394,1873],{"class":1343},[1338,2396,1323],{"class":1347},[1338,2398,1362],{"class":1343},[1338,2400,2401,2403,2405],{"class":1340,"line":137},[1338,2402,1400],{"class":1343},[1338,2404,1348],{"class":1347},[1338,2406,1362],{"class":1343},[1338,2408,2409,2411,2413],{"class":1340,"line":125},[1338,2410,1409],{"class":1343},[1338,2412,1573],{"class":1347},[1338,2414,1362],{"class":1343},[1216,2416,2417,2418,2421,2422,2425,2426,2428],{},"在這裡可以看到，使用",[1273,2419,2420],{},"#test1122334455","這個具名插槽，但在子組件中沒有對應的插槽，因此其內容會自動放置到未命名的",[1273,2423,2424],{},"\u003Cslot>\u003C\u002Fslot>","或具名為",[1273,2427,1986],{},"的插槽中。",[1259,2430,1239],{"id":2431},"子組件插槽傳遞參數-作用域插槽",[1216,2433,2434,2435,2437,2438,2441],{},"一般來說，使用",[1273,2436,1323],{},"插槽時，父組件會傳遞模板內容給子組件來進行渲染。然而，在某些情況下，我們可能希望部分數據的控管在子組件中進行，並將這些參數回傳給父組件，使父組件能根據這些參數動態改變傳入的模板內容。這時，我們會使用",[1273,2439,2440],{},"作用域插槽","，使子組件能將必要的參數提供給父組件使用。",[1216,2443,2444],{},"此外，根據是否使用具名插槽，插槽的使用方式會有所不同。以下將分別舉例，幫助大家更好地理解作用域插槽的應用。",[1228,2446,2447],{},[1231,2448,2449,2452,2453,2456],{},[1593,2450,2451],{},"預設內容插槽傳遞參數的情形","：子組件通過插槽傳遞的所有內容，會被包裝在父組件使用 v-slot 定義的變數中（例如：",[1273,2454,2455],{},"\u003Cmy-component v-slot=\"slotProps\">","）",[1216,2458,2459],{},[1219,2460],{"alt":2461,"src":2462},"slot 作用域插槽官方範例圖","https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728101208\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002Fslot_%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%8F%92%E6%A7%BD%E5%AE%98%E6%96%B9%E7%AF%84%E4%BE%8B%E5%9C%96_amxkod.png",[1216,2464,1300,2465],{},[1266,2466,2469],{"href":2467,"rel":2468},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FyLmYVME",[1269],"Vue3 Options API 子組件默認內容插槽傳遞參數實作連結",[1216,2471,1327],{},[1329,2473,2475],{"className":1331,"code":2474,"language":1333,"meta":1334,"style":1334},"\u003Cdiv id=\"app\">\n  \u003Cmy-component v-slot=\"slotProps\">\n    \u003Cp>slotProps：{{ slotProps }}\u003C\u002Fp>\n    \u003Cp>text：{{ slotProps.text }}\u003C\u002Fp>\n    \u003Cp>count：{{ slotProps.count }}\u003C\u002Fp>\n  \u003C\u002Fmy-component>\n  \u003Cp>子組件外部範圍 slotProps：{{ slotProps }}\u003C\u002Fp>\n\u003C\u002Fdiv>\n",[1273,2476,2477,2491,2508,2521,2534,2547,2555,2568],{"__ignoreMap":1334},[1338,2478,2479,2481,2483,2485,2487,2489],{"class":1340,"line":340},[1338,2480,1344],{"class":1343},[1338,2482,1348],{"class":1347},[1338,2484,1352],{"class":1351},[1338,2486,1355],{"class":1343},[1338,2488,1359],{"class":1358},[1338,2490,1362],{"class":1343},[1338,2492,2493,2495,2498,2501,2503,2506],{"class":1340,"line":329},[1338,2494,1367],{"class":1343},[1338,2496,2497],{"class":1347},"my-component",[1338,2499,2500],{"class":1351}," v-slot",[1338,2502,1355],{"class":1343},[1338,2504,2505],{"class":1358},"\"slotProps\"",[1338,2507,1362],{"class":1343},[1338,2509,2510,2512,2514,2517,2519],{"class":1340,"line":318},[1338,2511,1377],{"class":1343},[1338,2513,1216],{"class":1347},[1338,2515,2516],{"class":1343},">slotProps：{{ slotProps }}\u003C\u002F",[1338,2518,1216],{"class":1347},[1338,2520,1362],{"class":1343},[1338,2522,2523,2525,2527,2530,2532],{"class":1340,"line":134},[1338,2524,1377],{"class":1343},[1338,2526,1216],{"class":1347},[1338,2528,2529],{"class":1343},">text：{{ slotProps.text }}\u003C\u002F",[1338,2531,1216],{"class":1347},[1338,2533,1362],{"class":1343},[1338,2535,2536,2538,2540,2543,2545],{"class":1340,"line":122},[1338,2537,1377],{"class":1343},[1338,2539,1216],{"class":1347},[1338,2541,2542],{"class":1343},">count：{{ slotProps.count }}\u003C\u002F",[1338,2544,1216],{"class":1347},[1338,2546,1362],{"class":1343},[1338,2548,2549,2551,2553],{"class":1340,"line":31},[1338,2550,1400],{"class":1343},[1338,2552,2497],{"class":1347},[1338,2554,1362],{"class":1343},[1338,2556,2557,2559,2561,2564,2566],{"class":1340,"line":17},[1338,2558,1367],{"class":1343},[1338,2560,1216],{"class":1347},[1338,2562,2563],{"class":1343},">子組件外部範圍 slotProps：{{ slotProps }}\u003C\u002F",[1338,2565,1216],{"class":1347},[1338,2567,1362],{"class":1343},[1338,2569,2570,2572,2574],{"class":1340,"line":110},[1338,2571,1409],{"class":1343},[1338,2573,1348],{"class":1347},[1338,2575,1362],{"class":1343},[1216,2577,2578,2579,2581,2582,2585],{},"⭐ 子組件通過",[1273,2580,1586],{},"傳遞的",[1273,2583,2584],{},"slotProps","參數只能在父組件中引用插槽內容的區域內使用，而不能在父組件的外部範圍使用。",[1216,2587,1496],{},[1329,2589,2591],{"className":1331,"code":2590,"language":1333,"meta":1334,"style":1334},"\u003Ctemplate id=\"child\">\n  \u003Cslot :text=\"text\" :count=\"count\">\u003C\u002Fslot>\n\u003C\u002Ftemplate>\n",[1273,2592,2593,2607,2635],{"__ignoreMap":1334},[1338,2594,2595,2597,2599,2601,2603,2605],{"class":1340,"line":340},[1338,2596,1344],{"class":1343},[1338,2598,1573],{"class":1347},[1338,2600,1352],{"class":1351},[1338,2602,1355],{"class":1343},[1338,2604,1841],{"class":1358},[1338,2606,1362],{"class":1343},[1338,2608,2609,2611,2613,2616,2618,2621,2624,2626,2629,2631,2633],{"class":1340,"line":329},[1338,2610,1367],{"class":1343},[1338,2612,1323],{"class":1347},[1338,2614,2615],{"class":1351}," :text",[1338,2617,1355],{"class":1343},[1338,2619,2620],{"class":1358},"\"text\"",[1338,2622,2623],{"class":1351}," :count",[1338,2625,1355],{"class":1343},[1338,2627,2628],{"class":1358},"\"count\"",[1338,2630,1873],{"class":1343},[1338,2632,1323],{"class":1347},[1338,2634,1362],{"class":1343},[1338,2636,2637,2639,2641],{"class":1340,"line":318},[1338,2638,1409],{"class":1343},[1338,2640,1573],{"class":1347},[1338,2642,1362],{"class":1343},[1228,2644,2645],{},[1231,2646,2647,2650,2651,2654,2655,2657,2658,2660],{},[1593,2648,2649],{},"具名插槽傳遞參數的情況","：子組件傳遞的參數必須對應到父組件中的具名",[1273,2652,2653],{},"\u003Ctemplate>","，否則參數無法正確傳遞與使用。在傳遞參數時，具名插槽會將其對應於特定的",[1273,2656,2653],{},"，而且這些參數的作用域僅限於對應的",[1273,2659,2653],{},"標籤內。",[1216,2662,1300,2663],{},[1266,2664,2667],{"href":2665,"rel":2666},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FGRVpMav",[1269],"Vue3 Options API slot 具名插槽傳值實作連結",[1216,2669,1327],{},[1329,2671,2673],{"className":1331,"code":2672,"language":1333,"meta":1334,"style":1334},"\u003Cdiv id=\"app\">\n  \u003Cbase-layout>\n\n    \u003Ctemplate #header=\"slotProps\">\n      \u003Ch2>這是 header\u003C\u002Fh2>\n      \u003Cp>查看子組件傳入的參數值：{{ slotProps }}\u003C\u002Fp>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #main=\"slotProps\">\n      \u003Ch2>這是 main\u003C\u002Fh2>\n      \u003Cp>查看子組件傳入的參數值：{{ slotProps }}\u003C\u002Fp>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #footer=\"slotProps\">\n      \u003Ch2>這是 footer\u003C\u002Fh2>\n      \u003Cp>查看子組件傳入的參數值：{{ slotProps }}\u003C\u002Fp>\n    \u003C\u002Ftemplate>\n\n  \u003C\u002Fbase-layout>\n\u003C\u002Fdiv>\n",[1273,2674,2675,2689,2697,2701,2716,2728,2741,2749,2753,2767,2779,2791,2799,2803,2817,2829,2841,2849,2853,2861],{"__ignoreMap":1334},[1338,2676,2677,2679,2681,2683,2685,2687],{"class":1340,"line":340},[1338,2678,1344],{"class":1343},[1338,2680,1348],{"class":1347},[1338,2682,1352],{"class":1351},[1338,2684,1355],{"class":1343},[1338,2686,1359],{"class":1358},[1338,2688,1362],{"class":1343},[1338,2690,2691,2693,2695],{"class":1340,"line":329},[1338,2692,1367],{"class":1343},[1338,2694,1687],{"class":1347},[1338,2696,1362],{"class":1343},[1338,2698,2699],{"class":1340,"line":318},[1338,2700,2035],{"emptyLinePlaceholder":2034},[1338,2702,2703,2705,2707,2710,2712,2714],{"class":1340,"line":134},[1338,2704,1377],{"class":1343},[1338,2706,1573],{"class":1347},[1338,2708,2709],{"class":1351}," #header",[1338,2711,1355],{"class":1343},[1338,2713,2505],{"class":1358},[1338,2715,1362],{"class":1343},[1338,2717,2718,2720,2722,2724,2726],{"class":1340,"line":122},[1338,2719,1710],{"class":1343},[1338,2721,1224],{"class":1347},[1338,2723,1715],{"class":1343},[1338,2725,1224],{"class":1347},[1338,2727,1362],{"class":1343},[1338,2729,2730,2732,2734,2737,2739],{"class":1340,"line":31},[1338,2731,1710],{"class":1343},[1338,2733,1216],{"class":1347},[1338,2735,2736],{"class":1343},">查看子組件傳入的參數值：{{ slotProps }}\u003C\u002F",[1338,2738,1216],{"class":1347},[1338,2740,1362],{"class":1343},[1338,2742,2743,2745,2747],{"class":1340,"line":17},[1338,2744,1724],{"class":1343},[1338,2746,1573],{"class":1347},[1338,2748,1362],{"class":1343},[1338,2750,2751],{"class":1340,"line":110},[1338,2752,2035],{"emptyLinePlaceholder":2034},[1338,2754,2755,2757,2759,2761,2763,2765],{"class":1340,"line":76},[1338,2756,1377],{"class":1343},[1338,2758,1573],{"class":1347},[1338,2760,1741],{"class":1351},[1338,2762,1355],{"class":1343},[1338,2764,2505],{"class":1358},[1338,2766,1362],{"class":1343},[1338,2768,2769,2771,2773,2775,2777],{"class":1340,"line":247},[1338,2770,1710],{"class":1343},[1338,2772,1224],{"class":1347},[1338,2774,1752],{"class":1343},[1338,2776,1224],{"class":1347},[1338,2778,1362],{"class":1343},[1338,2780,2781,2783,2785,2787,2789],{"class":1340,"line":236},[1338,2782,1710],{"class":1343},[1338,2784,1216],{"class":1347},[1338,2786,2736],{"class":1343},[1338,2788,1216],{"class":1347},[1338,2790,1362],{"class":1343},[1338,2792,2793,2795,2797],{"class":1340,"line":225},[1338,2794,1724],{"class":1343},[1338,2796,1573],{"class":1347},[1338,2798,1362],{"class":1343},[1338,2800,2801],{"class":1340,"line":214},[1338,2802,2035],{"emptyLinePlaceholder":2034},[1338,2804,2805,2807,2809,2811,2813,2815],{"class":1340,"line":203},[1338,2806,1377],{"class":1343},[1338,2808,1573],{"class":1347},[1338,2810,1777],{"class":1351},[1338,2812,1355],{"class":1343},[1338,2814,2505],{"class":1358},[1338,2816,1362],{"class":1343},[1338,2818,2819,2821,2823,2825,2827],{"class":1340,"line":192},[1338,2820,1710],{"class":1343},[1338,2822,1224],{"class":1347},[1338,2824,1788],{"class":1343},[1338,2826,1224],{"class":1347},[1338,2828,1362],{"class":1343},[1338,2830,2831,2833,2835,2837,2839],{"class":1340,"line":181},[1338,2832,1710],{"class":1343},[1338,2834,1216],{"class":1347},[1338,2836,2736],{"class":1343},[1338,2838,1216],{"class":1347},[1338,2840,1362],{"class":1343},[1338,2842,2843,2845,2847],{"class":1340,"line":170},[1338,2844,1724],{"class":1343},[1338,2846,1573],{"class":1347},[1338,2848,1362],{"class":1343},[1338,2850,2851],{"class":1340,"line":159},[1338,2852,2035],{"emptyLinePlaceholder":2034},[1338,2854,2855,2857,2859],{"class":1340,"line":148},[1338,2856,1400],{"class":1343},[1338,2858,1687],{"class":1347},[1338,2860,1362],{"class":1343},[1338,2862,2863,2865,2867],{"class":1340,"line":137},[1338,2864,1409],{"class":1343},[1338,2866,1348],{"class":1347},[1338,2868,1362],{"class":1343},[1216,2870,1496],{},[1329,2872,2874],{"className":1331,"code":2873,"language":1333,"meta":1334,"style":1334},"\u003Ctemplate id=\"child\">\n\n  \u003Cheader>\n    \u003Cslot name=\"header\" :headeMessage=\"headeMessage\">\u003C\u002Fslot>\n  \u003C\u002Fheader>\n\n  \u003Cmain>\n    \u003Cslot name=\"main\" :mainMessage=\"mainMessage\">\u003C\u002Fslot>\n  \u003C\u002Fmain>\n\n  \u003Cfooter>\n    \u003Cslot name=\"footer\" :footerMessage=\"footerMessage\">\u003C\u002Fslot>\n  \u003C\u002Ffooter>\n\n\u003C\u002Ftemplate>\n",[1273,2875,2876,2890,2894,2902,2928,2936,2940,2948,2974,2982,2986,2994,3020,3028,3032],{"__ignoreMap":1334},[1338,2877,2878,2880,2882,2884,2886,2888],{"class":1340,"line":340},[1338,2879,1344],{"class":1343},[1338,2881,1573],{"class":1347},[1338,2883,1352],{"class":1351},[1338,2885,1355],{"class":1343},[1338,2887,1841],{"class":1358},[1338,2889,1362],{"class":1343},[1338,2891,2892],{"class":1340,"line":329},[1338,2893,2035],{"emptyLinePlaceholder":2034},[1338,2895,2896,2898,2900],{"class":1340,"line":318},[1338,2897,1367],{"class":1343},[1338,2899,1640],{"class":1347},[1338,2901,1362],{"class":1343},[1338,2903,2904,2906,2908,2910,2912,2914,2917,2919,2922,2924,2926],{"class":1340,"line":134},[1338,2905,1377],{"class":1343},[1338,2907,1323],{"class":1347},[1338,2909,1865],{"class":1351},[1338,2911,1355],{"class":1343},[1338,2913,1870],{"class":1358},[1338,2915,2916],{"class":1351}," :headeMessage",[1338,2918,1355],{"class":1343},[1338,2920,2921],{"class":1358},"\"headeMessage\"",[1338,2923,1873],{"class":1343},[1338,2925,1323],{"class":1347},[1338,2927,1362],{"class":1343},[1338,2929,2930,2932,2934],{"class":1340,"line":122},[1338,2931,1400],{"class":1343},[1338,2933,1640],{"class":1347},[1338,2935,1362],{"class":1343},[1338,2937,2938],{"class":1340,"line":31},[1338,2939,2035],{"emptyLinePlaceholder":2034},[1338,2941,2942,2944,2946],{"class":1340,"line":17},[1338,2943,1367],{"class":1343},[1338,2945,1644],{"class":1347},[1338,2947,1362],{"class":1343},[1338,2949,2950,2952,2954,2956,2958,2960,2963,2965,2968,2970,2972],{"class":1340,"line":110},[1338,2951,1377],{"class":1343},[1338,2953,1323],{"class":1347},[1338,2955,1865],{"class":1351},[1338,2957,1355],{"class":1343},[1338,2959,1910],{"class":1358},[1338,2961,2962],{"class":1351}," :mainMessage",[1338,2964,1355],{"class":1343},[1338,2966,2967],{"class":1358},"\"mainMessage\"",[1338,2969,1873],{"class":1343},[1338,2971,1323],{"class":1347},[1338,2973,1362],{"class":1343},[1338,2975,2976,2978,2980],{"class":1340,"line":76},[1338,2977,1400],{"class":1343},[1338,2979,1644],{"class":1347},[1338,2981,1362],{"class":1343},[1338,2983,2984],{"class":1340,"line":247},[1338,2985,2035],{"emptyLinePlaceholder":2034},[1338,2987,2988,2990,2992],{"class":1340,"line":236},[1338,2989,1367],{"class":1343},[1338,2991,1648],{"class":1347},[1338,2993,1362],{"class":1343},[1338,2995,2996,2998,3000,3002,3004,3006,3009,3011,3014,3016,3018],{"class":1340,"line":225},[1338,2997,1377],{"class":1343},[1338,2999,1323],{"class":1347},[1338,3001,1865],{"class":1351},[1338,3003,1355],{"class":1343},[1338,3005,1949],{"class":1358},[1338,3007,3008],{"class":1351}," :footerMessage",[1338,3010,1355],{"class":1343},[1338,3012,3013],{"class":1358},"\"footerMessage\"",[1338,3015,1873],{"class":1343},[1338,3017,1323],{"class":1347},[1338,3019,1362],{"class":1343},[1338,3021,3022,3024,3026],{"class":1340,"line":214},[1338,3023,1400],{"class":1343},[1338,3025,1648],{"class":1347},[1338,3027,1362],{"class":1343},[1338,3029,3030],{"class":1340,"line":203},[1338,3031,2035],{"emptyLinePlaceholder":2034},[1338,3033,3034,3036,3038],{"class":1340,"line":192},[1338,3035,1409],{"class":1343},[1338,3037,1573],{"class":1347},[1338,3039,1362],{"class":1343},[1216,3041,3042,3043,1645,3046,3049,3050,3052,3053,3055],{},"在混合上面",[1273,3044,3045],{},"預設內容插槽傳遞參數",[1273,3047,3048],{},"具名插槽傳遞參數","的情況下，預設插槽的內容需要在父組件中使用具名為",[1273,3051,1986],{},"的",[1273,3054,2653],{},"才能正常編譯和顯示。",[1216,3057,1300,3058],{},[1266,3059,3062],{"href":3060,"rel":3061},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FQWejajb",[1269],"Vue3 Options API slot 具名插槽 + 默認內容插槽傳值實作連結",[1259,3064,1242],{"id":3065},"slot-與-props-設計方式比較-以切換卡片展示型態為例",[1216,3067,3068,3069,3071,3072,3074],{},"這裡我們以一個常見的模板類型為例，演示如何將內容以「列表式」或「卡片式」兩種方式進行呈現。我們將以 momo 官方網站為範例，並對比使用",[1273,3070,1275],{},"和",[1273,3073,1323],{},"的組件設計思維，展示不同的實現方式。",[1216,3076,3077,3078,3080],{},"【 momo 官網查詢 - 卡片式呈現搜尋結果 】",[1551,3079],{},[1219,3081],{"alt":3082,"src":3083},"momo 官網查詢 - 卡片式呈現搜尋結果","https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728101758\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002Fmomo_%E7%B6%B2%E9%A0%81%E5%8D%A1%E7%89%87%E5%BC%8F%E5%91%88%E7%8F%BE%E6%96%B9%E5%BC%8F_ehx9kw.png",[1216,3085,3086,3087,3089],{},"【 momo 官網查詢 - 列表式呈現搜尋結果 】",[1551,3088],{},[1219,3090],{"alt":3091,"src":3092},"momo 官網查詢 - 列表式呈現搜尋結果","https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728101812\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002Fmomo_%E5%88%97%E8%A1%A8%E5%BC%8F%E5%91%88%E7%8F%BE%E6%96%B9%E5%BC%8F_dehtt5.png",[1228,3094,3095],{},[1231,3096,3097,3100,3101],{},[1593,3098,3099],{},"props 的設計方式","：\n",[1228,3102,3103,3106],{},[1231,3104,3105],{},"父組件管控要呈現的類別(showType)",[1231,3107,3108,3109,3112],{},"子組件負責取得查詢結果的 API 資料及根據父組件傳入的",[1273,3110,3111],{},"showType props","決定呈現類型的組件。",[1216,3114,1300,3115,3120,3122],{},[1266,3116,3119],{"href":3117,"rel":3118},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FbGXVapG",[1269],"Vue3 Options API 不同排版方式 porps 參數設計方式實作連結",[1551,3121],{},[1219,3123],{"alt":3124,"src":3125},"props 設計卡片式及列表式資料傳遞結構圖","https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728101965\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002FProps_%E8%A8%AD%E8%A8%88%E5%8D%A1%E7%89%87%E5%BC%8F%E5%8F%8A%E5%88%97%E8%A1%A8%E5%BC%8F%E8%B3%87%E6%96%99%E5%82%B3%E9%81%9E%E7%B5%90%E6%A7%8B%E5%9C%96_kbqju2.png",[1228,3127,3128],{},[1231,3129,3130,3100,3133],{},[1593,3131,3132],{},"slot 的設計方式",[1228,3134,3135,3141],{},[1231,3136,3137,3138,3140],{},"父組件負責控制顯示類型(showType)，並根據這個響應式變數決定渲染卡片式或列表式的組件模板內容。渲染所需的數據由子組件通過",[1273,3139,1323],{},"回傳的參數提供。",[1231,3142,3143,3144,3146],{},"子組件負責取得查詢結果的 API 資料並透過",[1273,3145,1323],{},"將參數回傳給父組件使用。",[1216,3148,1300,3149,3154,3156],{},[1266,3150,3153],{"href":3151,"rel":3152},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FWNVQMej",[1269],"Vue3 Options API 不同排版方式 slot 參數設計方式實作連結",[1551,3155],{},[1219,3157],{"alt":3158,"src":3159},"slot 設計卡片式及列表式資料傳遞結構圖","https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728102064\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002FSlot_%E8%A8%AD%E8%A8%88%E5%8D%A1%E7%89%87%E5%BC%8F%E5%8F%8A%E5%88%97%E8%A1%A8%E5%BC%8F%E8%B3%87%E6%96%99%E5%82%B3%E9%81%9E%E7%B5%90%E6%A7%8B%E5%9C%96_gkms0q.png",[1216,3161,3162],{},"兩種方式都能實現相同的功能，主要差異在於當顯示類型需要增加時(例如：新增 grid「四列網格」項目組件)，兩種設計方式的修改如下：",[1310,3164,3165,3194],{},[1231,3166,3167,3170],{},[1593,3168,3169],{},"props 參數設計方式：",[1228,3171,3172,3183,3191],{},[1231,3173,3174,3175,3178,3179,3182],{},"在父組件的",[1273,3176,3177],{},"showType","中新增第三種類型",[1273,3180,3181],{},"grid","。",[1231,3184,3185,3186,3188,3189,3182],{},"在子組件的邏輯判斷中加入新的",[1273,3187,3177],{},"選項",[1273,3190,3181],{},[1231,3192,3193],{},"子組件需新增「四列網格項目組件」以顯示相應的呈現方式。",[1231,3195,3196,3199],{},[1593,3197,3198],{},"slot 參數設計方式：",[1228,3200,3201,3207,3214],{},[1231,3202,3174,3203,3178,3205,3182],{},[1273,3204,3177],{},[1273,3206,3181],{},[1231,3208,3209,3210,3188,3212,3182],{},"在父組件的邏輯判斷中加入新的",[1273,3211,3177],{},[1273,3213,3181],{},[1231,3215,3216,3217,3182],{},"父組件需新增「四列網格項目組件」以顯示對應的",[1273,3218,3219],{},"模板內容",[1216,3221,3222,3225,3226,3228,3229,3231,3232,3235],{},[1593,3223,3224],{},"在這個場景案例中","，使用",[1273,3227,1275],{},"設計方式時，如果需要新增顯示類型，父組件和子組件都需要進行相應的調整。而使用",[1273,3230,1323],{},"設計方式時，子組件的職責更加單一，只負責處理",[1273,3233,3234],{},"API","資料的讀取，因此僅需在父組件中進行修改，讓維護和擴展更為方便。",[1259,3237,1245],{"id":3238},"條件插槽-slots",[1216,3240,3241,3242,3245,3246,3249,3250,3253,3254,3257],{},"在以下示例中，子組件的模板可以使用",[1273,3243,3244],{},"$slots","配合條件語句來判斷插槽是否存在。如果插槽存在，則顯示父組件傳入的模板內容；如果插槽不存在，則顯示一條提示信息：",[1273,3247,3248],{},"\u003Ch2>父組件尚未提供 v-slot 綁定 content\u003C\u002Fh2>","。此外，也可以在",[1273,3251,3252],{},"mounted","生命週期階段通過",[1273,3255,3256],{},"console.log(this.$slots)","來查看當前傳入的具名插槽。",[1216,3259,1300,3260],{},[1266,3261,3264],{"href":3262,"rel":3263},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FWNVrNjY",[1269],"Vue3 Options API slot 條件渲染實作連結",[1216,3266,1327],{},[1329,3268,3270],{"className":1331,"code":3269,"language":1333,"meta":1334,"style":1334},"\u003Cdiv id=\"app\">\n  \u003Cchild-component>\n    \u003Ctemplate #content>\n      hello world vue !\n    \u003C\u002Ftemplate>\n  \u003C\u002Fchild-component>\n\u003C\u002Fdiv>\n",[1273,3271,3272,3286,3295,3306,3311,3319,3327],{"__ignoreMap":1334},[1338,3273,3274,3276,3278,3280,3282,3284],{"class":1340,"line":340},[1338,3275,1344],{"class":1343},[1338,3277,1348],{"class":1347},[1338,3279,1352],{"class":1351},[1338,3281,1355],{"class":1343},[1338,3283,1359],{"class":1358},[1338,3285,1362],{"class":1343},[1338,3287,3288,3290,3293],{"class":1340,"line":329},[1338,3289,1367],{"class":1343},[1338,3291,3292],{"class":1347},"child-component",[1338,3294,1362],{"class":1343},[1338,3296,3297,3299,3301,3304],{"class":1340,"line":318},[1338,3298,1377],{"class":1343},[1338,3300,1573],{"class":1347},[1338,3302,3303],{"class":1351}," #content",[1338,3305,1362],{"class":1343},[1338,3307,3308],{"class":1340,"line":134},[1338,3309,3310],{"class":1343},"      hello world vue !\n",[1338,3312,3313,3315,3317],{"class":1340,"line":122},[1338,3314,1724],{"class":1343},[1338,3316,1573],{"class":1347},[1338,3318,1362],{"class":1343},[1338,3320,3321,3323,3325],{"class":1340,"line":31},[1338,3322,1400],{"class":1343},[1338,3324,3292],{"class":1347},[1338,3326,1362],{"class":1343},[1338,3328,3329,3331,3333],{"class":1340,"line":17},[1338,3330,1409],{"class":1343},[1338,3332,1348],{"class":1347},[1338,3334,1362],{"class":1343},[1216,3336,1496],{},[1329,3338,3340],{"className":1331,"code":3339,"language":1333,"meta":1334,"style":1334},"\u003Ctemplate id=\"childComponent\">\n  \u003Cdiv v-if=\"$slots.content\" class=\"content\">\n    \u003Ch2>\n      \u003Cslot name=\"content\">\u003C\u002Fslot>\n    \u003C\u002Fh2>\n  \u003C\u002Fdiv>\n  \u003Cdiv v-else class=\"default\">\n    \u003Ch2>父組件尚未提供 v-slot 綁定 content\u003C\u002Fh2>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[1273,3341,3342,3357,3380,3388,3406,3414,3422,3439,3452,3460],{"__ignoreMap":1334},[1338,3343,3344,3346,3348,3350,3352,3355],{"class":1340,"line":340},[1338,3345,1344],{"class":1343},[1338,3347,1573],{"class":1347},[1338,3349,1352],{"class":1351},[1338,3351,1355],{"class":1343},[1338,3353,3354],{"class":1358},"\"childComponent\"",[1338,3356,1362],{"class":1343},[1338,3358,3359,3361,3363,3366,3368,3371,3373,3375,3378],{"class":1340,"line":329},[1338,3360,1367],{"class":1343},[1338,3362,1348],{"class":1347},[1338,3364,3365],{"class":1351}," v-if",[1338,3367,1355],{"class":1343},[1338,3369,3370],{"class":1358},"\"$slots.content\"",[1338,3372,2334],{"class":1351},[1338,3374,1355],{"class":1343},[1338,3376,3377],{"class":1358},"\"content\"",[1338,3379,1362],{"class":1343},[1338,3381,3382,3384,3386],{"class":1340,"line":318},[1338,3383,1377],{"class":1343},[1338,3385,1224],{"class":1347},[1338,3387,1362],{"class":1343},[1338,3389,3390,3392,3394,3396,3398,3400,3402,3404],{"class":1340,"line":134},[1338,3391,1710],{"class":1343},[1338,3393,1323],{"class":1347},[1338,3395,1865],{"class":1351},[1338,3397,1355],{"class":1343},[1338,3399,3377],{"class":1358},[1338,3401,1873],{"class":1343},[1338,3403,1323],{"class":1347},[1338,3405,1362],{"class":1343},[1338,3407,3408,3410,3412],{"class":1340,"line":122},[1338,3409,1724],{"class":1343},[1338,3411,1224],{"class":1347},[1338,3413,1362],{"class":1343},[1338,3415,3416,3418,3420],{"class":1340,"line":31},[1338,3417,1400],{"class":1343},[1338,3419,1348],{"class":1347},[1338,3421,1362],{"class":1343},[1338,3423,3424,3426,3428,3431,3433,3435,3437],{"class":1340,"line":17},[1338,3425,1367],{"class":1343},[1338,3427,1348],{"class":1347},[1338,3429,3430],{"class":1351}," v-else",[1338,3432,2334],{"class":1351},[1338,3434,1355],{"class":1343},[1338,3436,2392],{"class":1358},[1338,3438,1362],{"class":1343},[1338,3440,3441,3443,3445,3448,3450],{"class":1340,"line":110},[1338,3442,1377],{"class":1343},[1338,3444,1224],{"class":1347},[1338,3446,3447],{"class":1343},">父組件尚未提供 v-slot 綁定 content\u003C\u002F",[1338,3449,1224],{"class":1347},[1338,3451,1362],{"class":1343},[1338,3453,3454,3456,3458],{"class":1340,"line":76},[1338,3455,1400],{"class":1343},[1338,3457,1348],{"class":1347},[1338,3459,1362],{"class":1343},[1338,3461,3462,3464,3466],{"class":1340,"line":247},[1338,3463,1409],{"class":1343},[1338,3465,1573],{"class":1347},[1338,3467,1362],{"class":1343},[1259,3469,1248],{"id":1248},[1216,3471,3472,3474,3475,3477],{},[1273,3473,1595],{},"可以用來設置動態屬性名稱，而",[1273,3476,1586],{},"同樣可以綁定動態插槽名稱，從而更靈活地控制插槽的內容。",[1216,3479,3480],{},"透過以下案例進行流程說明：",[1310,3482,3483,3494],{},[1231,3484,3485,3486,3489,3490,3493],{},"下拉式選單透過",[1273,3487,3488],{},"v-model","綁定",[1273,3491,3492],{},"blocktype","響應式變數",[1231,3495,3496],{},"根據這個響應式變數可以動態改動要渲染的插槽對象",[1216,3498,1300,3499],{},[1266,3500,3503],{"href":3501,"rel":3502},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FOJeVGOB",[1269],"Vue3 Options API slot 動態插槽實作連結",[1216,3505,1327],{},[1329,3507,3509],{"className":1331,"code":3508,"language":1333,"meta":1334,"style":1334},"\u003Cdiv id=\"app\">\n    \n  \u003Cdiv class=\"input-group\">\n    \u003Clabel for=\"blockOption\">選擇 slot 插槽名稱：\u003C\u002Flabel>\n    \u003Cselect name=\"blockOption\" id=\"blockOption\" v-model=\"blocktype\">\n      \u003Coption disabled value=\"\">請選擇\u003C\u002Foption>\n      \u003Coption value=\"header\">header\u003C\u002Foption>\n      \u003Coption value=\"body\">body\u003C\u002Foption>\n      \u003Coption value=\"footer\">footer\u003C\u002Foption>\n    \u003C\u002Fselect>\n  \u003C\u002Fdiv>\n\n  \u003Cdiv class=\"content\">\n    \u003Cchild-component>\n      \u003Ctemplate #[blocktype]>\n        \u003Ch2>今天開心嗎!!!!!(動態小壞蛋) 顯示 blocktype：{{ blocktype }}\u003C\u002Fh2>\n      \u003C\u002Ftemplate>\n    \u003C\u002Fchild-component>\n  \u003C\u002Fdiv>\n  \n\u003C\u002Fdiv>\n",[1273,3510,3511,3525,3530,3545,3567,3596,3621,3640,3660,3679,3687,3695,3699,3713,3721,3732,3746,3755,3763,3771,3775],{"__ignoreMap":1334},[1338,3512,3513,3515,3517,3519,3521,3523],{"class":1340,"line":340},[1338,3514,1344],{"class":1343},[1338,3516,1348],{"class":1347},[1338,3518,1352],{"class":1351},[1338,3520,1355],{"class":1343},[1338,3522,1359],{"class":1358},[1338,3524,1362],{"class":1343},[1338,3526,3527],{"class":1340,"line":329},[1338,3528,3529],{"class":1343},"    \n",[1338,3531,3532,3534,3536,3538,3540,3543],{"class":1340,"line":318},[1338,3533,1367],{"class":1343},[1338,3535,1348],{"class":1347},[1338,3537,2334],{"class":1351},[1338,3539,1355],{"class":1343},[1338,3541,3542],{"class":1358},"\"input-group\"",[1338,3544,1362],{"class":1343},[1338,3546,3547,3549,3552,3555,3557,3560,3563,3565],{"class":1340,"line":134},[1338,3548,1377],{"class":1343},[1338,3550,3551],{"class":1347},"label",[1338,3553,3554],{"class":1351}," for",[1338,3556,1355],{"class":1343},[1338,3558,3559],{"class":1358},"\"blockOption\"",[1338,3561,3562],{"class":1343},">選擇 slot 插槽名稱：\u003C\u002F",[1338,3564,3551],{"class":1347},[1338,3566,1362],{"class":1343},[1338,3568,3569,3571,3574,3576,3578,3580,3582,3584,3586,3589,3591,3594],{"class":1340,"line":122},[1338,3570,1377],{"class":1343},[1338,3572,3573],{"class":1347},"select",[1338,3575,1865],{"class":1351},[1338,3577,1355],{"class":1343},[1338,3579,3559],{"class":1358},[1338,3581,1352],{"class":1351},[1338,3583,1355],{"class":1343},[1338,3585,3559],{"class":1358},[1338,3587,3588],{"class":1351}," v-model",[1338,3590,1355],{"class":1343},[1338,3592,3593],{"class":1358},"\"blocktype\"",[1338,3595,1362],{"class":1343},[1338,3597,3598,3600,3603,3606,3609,3611,3614,3617,3619],{"class":1340,"line":31},[1338,3599,1710],{"class":1343},[1338,3601,3602],{"class":1347},"option",[1338,3604,3605],{"class":1351}," disabled",[1338,3607,3608],{"class":1351}," value",[1338,3610,1355],{"class":1343},[1338,3612,3613],{"class":1358},"\"\"",[1338,3615,3616],{"class":1343},">請選擇\u003C\u002F",[1338,3618,3602],{"class":1347},[1338,3620,1362],{"class":1343},[1338,3622,3623,3625,3627,3629,3631,3633,3636,3638],{"class":1340,"line":17},[1338,3624,1710],{"class":1343},[1338,3626,3602],{"class":1347},[1338,3628,3608],{"class":1351},[1338,3630,1355],{"class":1343},[1338,3632,1870],{"class":1358},[1338,3634,3635],{"class":1343},">header\u003C\u002F",[1338,3637,3602],{"class":1347},[1338,3639,1362],{"class":1343},[1338,3641,3642,3644,3646,3648,3650,3653,3656,3658],{"class":1340,"line":110},[1338,3643,1710],{"class":1343},[1338,3645,3602],{"class":1347},[1338,3647,3608],{"class":1351},[1338,3649,1355],{"class":1343},[1338,3651,3652],{"class":1358},"\"body\"",[1338,3654,3655],{"class":1343},">body\u003C\u002F",[1338,3657,3602],{"class":1347},[1338,3659,1362],{"class":1343},[1338,3661,3662,3664,3666,3668,3670,3672,3675,3677],{"class":1340,"line":76},[1338,3663,1710],{"class":1343},[1338,3665,3602],{"class":1347},[1338,3667,3608],{"class":1351},[1338,3669,1355],{"class":1343},[1338,3671,1949],{"class":1358},[1338,3673,3674],{"class":1343},">footer\u003C\u002F",[1338,3676,3602],{"class":1347},[1338,3678,1362],{"class":1343},[1338,3680,3681,3683,3685],{"class":1340,"line":247},[1338,3682,1724],{"class":1343},[1338,3684,3573],{"class":1347},[1338,3686,1362],{"class":1343},[1338,3688,3689,3691,3693],{"class":1340,"line":236},[1338,3690,1400],{"class":1343},[1338,3692,1348],{"class":1347},[1338,3694,1362],{"class":1343},[1338,3696,3697],{"class":1340,"line":225},[1338,3698,2035],{"emptyLinePlaceholder":2034},[1338,3700,3701,3703,3705,3707,3709,3711],{"class":1340,"line":214},[1338,3702,1367],{"class":1343},[1338,3704,1348],{"class":1347},[1338,3706,2334],{"class":1351},[1338,3708,1355],{"class":1343},[1338,3710,3377],{"class":1358},[1338,3712,1362],{"class":1343},[1338,3714,3715,3717,3719],{"class":1340,"line":203},[1338,3716,1377],{"class":1343},[1338,3718,3292],{"class":1347},[1338,3720,1362],{"class":1343},[1338,3722,3723,3725,3727,3730],{"class":1340,"line":192},[1338,3724,1710],{"class":1343},[1338,3726,1573],{"class":1347},[1338,3728,3729],{"class":1351}," #[blocktype]",[1338,3731,1362],{"class":1343},[1338,3733,3734,3737,3739,3742,3744],{"class":1340,"line":181},[1338,3735,3736],{"class":1343},"        \u003C",[1338,3738,1224],{"class":1347},[1338,3740,3741],{"class":1343},">今天開心嗎!!!!!(動態小壞蛋) 顯示 blocktype：{{ blocktype }}\u003C\u002F",[1338,3743,1224],{"class":1347},[1338,3745,1362],{"class":1343},[1338,3747,3748,3751,3753],{"class":1340,"line":170},[1338,3749,3750],{"class":1343},"      \u003C\u002F",[1338,3752,1573],{"class":1347},[1338,3754,1362],{"class":1343},[1338,3756,3757,3759,3761],{"class":1340,"line":159},[1338,3758,1724],{"class":1343},[1338,3760,3292],{"class":1347},[1338,3762,1362],{"class":1343},[1338,3764,3765,3767,3769],{"class":1340,"line":148},[1338,3766,1400],{"class":1343},[1338,3768,1348],{"class":1347},[1338,3770,1362],{"class":1343},[1338,3772,3773],{"class":1340,"line":137},[1338,3774,1848],{"class":1343},[1338,3776,3777,3779,3781],{"class":1340,"line":125},[1338,3778,1409],{"class":1343},[1338,3780,1348],{"class":1347},[1338,3782,1362],{"class":1343},[1216,3784,1496],{},[1329,3786,3788],{"className":1331,"code":3787,"language":1333,"meta":1334,"style":1334},"\u003Ctemplate id=\"childComponent\">\n  \u003Cdiv>我是childComponent！！\u003C\u002Fdiv>\n  \u003Cslot name=\"header\">\n    \u003Ch2>我是預設 header\u003C\u002Fh2>\n  \u003C\u002Fslot>\n  \u003Cslot name=\"body\">\n    \u003Ch2>我是預設 body\u003C\u002Fh2>\n  \u003C\u002Fslot>\n  \u003Cslot name=\"footer\">\n    \u003Ch2>我是預設 footer\u003C\u002Fh2>\n  \u003C\u002Fslot>\n\u003C\u002Ftemplate>\n",[1273,3789,3790,3804,3817,3831,3844,3852,3866,3879,3887,3901,3914,3922],{"__ignoreMap":1334},[1338,3791,3792,3794,3796,3798,3800,3802],{"class":1340,"line":340},[1338,3793,1344],{"class":1343},[1338,3795,1573],{"class":1347},[1338,3797,1352],{"class":1351},[1338,3799,1355],{"class":1343},[1338,3801,3354],{"class":1358},[1338,3803,1362],{"class":1343},[1338,3805,3806,3808,3810,3813,3815],{"class":1340,"line":329},[1338,3807,1367],{"class":1343},[1338,3809,1348],{"class":1347},[1338,3811,3812],{"class":1343},">我是childComponent！！\u003C\u002F",[1338,3814,1348],{"class":1347},[1338,3816,1362],{"class":1343},[1338,3818,3819,3821,3823,3825,3827,3829],{"class":1340,"line":318},[1338,3820,1367],{"class":1343},[1338,3822,1323],{"class":1347},[1338,3824,1865],{"class":1351},[1338,3826,1355],{"class":1343},[1338,3828,1870],{"class":1358},[1338,3830,1362],{"class":1343},[1338,3832,3833,3835,3837,3840,3842],{"class":1340,"line":134},[1338,3834,1377],{"class":1343},[1338,3836,1224],{"class":1347},[1338,3838,3839],{"class":1343},">我是預設 header\u003C\u002F",[1338,3841,1224],{"class":1347},[1338,3843,1362],{"class":1343},[1338,3845,3846,3848,3850],{"class":1340,"line":122},[1338,3847,1400],{"class":1343},[1338,3849,1323],{"class":1347},[1338,3851,1362],{"class":1343},[1338,3853,3854,3856,3858,3860,3862,3864],{"class":1340,"line":31},[1338,3855,1367],{"class":1343},[1338,3857,1323],{"class":1347},[1338,3859,1865],{"class":1351},[1338,3861,1355],{"class":1343},[1338,3863,3652],{"class":1358},[1338,3865,1362],{"class":1343},[1338,3867,3868,3870,3872,3875,3877],{"class":1340,"line":17},[1338,3869,1377],{"class":1343},[1338,3871,1224],{"class":1347},[1338,3873,3874],{"class":1343},">我是預設 body\u003C\u002F",[1338,3876,1224],{"class":1347},[1338,3878,1362],{"class":1343},[1338,3880,3881,3883,3885],{"class":1340,"line":110},[1338,3882,1400],{"class":1343},[1338,3884,1323],{"class":1347},[1338,3886,1362],{"class":1343},[1338,3888,3889,3891,3893,3895,3897,3899],{"class":1340,"line":76},[1338,3890,1367],{"class":1343},[1338,3892,1323],{"class":1347},[1338,3894,1865],{"class":1351},[1338,3896,1355],{"class":1343},[1338,3898,1949],{"class":1358},[1338,3900,1362],{"class":1343},[1338,3902,3903,3905,3907,3910,3912],{"class":1340,"line":247},[1338,3904,1377],{"class":1343},[1338,3906,1224],{"class":1347},[1338,3908,3909],{"class":1343},">我是預設 footer\u003C\u002F",[1338,3911,1224],{"class":1347},[1338,3913,1362],{"class":1343},[1338,3915,3916,3918,3920],{"class":1340,"line":236},[1338,3917,1400],{"class":1343},[1338,3919,1323],{"class":1347},[1338,3921,1362],{"class":1343},[1338,3923,3924,3926,3928],{"class":1340,"line":225},[1338,3925,1409],{"class":1343},[1338,3927,1573],{"class":1347},[1338,3929,1362],{"class":1343},[1259,3931,1251],{"id":1251},[1310,3933,3934,3948,3966,3975],{},[1231,3935,3936,3939,3940,3943,3944,3947],{},[1593,3937,3938],{},"slot 分成預設內容插槽及具名插槽","：",[1273,3941,3942],{},"預設內容插槽","可用來顯示父組件未傳入模板時的預設內容，",[1273,3945,3946],{},"具名插槽","則需要父組件可以精確地指定要插入的內容位置。",[1231,3949,3950,3939,3953,3956,3957,3959,3960,3962,3963,3965],{},[1593,3951,3952],{},"子組件插槽可以傳遞參數",[1273,3954,3955],{},"子組件","可以透過",[1273,3958,2440],{},"將其內部管理的參數回傳給父組件，從而使父組件能夠根據這些參數動態地改變顯示的模板內容。需要注意的是，",[1273,3961,3946],{},"與",[1273,3964,3942],{},"在傳遞變數的位置上有所不同，這樣可以確保父組件中的對應模板能接收到來自特定作用域的參數。",[1231,3967,3968,3971,3972,3974],{},[1593,3969,3970],{},"條件插槽","：子組件可以使用",[1273,3973,3244],{},"搭配條件語句來判斷插槽是否存在，從而根據情況顯示不同的內容。",[1231,3976,3977,3939,3979,3981,3982,3984],{},[1593,3978,1248],{},[1273,3980,1586],{},"可以綁定動態的插槽名稱，使得父組件能夠根據",[1273,3983,3493],{},"動態決定要渲染哪個插槽，達到更靈活的插槽內容控制。",[1259,3986,1254],{"id":1254},[1216,3988,3989,3991,3992,3994],{},[1273,3990,1323],{},"是我學習",[1273,3993,713],{},"的過程中，認為最難理解的部分。一度跳過這個部分，這次也好好的把整個內容跑過一次，我並不聰明，但我始終相信這過程中所有的練習都會變成我的養分。",[1216,3996,3997,3998,1645,4000,4002,4003,4005],{},"這次提供的練習是結合",[1273,3999,1275],{},[1273,4001,1323],{},"的應用(僅需調整模板上",[1273,4004,1323],{},"參數傳遞的部分)：",[1216,4007,1308],{},[1310,4009,4010,4017,4024],{},[1231,4011,4012,4013,4016],{},"父組件決定下拉式選單的變數值",[1273,4014,4015],{},"currentLang","傳遞給子組件",[1231,4018,4019,4020,4023],{},"子組件根據傳入的語言類型，使用",[1273,4021,4022],{},"slot 參數","回傳要顯示的內容",[1231,4025,4026,4027,4029],{},"父組件接收",[1273,4028,4022],{},"內容後，組成對應模板傳遞給子組件顯示",[1216,4031,1300,4032,4037,1553,4039],{},[1266,4033,4036],{"href":4034,"rel":4035},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FMWNKYYy",[1269],"Vue3 Options API props 搭配 slot 結合使用練習模板",[1551,4038],{},[1266,4040,4043],{"href":4041,"rel":4042},"https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FXWLbwRz",[1269],"Vue3 Options API props 搭配 slot 結合使用完成版本",[4045,4046,4047],"style",{},"html pre.shiki code .sYgZi, html code.shiki .sYgZi{--shiki-default:#24292E;--shiki-dark:#ADBAC7}html pre.shiki code .sIAta, html code.shiki .sIAta{--shiki-default:#22863A;--shiki-dark:#8DDB8C}html pre.shiki code .sMOND, html code.shiki .sMOND{--shiki-default:#6F42C1;--shiki-dark:#6CB6FF}html pre.shiki code .s-HuK, html code.shiki .s-HuK{--shiki-default:#032F62;--shiki-dark:#96D0FF}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 .s7YZ4, html code.shiki .s7YZ4{--shiki-default:#D73A49;--shiki-dark:#F47067}html pre.shiki code .sviXB, html code.shiki .sviXB{--shiki-default:#005CC5;--shiki-dark:#6CB6FF}html pre.shiki code .sPO5f, html code.shiki .sPO5f{--shiki-default:#6F42C1;--shiki-dark:#DCBDFB}",{"title":1334,"searchDepth":134,"depth":134,"links":4049},[4050],{"id":1226,"depth":329,"text":1226,"children":4051},[4052,4053,4054,4055,4056,4057,4058,4059],{"id":1261,"depth":318,"text":1233},{"id":1561,"depth":318,"text":1236},{"id":2431,"depth":318,"text":1239},{"id":3065,"depth":318,"text":1242},{"id":3238,"depth":318,"text":1245},{"id":1248,"depth":318,"text":1248},{"id":1251,"depth":318,"text":1251},{"id":1254,"depth":318,"text":1254},[11,713],"md",{},"---\ntitle: \"Vue 3 用實作帶你看過核心概念 - Day 22：v-slot 插槽使用\"\ndate: 2024-10-05 12:32:51\ntags:\n  - \"iThome 鐵人賽\"\n  - \"2024 鐵人賽\"\n  - \"Vue 3\"\n  - \"Options API\"\ncategories:\n  - \"iThome 鐵人賽\"\n  - \"Vue\"\ndescription: \"先前Day 18中提到父組件可以通過props將參數資料傳遞給子組件進行渲染，這樣可以有效地將資料處理與畫面渲染的工作分開。然而，當我們需要更加客製化的呈現內容，由父組件來控制子組件的部分顯示時，可以使用v-slot 指…\"\ncanonical: https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10363713\nseries:\n  name: \"2024 iThome 鐵人賽：Vue 3 初學者：用實作帶你看過核心概念\"\n  url: https:\u002F\u002Fithelp.ithome.com.tw\u002Fusers\u002F20116554\u002Fironman\u002F7800\n  day: 22\n---\n\n![文章背景圖](https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728100231\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002FDay22_v-slot_%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8_i3a0ig.png)\n\n## 目錄\n\n- slot 默認內容插槽\n- slot 具名插槽\n- 子組件插槽傳遞參數 - 作用域插槽\n- slot 與 props 設計方式比較 - 以切換卡片展示型態為例\n- 條件插槽 - $slots\n- 動態插槽\n- 總結\n- 小試身手\n\n* * *\n\n### slot 默認內容插槽\n\n先前[Day 18](https:\u002F\u002Fithelp.ithome.com.tw\u002Farticles\u002F10361721)中提到父組件可以通過`props`將參數資料傳遞給子組件進行渲染，這樣可以有效地將資料處理與畫面渲染的工作分開。然而，當我們需要更加客製化的呈現內容，由父組件來控制子組件的部分顯示時，可以使用`v-slot 指令`，將父組件的`模板`傳入給子組件，可以更靈活地呈現內容。\n\n![v-slot 指令基本應用區域官方範例圖](https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728100366\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002Fv-slot_%E6%8C%87%E4%BB%A4%E5%9F%BA%E6%9C%AC%E6%87%89%E7%94%A8%E5%8D%80%E5%9F%9F_cyylfp.png)\n\n以下透過一個父組件傳入`按鈕模板內容`給子組件的案例進行說明：\n\n👉 [Vue3 Options API slot 默認插槽內容實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FQWebeLj)\n\n流程說明：\n\n1. 父組件區域註冊子組件。\n2. 在子組件使用的標籤內放入父組件要傳入的模板內容。\n3. 子組件使用`slot`標籤接應父組件要傳入的模板內容。\n\n父組件 Vue Template：\n\n```html\n\u003Cdiv id=\"app\">\n  \u003Cfancy-button>\n    \u003Cbutton type=\"button\">{{ icon }} {{ buttonText }}\u003C\u002Fbutton>\n  \u003C\u002Ffancy-button>\n\u003C\u002Fdiv>\n```\n\n父組件 javascript：\n\n```javascript\nconst rootComponent = {\n  data() {\n    return {\n      buttonText: \"我是按鈕\",\n      icon: \"🐱\"\n    };\n  },\n  components: { FancyButton }\n};\n```\n\n子組件 Vue Template：\n\n```html\n\u003Cslot>\n  \u003Cp>目前暫時不服務！\u003C\u002Fp>\n\u003C\u002Fslot>\n```\n\n⭐ 子組件的`slot`標籤裡面可以放置預設值，當父組件未傳入模板內容的時候就會套用`\u003Cp>目前暫時不服務！\u003C\u002Fp>`。若父組件有傳入模板內容，則會忽略`slot`標籤裡面的內容。\n\n這邊附上父組件透過`props`傳入資料，子組件根據資料渲染的案例，讓大家感受一下兩者架構的差異，也可以思考一下再擴增功能上的方向。  \n👉 [Vue3 Options API 父組件傳遞 props 資料給子組件實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FJjgdqBd)\n\n### slot 具名插槽\n\n子組件使用的`slot`標籤可以設定不只一個，當使用複數個`slot`標籤的時候，父組件需要搭配具名插槽加上`template`標籤使用，才可以明確配對子組件中每個`slot`標籤要寫入對應的`template`是哪一個。\n\n在說明`v-slot`縮寫之前，幫大家複習一下之前常用指令的縮寫：\n\n- **v-bind**：縮寫型態`:`\n- **v-on**：縮寫型態`@`\n- **v-slot**：縮寫型態`#`\n\n![slot 具名插槽對應模板名稱官方範例圖](https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728100929\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002FSlot_%E5%85%B7%E5%90%8D%E6%8F%92%E6%A7%BD%E5%AE%98%E6%96%B9%E7%AF%84%E4%BE%8B%E5%9C%96_mm8ej2.png)\n\n以下透過子組件制定網頁版型，並由父組件根據不同區塊傳入模板內容案例說明：\n\n👉 [Vue3 Options API slot 具名插槽實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FKKOdPBG)\n\n流程說明：\n\n1. 子組件定出版型架構`header`、`main`及`footer`標籤區域。\n2. 父組件根據不同區域將對應該顯示的模板內容傳入。\n3. 透過`template name`與具名插槽名稱的對應，使彼此內容互不影響。\n\n父組件 Vue Template：\n\n```html\n\u003Cdiv id=\"app\">\n  \u003Cbase-layout>\n      \n    \u003Ctemplate v-slot:header>\n      \u003Ch2>這是 header\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n      \n    \u003Ctemplate #main>\n      \u003Ch2>這是 main\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n      \n    \u003Ctemplate #footer>\n      \u003Ch2>這是 footer\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n      \n  \u003C\u002Fbase-layout>\n\u003C\u002Fdiv>\n```\n\n子組件 Vue Template\n\n```html\n\u003Ctemplate id=\"child\">\n  \n  \u003Cheader>\n    \u003Cslot name=\"header\">\u003C\u002Fslot>\n  \u003C\u002Fheader>\n  \n  \u003Cmain>\n    \u003Cslot name=\"main\">\u003C\u002Fslot>\n  \u003C\u002Fmain>\n  \n  \u003Cfooter>\n    \u003Cslot name=\"footer\">\u003C\u002Fslot>\n  \u003C\u002Ffooter>\n  \n\u003C\u002Ftemplate>\n```\n\n* * *\n\n如果`slot`標籤未設置名稱，或者使用了預設名稱`default`，那麼所有無法對應到具名插槽的模板內容都會被放置在這個插槽中。可以將`slot`標籤想像成一個分類器，負責將父組件傳入的模板內容進行分類。\n\n延續上面的案例，我們試著透過範例更加了解：\n\n👉 [Vue3 Options API slot 未命名內容插槽與具名插槽的使用實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FjOgbqoQ)\n\n父組件 Vue Template：\n\n```html\n\u003Cdiv id=\"app\">\n  \u003Cbase-layout>\n\n    \u003Ctemplate v-slot:header>\n      \u003Ch2>這是 header\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #main>\n      \u003Ch2>這是 main\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #footer>\n      \u003Ch2>這是 footer\u003C\u002Fh2>\n    \u003C\u002Ftemplate>\n\n    \u003Cdiv #test1122334455>123\u003C\u002Fdiv>\n    \u003Cp>我是剩餘段落\u003C\u002Fp>\n\n  \u003C\u002Fbase-layout>\n\u003C\u002Fdiv>\n```\n\n子組件 Vue Template：\n\n```html\n\u003Ctemplate id=\"child\">\n\n  \u003Cheader>\n    \u003Cslot name=\"header\">\u003C\u002Fslot>\n  \u003C\u002Fheader>\n\n  \u003Cmain>\n    \u003Cslot name=\"main\">\u003C\u002Fslot>\n  \u003C\u002Fmain>\n\n  \u003Cfooter>\n    \u003Cslot name=\"footer\">\u003C\u002Fslot>\n  \u003C\u002Ffooter>\n\n  \u003Cdiv class=\"container\">\n    \u003Ch2>未命名插槽內容（預設插槽）\u003C\u002Fh2>\n    \u003Cslot>\u003C\u002Fslot>\n    \u003Ch2>具名的預設插槽內容（插槽名稱為 \"default\"）\u003C\u002Fh2>\n    \u003Cslot name=\"default\">\u003C\u002Fslot>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n在這裡可以看到，使用`#test1122334455`這個具名插槽，但在子組件中沒有對應的插槽，因此其內容會自動放置到未命名的`\u003Cslot>\u003C\u002Fslot>`或具名為`default`的插槽中。\n\n### 子組件插槽傳遞參數 - 作用域插槽\n\n一般來說，使用`slot`插槽時，父組件會傳遞模板內容給子組件來進行渲染。然而，在某些情況下，我們可能希望部分數據的控管在子組件中進行，並將這些參數回傳給父組件，使父組件能根據這些參數動態改變傳入的模板內容。這時，我們會使用`作用域插槽`，使子組件能將必要的參數提供給父組件使用。\n\n此外，根據是否使用具名插槽，插槽的使用方式會有所不同。以下將分別舉例，幫助大家更好地理解作用域插槽的應用。\n\n- **預設內容插槽傳遞參數的情形**：子組件通過插槽傳遞的所有內容，會被包裝在父組件使用 v-slot 定義的變數中（例如：`\u003Cmy-component v-slot=\"slotProps\">`）\n\n![slot 作用域插槽官方範例圖](https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728101208\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002Fslot_%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%8F%92%E6%A7%BD%E5%AE%98%E6%96%B9%E7%AF%84%E4%BE%8B%E5%9C%96_amxkod.png)\n\n👉 [Vue3 Options API 子組件默認內容插槽傳遞參數實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FyLmYVME)\n\n父組件 Vue Template：\n\n```html\n\u003Cdiv id=\"app\">\n  \u003Cmy-component v-slot=\"slotProps\">\n    \u003Cp>slotProps：{{ slotProps }}\u003C\u002Fp>\n    \u003Cp>text：{{ slotProps.text }}\u003C\u002Fp>\n    \u003Cp>count：{{ slotProps.count }}\u003C\u002Fp>\n  \u003C\u002Fmy-component>\n  \u003Cp>子組件外部範圍 slotProps：{{ slotProps }}\u003C\u002Fp>\n\u003C\u002Fdiv>\n```\n\n⭐ 子組件通過`v-slot`傳遞的`slotProps`參數只能在父組件中引用插槽內容的區域內使用，而不能在父組件的外部範圍使用。\n\n子組件 Vue Template：\n\n```html\n\u003Ctemplate id=\"child\">\n  \u003Cslot :text=\"text\" :count=\"count\">\u003C\u002Fslot>\n\u003C\u002Ftemplate>\n```\n\n- **具名插槽傳遞參數的情況**：子組件傳遞的參數必須對應到父組件中的具名`\u003Ctemplate>`，否則參數無法正確傳遞與使用。在傳遞參數時，具名插槽會將其對應於特定的`\u003Ctemplate>`，而且這些參數的作用域僅限於對應的`\u003Ctemplate>`標籤內。\n\n👉 [Vue3 Options API slot 具名插槽傳值實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FGRVpMav)\n\n父組件 Vue Template：\n\n```html\n\u003Cdiv id=\"app\">\n  \u003Cbase-layout>\n\n    \u003Ctemplate #header=\"slotProps\">\n      \u003Ch2>這是 header\u003C\u002Fh2>\n      \u003Cp>查看子組件傳入的參數值：{{ slotProps }}\u003C\u002Fp>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #main=\"slotProps\">\n      \u003Ch2>這是 main\u003C\u002Fh2>\n      \u003Cp>查看子組件傳入的參數值：{{ slotProps }}\u003C\u002Fp>\n    \u003C\u002Ftemplate>\n\n    \u003Ctemplate #footer=\"slotProps\">\n      \u003Ch2>這是 footer\u003C\u002Fh2>\n      \u003Cp>查看子組件傳入的參數值：{{ slotProps }}\u003C\u002Fp>\n    \u003C\u002Ftemplate>\n\n  \u003C\u002Fbase-layout>\n\u003C\u002Fdiv>\n```\n\n子組件 Vue Template：\n\n```html\n\u003Ctemplate id=\"child\">\n\n  \u003Cheader>\n    \u003Cslot name=\"header\" :headeMessage=\"headeMessage\">\u003C\u002Fslot>\n  \u003C\u002Fheader>\n\n  \u003Cmain>\n    \u003Cslot name=\"main\" :mainMessage=\"mainMessage\">\u003C\u002Fslot>\n  \u003C\u002Fmain>\n\n  \u003Cfooter>\n    \u003Cslot name=\"footer\" :footerMessage=\"footerMessage\">\u003C\u002Fslot>\n  \u003C\u002Ffooter>\n\n\u003C\u002Ftemplate>\n```\n\n在混合上面`預設內容插槽傳遞參數`及`具名插槽傳遞參數`的情況下，預設插槽的內容需要在父組件中使用具名為`default`的`\u003Ctemplate>`才能正常編譯和顯示。\n\n👉 [Vue3 Options API slot 具名插槽 + 默認內容插槽傳值實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FQWejajb)\n\n### slot 與 props 設計方式比較 - 以切換卡片展示型態為例\n\n這裡我們以一個常見的模板類型為例，演示如何將內容以「列表式」或「卡片式」兩種方式進行呈現。我們將以 momo 官方網站為範例，並對比使用`props`和`slot`的組件設計思維，展示不同的實現方式。\n\n【 momo 官網查詢 - 卡片式呈現搜尋結果 】  \n![momo 官網查詢 - 卡片式呈現搜尋結果](https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728101758\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002Fmomo_%E7%B6%B2%E9%A0%81%E5%8D%A1%E7%89%87%E5%BC%8F%E5%91%88%E7%8F%BE%E6%96%B9%E5%BC%8F_ehx9kw.png)\n\n【 momo 官網查詢 - 列表式呈現搜尋結果 】  \n![momo 官網查詢 - 列表式呈現搜尋結果](https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728101812\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002Fmomo_%E5%88%97%E8%A1%A8%E5%BC%8F%E5%91%88%E7%8F%BE%E6%96%B9%E5%BC%8F_dehtt5.png)\n\n- **props 的設計方式**：\n    - 父組件管控要呈現的類別(showType)\n    - 子組件負責取得查詢結果的 API 資料及根據父組件傳入的`showType props`決定呈現類型的組件。\n\n👉 [Vue3 Options API 不同排版方式 porps 參數設計方式實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FbGXVapG)  \n![props 設計卡片式及列表式資料傳遞結構圖](https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728101965\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002FProps_%E8%A8%AD%E8%A8%88%E5%8D%A1%E7%89%87%E5%BC%8F%E5%8F%8A%E5%88%97%E8%A1%A8%E5%BC%8F%E8%B3%87%E6%96%99%E5%82%B3%E9%81%9E%E7%B5%90%E6%A7%8B%E5%9C%96_kbqju2.png)\n\n- **slot 的設計方式**：\n    - 父組件負責控制顯示類型(showType)，並根據這個響應式變數決定渲染卡片式或列表式的組件模板內容。渲染所需的數據由子組件通過`slot`回傳的參數提供。\n    - 子組件負責取得查詢結果的 API 資料並透過`slot`將參數回傳給父組件使用。\n\n👉 [Vue3 Options API 不同排版方式 slot 參數設計方式實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FWNVQMej)  \n![slot 設計卡片式及列表式資料傳遞結構圖](https:\u002F\u002Fres.cloudinary.com\u002Fdseg0uwc9\u002Fimage\u002Fupload\u002Fv1728102064\u002F2024%20%E9%90%B5%E4%BA%BA%E8%B3%BD\u002FDay22%EF%BC%9Av-slot%20%E6%8F%92%E6%A7%BD%E4%BD%BF%E7%94%A8\u002FSlot_%E8%A8%AD%E8%A8%88%E5%8D%A1%E7%89%87%E5%BC%8F%E5%8F%8A%E5%88%97%E8%A1%A8%E5%BC%8F%E8%B3%87%E6%96%99%E5%82%B3%E9%81%9E%E7%B5%90%E6%A7%8B%E5%9C%96_gkms0q.png)\n\n兩種方式都能實現相同的功能，主要差異在於當顯示類型需要增加時(例如：新增 grid「四列網格」項目組件)，兩種設計方式的修改如下：\n\n1. **props 參數設計方式：**\n    - 在父組件的`showType`中新增第三種類型`grid`。\n    - 在子組件的邏輯判斷中加入新的`showType`選項`grid`。\n    - 子組件需新增「四列網格項目組件」以顯示相應的呈現方式。\n2. **slot 參數設計方式：**\n    - 在父組件的`showType`中新增第三種類型`grid`。\n    - 在父組件的邏輯判斷中加入新的`showType`選項`grid`。\n    - 父組件需新增「四列網格項目組件」以顯示對應的`模板內容`。\n\n**在這個場景案例中**，使用`props`設計方式時，如果需要新增顯示類型，父組件和子組件都需要進行相應的調整。而使用`slot`設計方式時，子組件的職責更加單一，只負責處理`API`資料的讀取，因此僅需在父組件中進行修改，讓維護和擴展更為方便。\n\n### 條件插槽 - $slots\n\n在以下示例中，子組件的模板可以使用`$slots`配合條件語句來判斷插槽是否存在。如果插槽存在，則顯示父組件傳入的模板內容；如果插槽不存在，則顯示一條提示信息：`\u003Ch2>父組件尚未提供 v-slot 綁定 content\u003C\u002Fh2>`。此外，也可以在`mounted`生命週期階段通過`console.log(this.$slots)`來查看當前傳入的具名插槽。\n\n👉 [Vue3 Options API slot 條件渲染實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FWNVrNjY)\n\n父組件 Vue Template：\n\n```html\n\u003Cdiv id=\"app\">\n  \u003Cchild-component>\n    \u003Ctemplate #content>\n      hello world vue !\n    \u003C\u002Ftemplate>\n  \u003C\u002Fchild-component>\n\u003C\u002Fdiv>\n```\n\n子組件 Vue Template：\n\n```html\n\u003Ctemplate id=\"childComponent\">\n  \u003Cdiv v-if=\"$slots.content\" class=\"content\">\n    \u003Ch2>\n      \u003Cslot name=\"content\">\u003C\u002Fslot>\n    \u003C\u002Fh2>\n  \u003C\u002Fdiv>\n  \u003Cdiv v-else class=\"default\">\n    \u003Ch2>父組件尚未提供 v-slot 綁定 content\u003C\u002Fh2>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n### 動態插槽\n\n`v-bind`可以用來設置動態屬性名稱，而`v-slot`同樣可以綁定動態插槽名稱，從而更靈活地控制插槽的內容。\n\n透過以下案例進行流程說明：\n\n1. 下拉式選單透過`v-model`綁定`blocktype`響應式變數\n2. 根據這個響應式變數可以動態改動要渲染的插槽對象\n\n👉 [Vue3 Options API slot 動態插槽實作連結](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FOJeVGOB)\n\n父組件 Vue Template：\n\n```html\n\u003Cdiv id=\"app\">\n    \n  \u003Cdiv class=\"input-group\">\n    \u003Clabel for=\"blockOption\">選擇 slot 插槽名稱：\u003C\u002Flabel>\n    \u003Cselect name=\"blockOption\" id=\"blockOption\" v-model=\"blocktype\">\n      \u003Coption disabled value=\"\">請選擇\u003C\u002Foption>\n      \u003Coption value=\"header\">header\u003C\u002Foption>\n      \u003Coption value=\"body\">body\u003C\u002Foption>\n      \u003Coption value=\"footer\">footer\u003C\u002Foption>\n    \u003C\u002Fselect>\n  \u003C\u002Fdiv>\n\n  \u003Cdiv class=\"content\">\n    \u003Cchild-component>\n      \u003Ctemplate #[blocktype]>\n        \u003Ch2>今天開心嗎!!!!!(動態小壞蛋) 顯示 blocktype：{{ blocktype }}\u003C\u002Fh2>\n      \u003C\u002Ftemplate>\n    \u003C\u002Fchild-component>\n  \u003C\u002Fdiv>\n  \n\u003C\u002Fdiv>\n```\n\n子組件 Vue Template：\n\n```html\n\u003Ctemplate id=\"childComponent\">\n  \u003Cdiv>我是childComponent！！\u003C\u002Fdiv>\n  \u003Cslot name=\"header\">\n    \u003Ch2>我是預設 header\u003C\u002Fh2>\n  \u003C\u002Fslot>\n  \u003Cslot name=\"body\">\n    \u003Ch2>我是預設 body\u003C\u002Fh2>\n  \u003C\u002Fslot>\n  \u003Cslot name=\"footer\">\n    \u003Ch2>我是預設 footer\u003C\u002Fh2>\n  \u003C\u002Fslot>\n\u003C\u002Ftemplate>\n```\n\n### 總結\n\n1. **slot 分成預設內容插槽及具名插槽**：`預設內容插槽`可用來顯示父組件未傳入模板時的預設內容，`具名插槽`則需要父組件可以精確地指定要插入的內容位置。\n2. **子組件插槽可以傳遞參數**：`子組件`可以透過`作用域插槽`將其內部管理的參數回傳給父組件，從而使父組件能夠根據這些參數動態地改變顯示的模板內容。需要注意的是，`具名插槽`與`預設內容插槽`在傳遞變數的位置上有所不同，這樣可以確保父組件中的對應模板能接收到來自特定作用域的參數。\n3. **條件插槽**：子組件可以使用`$slots`搭配條件語句來判斷插槽是否存在，從而根據情況顯示不同的內容。\n4. **動態插槽**：`v-slot`可以綁定動態的插槽名稱，使得父組件能夠根據`響應式變數`動態決定要渲染哪個插槽，達到更靈活的插槽內容控制。\n\n### 小試身手\n\n`slot`是我學習`Vue`的過程中，認為最難理解的部分。一度跳過這個部分，這次也好好的把整個內容跑過一次，我並不聰明，但我始終相信這過程中所有的練習都會變成我的養分。\n\n這次提供的練習是結合`props`及`slot`的應用(僅需調整模板上`slot`參數傳遞的部分)：\n\n流程說明：\n\n1. 父組件決定下拉式選單的變數值`currentLang`傳遞給子組件\n2. 子組件根據傳入的語言類型，使用`slot 參數`回傳要顯示的內容\n3. 父組件接收`slot 參數`內容後，組成對應模板傳遞給子組件顯示\n\n👉 [Vue3 Options API props 搭配 slot 結合使用練習模板](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FMWNKYYy)  \n👉 [Vue3 Options API props 搭配 slot 結合使用完成版本](https:\u002F\u002Fcodepen.io\u002Fgwhvusel-the-builder\u002Fpen\u002FXWLbwRz)\n",{"title":794,"description":795},{"name":717,"url":718,"day":113},{"loc":793,"images":4067,"lastmod":796},[4068,4069,4070,4071,4072,4073,4074,4075],{"loc":1222},{"loc":1290},{"loc":1620},{"loc":2462},{"loc":3083},{"loc":3092},{"loc":3125},{"loc":3159},"ithome-2024-day-22","2024-10-05-ithome-2024-day-22",[11,710,711,725],"L9wX-BlZve1Ow3lMidaPopdkmcBMaxfEBRU0RC8etkM",1792575202390]