---
tags: share
disqus: hackmd
---
# 1100304
Vue 元件樹
---
* Nuxt 除了把vue檔案變成 router,也會有切換組件的功能(可從 vuetool 的 nuxt 組件下看出利用索引值切換組件)
* template 就是元件模板( angular 也是將模板內的標籤視為字串)
* 利用 `{{}}` 將字串轉成 `dom`
* `:bind` 綁的屬性值為動態屬性(在編輯器上通常跟變數同個顏色),父組件傳值給子組件時用。
Vue
---
* 在vue中父組件權限比較高
* 父組件傳屬性給子組件時是同js原生傳值原理(傳記憶體位置),因此子組件不可以主動改父組件資料(動態綁定屬性get跟set會被vue綁架),只能通知父組件要改資料,由父組件建立處理方式去修改
* v-for的`:key`屬性要寫:有`:key`之後,同一個key值的template不用重新渲染,可以優化效能。
元件詳解
---
* 一般寫法computed到class寫法會變成get
* 父子組件如何溝通
`$emit、$on`都在Vue Class裡面
`this.$on`等於@(就是監聽事件)
```javascript=
// 子組件
onClick(item){
this.$emit('onClick',item)
this.$on('onClick',()=>{
})
}
// 父組件模板
<Child @onClick="doSomething"><>
// 父組件方法
doSomething(item){
// item 是子組件傳過來的值
}
```
關於bus
---
* 叫第三方(bus)去做通知,就跳過中間子組件傳值到任何地方。
* bus也是一個Vue Class
* 靈活度高但不常用(因為不好維護,可能發生不確定bus的事件,有幾個組件註冊),通常用Vuex
Vuex
---
* vuex是單向流
* 轉資料中心,等同bus,只有兩種功能:拿資料取資料。
* `mutation` 是處理資料的地方
* `state` 是放資料的地方
* 使用時機:資料共用時,如登入狀態、購物車清單(可以想像原本存放在 local storage 的東西現在存放在Vuex,只要定義好 action 跟 mutation,再利用state就可以取得資料,就不用把資料傳來傳去)
```javascript=
export default class DefaultLayout extends Vue {
@State(state => state.app.sidebarTabMap) sidebarTabMap!: IMap<IRoute[]>;
// or
@State(state => state.app.sidebarTabMap) // 利用裝飾器State取得app中sidebarTabMap的資料
sidebarTabMap!: IMap<IRoute[]>; // 此處的sidebarTabMap是代表此Class的屬性,可自定義
// 裝飾器要緊鄰要使用的元素,可以換行但不可以空行
}
```
專案
---
* store資料夾下存的是vuex state裡的模組
* `import { Vue, Component, State, Watch } from "nuxt-property-decorator";` 引入裝飾器
* 公用函式放在utils資料夾下
### EXCEL
* [系統權限作業角色](https://docs.google.com/spreadsheets/d/1vSMY4rcmpTLdiYczlPGDT4E26qZGA-VAJailjqJLKx8/edit#gid=1839445946)

* ***GAD0104門禁異常清單 // 表示 API 文件名稱***
* ***gateLog // 表示優先使用此英文命名***
* [API:藍底表示一支 API](https://drive.google.com/drive/folders/1NIF1ChLxH1lY7hm8XvEfJsRpaYS8ymCF)

### 專案建立流程:目標是畫出畫面,並建立基礎功能 18:43
1. 開 UI 介面了解有哪些功能、畫面。
2. 至 EXCEL 確認文件格式、API。
3. 建 DTO(models資料夾):讓編輯器認得懂我要的文件格式。


* **回傳**(`I.....`開頭,`Res`結尾)
* 使用`interface`建立,因為回傳值由他方回傳,通常不會被修改或`new()`。
* 如果`interface`的資料是列表`[]`,就要先`interface`列表型別,再`interface`列表內各項資料的型別(命名規則:列表`List`、列表項目`Item`)。
* **傳入**(`ReqDTO`結尾)
* 表示此`Class`會被當成參數打出去。
* API 由我方所建立的,所以用`class`建(因為會`new()`)。
* 一個`Res`就會對應一個`ReqDTO`。
* 實例
**EXCEL**


**程式碼**
```javascript=
// ======= STEP =========
// 1.Class 定義傳入值型別:到 API excel 複製資料型別(提醒:編輯器內建型別開頭小寫,自定義 Class 型別開頭大寫)
// 2.資料定義型別、給初始值。
// 3.建立標題註解(打/**再按enter) - 第9行查詢系統登入記錄
// 4.interface 定義回傳值型別 (重複上1.2.3步驟):code、msg、data 為泛型因此不用定義在 interface 內,且interface 只要給型別不用給初始值
/**
* 查詢系統登入記錄
*/
export class SYS0401LoginListReqDTO {
beginDate: string = ""; // 起始日期
endDate: string = ""; // 終止日期
accountId: string = ""; // 登入者帳號
result: string = ""; // 登入結果
ip: string = ""; // 登入IP
}
export interface ISYS0401LoginListRes {
loginLogList: ISYS0401LoginItem[]; // 登入記錄列表
}
export interface ISYS0401LoginItem {
logDT: string; // 登入時間
accountId: string; // 登入者帳號
ip: string; // 登入者IP
result: string; // 登入結果
remark: string; // 備註
}
/**
* 匯出登入記錄
*/
export class SYS0401ExportLogReq {
beginDate: string = ""; // 起始日期
endDate: string = ""; // 終止日期
accountId: string = ""; // 登入者帳號
result: string = ""; // 登入結果
ip: string = ""; // 登入IP
}
export interface ISYS0401ExportLogRes {
fieldId: number; // 檔案ID
fieldUrl: string; // 檔案URL
}
// ======= 快捷鍵 ==========
ctrl+alt+上下:同時多個游標
ctrl+end:飛到該行最後面
ctrl+左右:一次跳一組字
選取單字後+ctrl+D:向下選取同樣名稱的單字
shift+alt+上下:複製
```
4. 建 API(api 資料夾)
* EXCEL

* 程式碼
```javascript=
// ***** 固定引用 axios 套件,API統一的出入口
import { $axios } from "@/utils/pluginsInstance";
import {
SYS0401ExportLogReq,
SYS0401LoginListReqDTO
} from "~/models/SYS/SYS04/loginLog/SYS0401DTO";
// ***** api路徑位置("sys0401/list")就是excel的項目代號(如上圖)
// ***** getLoginLogList 為下方定義的方法
export const API = {
getLoginLogList: "sys0401/list", // 查詢系統登入記錄
exportLoginLogList: "sys0401/export" // 匯出登入記錄
};
// ***** params 代表參數,:後接型別
// ***** $axios.$post(參數1:打API的位置,參數2:資料)
export const getLoginLogList = (params: SYS0401LoginListReqDTO) =>
$axios.$post(API.getLoginLogList, params);
export const exportLoginLogList = (params: SYS0401ExportLogReq) =>
$axios.$post(API.exportLoginLogList, params);
```
5. 畫畫面(pages資料夾)
* 查詢框及 table 會是分開的組件。
* 建組件(components資料夾,新增的組件資料夾名稱參考**系統作業權限角色**)。


* 組件畫面可以直接複製,但是內文class名稱記得修改
* 程式碼
```javascript=
// 1.修改元件名稱
// 2.按照UI畫面分組件
// 3.到components資料夾建立組件檔案 檔案如果用複製的要記得改內文class名稱
// 4.回到page掛載組件
// 先 import
import 組件名稱 from 'component資料夾位置的組件檔案'
// 註冊元件(如果名稱取的一樣就只要寫一次)
@Component({component:{元件名稱:元件屬性值})
// 5.修改template v-model等v開頭的屬性要優先先在前面
// 6.到頁面測試元件是否運作正常(值有沒有傳入DTO)
// 比對時要寫3個等於===
// 取得API資料用then,接後端丟出來的值 catch處理失敗(如後端取不到資料)
.then((放參數)=>{
})
.catch(()=>{
});``
// ***** 板手開頭就是api建的方法
<script lang="ts">
// ***** 來源是utils或model/common,表示公用函式或物件
import { Vue, Component, Prop, Watch } from "nuxt-property-decorator";
import { updateFormByTableOption } from "~/utils/form";
import { ITableOptions } from "~/models/common/PagesDTO";
import { SYS0401LoginListReqDTO } from "~/models/SYS/SYS04/loginLog/SYS0401DTO";
import { vRequired } from "~/utils/validate";
// ***** @Component(components: {}) 用來引入 import 進來的組件
@Component({ components: {} })
export default class SYS0401SearchForm extends Vue {
valid = false;
// ****** searchFrom 為我們自己建的 DTO(傳入值資料格式)
searchForm = new SYS0401LoginListReqDTO();
// ***** 驗證表單固定寫法
rules = {
beginDate: [vRequired("請輸入日期")],
endDate: [vRequired("請輸入日期")]
};
// ****** resetFrom 重設資料:讓 searchForm 初始化
resetForm() {
this.searchForm = new SYS0401LoginListReqDTO();
}
// ****** searchFrom 查詢資料
// ****** $refs:父元件取得子元件資料的方法(避免function傳參數):利用this.$refs(子組件標籤要綁屬性 ref='searchForm')
// ***** .validate()為 vuetify 給 v-form 的方法
search() {
(<any>this.$refs.searchForm).validate();
if (this.valid) {
this.$emit("onSearch", true);
} else {
this.$warningMsg();
}
}
updateSearchForm(options: ITableOptions) {
updateFormByTableOption(options, this.searchForm);
}
}
</script>
```
Vuetify
---
* 優先使用vuetify api
* v-card:卡片
在畫面上製作形狀通常都會使用 v-card,其下還有很多子組件
* v-card-action:按鈕欄位
* v-card-text:內容
* v-card-subtitle
* v-card-title:標題
* v-form:表格
* 屬性 API
* counter:input 輸入字數限制,預設25(要搭配欄位綁v-model才會生效)
* disabled:輸入框禁用(如果要從Vue定義的屬性值判斷,就以:disabled="屬性名字"作綁定)
* StatusSelect:定義狀態
* dense:小尺寸
JS
---
js 傳值的方法:指到同一個記憶體位置(傳址)
```javascript=
const obj1 ={ // 複雜型別
a1:1, // 簡單型別
a2:{ // 複雜型別
a3:1 // 簡單型別
}
}
obj2 = 0bj1;
obj2.a1=2;
obj1 // 2;
```
淺拷貝、深拷貝
---
待補
關於程式命名
---
_aaa:表示私有屬性(做不可告人的事情)
Sourcetree
---
* 先 Fetch 再 Merge
* 要併到dev跟 Karta 說
函式工廠
---
a = () => () => .....
* 它是一個函式。
* 它用來建立物件。
* 它像工廠一樣,生產出來的函式都是標準件(擁有同樣的屬性)