---
# System prepended metadata

title: vue 元件
tags: [Vue]

---

# 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`