---
# System prepended metadata

title: '1100304'
tags: [share]

---

---
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)
![](https://i.imgur.com/b3ZWD1d.png)
    * ***GAD0104門禁異常清單 // 表示 API 文件名稱***
    * ***gateLog // 表示優先使用此英文命名***
* [API：藍底表示一支 API](https://drive.google.com/drive/folders/1NIF1ChLxH1lY7hm8XvEfJsRpaYS8ymCF)
![](https://i.imgur.com/Z5Orinv.png)


### 專案建立流程：目標是畫出畫面，並建立基礎功能 18:43
1. 開 UI 介面了解有哪些功能、畫面。
2. 至 EXCEL 確認文件格式、API。
3. 建 DTO（models資料夾）：讓編輯器認得懂我要的文件格式。
    ![](https://i.imgur.com/hV7OvGX.png)
    ![](https://i.imgur.com/9JxQAWq.png)

* **回傳**（`I.....`開頭，`Res`結尾）
    * 使用`interface`建立，因為回傳值由他方回傳，通常不會被修改或`new()`。
    * 如果`interface`的資料是列表`[]`，就要先`interface`列表型別，再`interface`列表內各項資料的型別（命名規則：列表`List`、列表項目`Item`）。
* **傳入**（`ReqDTO`結尾）
    * 表示此`Class`會被當成參數打出去。
    * API 由我方所建立的，所以用`class`建（因為會`new()`）。
* 一個`Res`就會對應一個`ReqDTO`。
* 實例
    **EXCEL**
    ![](https://i.imgur.com/g0kPCTV.png)
    ![](https://i.imgur.com/x5LZ4JA.png)
    **程式碼**
    ```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
![](https://i.imgur.com/dvP0IDt.png)
* 程式碼
    ```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資料夾，新增的組件資料夾名稱參考**系統作業權限角色**）。
![](https://i.imgur.com/dZkPFcE.png)
![](https://i.imgur.com/M6NSVBw.png)
* 組件畫面可以直接複製，但是內文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 = () => () => .....
* 它是一個函式。
* 它用來建立物件。
* 它像工廠一樣，生產出來的函式都是標準件（擁有同樣的屬性）