# vue 元件 ## 安裝外掛 ![](https://i.imgur.com/y9Aw83T.png) 這樣你註解這段話下面就可以變成html 不然會顯示這樣 ![](https://i.imgur.com/4kVpP2j.png) ## component 結構 * 資料 * 方法,監聽器 * 生命週期 在createApp後才能用 命名規則用 - 連接 裡面資料是分開的 ex ``` <template> <app-form></app-form> </template> import AppForm from './components/form.vue' export default { name: 'App', components:{ AppForm, } } ``` ### 母模板挖洞(未命名插槽) **母模板** 寫法一樣,但把要得放在母模板裡面,注意要用元件標籤包起來(app-form) ``` <template> <app-form> <form action=""> <div class="help"> <p>test to create for template</p> </div> <div class="fields"> <input type="text" placeholder="email" /> <input type="text" placeholder="username" /> <input type="password" placeholder="password" /> </div> <div class="buttons"> <button>按我</button> </div> </form> </app-form> </template> ``` **子模板** slot 投幣口,代表他是挖洞的 如果要預設`<slot>中間寫預設</slot>` ``` <template> <slot></slot> </template> ``` ### props https://www.youtube.com/watch?v=bgpkvMtMUvM 用來溝通用 子層可以定義資料跟父層溝通用 ![](https://i.imgur.com/phcZ3ZC.png) 不要prop定義名字 在data又定義一個一樣的 ### 命名slot(正常使用) **可以直接{{}}印出來資料 但如果要在子模板做計算跟method要更動一樣要用props** **子** ``` <form action=""> <div class="help"> <slot name="help"></slot> </div> <div class="fields"> <slot name="fields"></slot> </div> <div class="buttons"> <slot name="buttons"></slot> </div> </form> ``` **母** ``` <template> <app-form> <template v-slot:help> <p>test to create for template</p> </template> <template v-slot:fields> <input type="text" placeholder="email" /> <input type="text" placeholder="username" /> <input type="password" placeholder="password" /> </template> <template v-slot:buttons> <button>按我</button> </template> </app-form> </template> <script> import AppForm from './components/form.vue' export default { name: 'App', components:{ AppForm, } } </script> ``` ### 關於元件 子繼承父 跟挖洞的總結(必看) 跟laravel不一樣在母為主 挖洞跟拉進來都在子,沒有繼承的概念。 用**laravel**舉例 **include的用法** 子模板寫好 母模板直接import然後註冊 ``` components:{ AppForm, } ``` 註冊好直接按照命名在template用出來 `<app-form></app-form>` **挖洞(把一個子模板重複利用)(命名slot)** 在子模板寫好然後在要填洞的地方 `<slot name="help"></slot>` name是要給填洞的像@yeild 主模板一樣註冊拉進來 `<app-form></app-form>` 在這範圍裡面找要填的地方輸入 `<template v-slot:fields> 這邊包的東西會被拉到子模板合在一起 </template>` **注意兩點** v-slot是指令要記得v v-slot:fields 後面fields這個是名字,**但是**沒有雙引號,記住沒有單雙引號 ### 動態元件 利用data資料去切換要顯示哪一個元件 母 ``` <template> <select v-model="componentName"> <option value="Home">Home</option> <option value="About">About</option> </select> <component :is="componentName"></component> </template> <script> import Home from './components/Home.vue' import About from './components/About.vue' export default { name: 'App', components:{ About, Home, }, data(){ return{ componentName:"Home", }; } } </script> ``` 子1 ``` <template> <p>home</p> </template> ``` 子2 ``` <template> <p>about</p> </template> ``` 要顯示哪個用 `<component :is="componentName"></component>` is去判斷,裡面的data就自己看要怎變化 **注意** 切換元件會把元件刪除 可用unmounted生命週期看 ![](https://i.imgur.com/mF84uOK.png) 所以裡面的資料或甚麼都會不見 如果不要讓她刪除 要存留在記憶體內 用 `<keep-alive></keep-alive>` ![](https://i.imgur.com/KrpFn6E.png) ### props(data for child) data放在root 同層的兄弟不能把資料交換 只能父給子 叫做props ![](https://i.imgur.com/EIfforS.png) data如何傳給子 **father** 建立好data然後把資料的key用在 要放的原件上面 用屬性傳入,傳入屬性自訂,最好跟data的key一樣,記得因為是綁定v-bind, 所以要加:。 ![](https://i.imgur.com/Qx4PlbV.png) **除了data也能傳function** **child** props接資料用array 然後就能模板印出 ![](https://i.imgur.com/t0aW49n.png) ### emit(子傳父) 如果要改值data的才要用$emit事件 不然用computed就好 (如果你要顯示data *2 顯示東西就計算就好 ,要改data才要用emit) 第一步 子層有事件才會改資料 在事件上面放涵式,不能直接放data去改會不給改,不能再子層直接改動data 第二步 有事件在下面寫,然後用this(指向proxy)然後取它裡面的$emit去發送事件給父層,第一個參數是名稱(用-連接),第二參數是數值(可傳可不傳)(不傳的話在父層的涵式內也可,但推薦在來源處寫) ![](https://i.imgur.com/cnaWiBE.png) 第三部 父層 接受子層來的事件 名稱就跟你發送事件名稱一樣 接收值在下面 **重點** 值不是從function來 是從事件來,所以上面@事件涵式不用加參數 ![](https://i.imgur.com/95SEAkc.png) 第四部 優化 做完以上會出現這個 無關的事件觸發 ![](https://i.imgur.com/7OzoGfF.png) 解決方法 讓他按照規局走 加入`emits:[]`, 符合規範,方便知道你有把事件傳出去 ![](https://i.imgur.com/yuG4WoN.png) 父層 可直接用event抓 ![](https://i.imgur.com/s0FsjXg.png) 子層觸發 ![](https://i.imgur.com/vf5oYKd.png) ### 全域註冊 ### local註冊元件 範例 ![](https://i.imgur.com/elihAjA.png) Greeing ![](https://i.imgur.com/dkGQrc4.png) ### style 也分為全球跟本地 建議用本地 scope(注意他是依賴在postcss) https://vue-loader.vuejs.org/zh/guide/scoped-css.html#%E6%B7%B7%E7%94%A8%E6%9C%AC%E5%9C%B0%E5%92%8C%E5%85%A8%E5%B1%80%E6%A0%B7%E5%BC%8F 如果要用sass ![](https://i.imgur.com/tDr3aBc.png) https://cli.vuejs.org/zh/guide/css.html 如果遇到 this.getOptions is not a function 降版本就好 https://stackoverflow.com/questions/66082397/typeerror-this-getoptions-is-not-a-function ### 元件驗證 https://v3.cn.vuejs.org/guide/component-props.html#%E4%BC%A0%E5%85%A5%E4%B8%80%E4%B8%AA%E5%B8%83%E5%B0%94%E5%80%BC **如果type是要多 要[]表示** 資料一定在父層,所以子層的props改成 ![](https://i.imgur.com/QOrjGx7.png) 這樣的意思是 當父層使用到他一定要有用到這個資料 像下面的:age一樣,如果少`:age="age"`就會錯,他是必要的 `<user :age="age" @age-change="udateAge"></user>` **預設** 當然你可以不要驗證,給他預設也可以,當心你type如果是array,預設也要array。 **自訂驗證規則** ![](https://i.imgur.com/nUV49b8.png) 是涵式 然後要return 提醒他是在created之前,所以計算跟method都抓不到,要小心 ![](https://i.imgur.com/IX6D7XH.png) ### 上面都是even的 也能用callback方法建立,父曾把函式帶給子層,但缺點 這邊會看不到事件傳送 ![](https://i.imgur.com/4nlmS2I.png) ###### tags: `Vue`