---
# System prepended metadata

title: 前端學習札記

---

# 前端學習札記 #

> 此篇文章為個人的學習小小紀錄，主要是方便複習及紀錄成長
> 如果有錯誤，或有想要討論的內容都十分歡迎找我討論
> https://github.com/xdkillyou
---
### 目錄 ###

* Web
* HTML
* CSS
* 網頁運作
* JS & JQ
* 前端框架
* Vue
* API管理

---
## Web ##

Web，即是我們正在看的網頁，呈現、互動、動畫、功能，網頁的演進到現在，不再只是純文字或資料取向，更多的是操作與使用者的互動。
> 網頁發展: http://www.evolutionoftheweb.com/?hl=zh-tw
#### 網頁的組成分成三大項目 ####

* 骨架 ( HTML )
* 皮膚 ( CSS )
* 大腦 ( Javascript )
> 有了骨架才能抹上皮膚，有了身體才能帶入大腦

## HTML ##

HTML並不是程式語言，而是一種==標記語言==，又稱做超文本標記語言(**H**yper**T**ext **M**arkup **L**anguage)，HTML透過tag來表達語意，而網頁由一個個的元素(DOM)所組成，最終形成一個網頁架構，來表達網頁的呈現內容
> 人(網頁)由骨頭(DOM)所組成，骨頭有不同種類及形式(tag的語意)，分別代表不同部位(作用)

網頁必須透過HTML這種語言來表達文字及畫面的語意

>將網頁語意話最重要的是要讓機器也能讀懂網頁的內容，優化SEO，也可以讓開發者更快理解網站結構

>介紹SEO(缺)

#### tag認識及介紹

```htmlmixed=
 <tag> ... </tag>
 <!-- tag透過<>包裹起來，有起始標籤及結束標籤 -->
 <!-- 組合成一個元素(DOM element) -->
```
當然也是有單個標籤的，稱為**空元素**
```htmlmixed
 <img> html寫法
 <img/> XHTML寫法
 <img /> XHTML兼容html寫法 -> 最嚴謹的寫法
 而html5兼容XHTML
```
> 空元素有哪些: https://developer.mozilla.org/zh-TW/docs/Glossary/Empty_element

>之後再補充XHTML、XML(缺)

可以為巢狀結構
```htmlmixed
 <div>
  <p>我是內文</p>
 </div>
```

#### HTML的架構

```htmlmixed=
<!DOCTYPE html>  <!-- 此處為文件類型聲明 -->
<html lang="en">
<head> <!-----------此範圍為表頭---------------->
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head> <!------------------------------------>
<body> <!-----------此範圍為畫面呈現------------->
  <h1>大標題</h1>
  <p>內文</p>  
</body> <!------------------------------------>
</html>
```
* 文件類型聲明
聲明html的類型、版本，但已經是時代的眼淚，只需要形式上的引入即可
* `<html></html>`
包住頁面的所有內容，又被稱為根元素
* `<head></head>`
表頭拿來宣告、引入資源及連結等，內容不會顯示在網頁上
`<title>Document</title>`指的是page title，可以在開啟瀏覽頁後的分頁上看到
![](https://i.imgur.com/T4PoRO3.png)
>表頭中除了導入資源，還有就是拿來宣吿meta，提高網頁SEO及網站的介紹、描述，在這邊先大致知道即可
>
* `<body></body>`
這邊就是網頁呈現的畫面及內容

#### tag的屬性

```htmlmixed=
<p class="name">contain<p>
<!-- class屬性 -->
<p id="name">contain<p>
<!-- id屬性 -->
```
>"name"皆為自定義，id與class屬性的差異為
>id 只能為獨一無二
>class 能夠有多個
>id的權重高於class

其餘的Tag及Attribute介紹皆可以到[W3Schools](https://www.w3schools.com/html/default.asp)及[MDN](https://developer.mozilla.org/en-US/docs/Web/HTML)查找

#### Atteribute

>補

## CSS ##



## 網頁運作 ##
## JS & JQ ##
## 前端框架 ##
## Vue ##

Vue為前端(2020)三大框架(Angular，React，Vue)之一，主打==輕量好入門==，官方已經宣布Vue3.0 release版本，這邊還先以2.x為主

### 特性

* 類MVVM
![](https://i.imgur.com/FFkgQXr.png)
>在這邊引用別人的圖來說明，為什麼會說是類MVVM，因為尤雨溪大大是參考MVVM架構做的
>>**View**是我們看到的前端畫面
>>**Model**是我們的資料(data)
>>**ViewModel**是連繫View & Model的橋樑
>
>這也是Vue資料驅動畫面的關鍵，透過綁定將View及Model繫在一起

* 漸進式
>漸進式意味著你可以只選用部分Vue提供的功能(vue-cli/vur-router/vuex...等)來實作專案，挑選你所需的功能來用即可，而不用將一大包資源一次引入

>除了上面說明以外，Vue其實也可以與其他如JQuery & JavaScript合併著使用，但在使用上要格外注意，一個功能就用單一一種語法寫就好(this指向問題)

* 聲明式渲染
> **聲明式渲染 V.S 命令式渲染**
> 白話一點的說明他們兩個之間的差異的話，以商店來舉例
> >聲明式 : 這枝筆我要調整價錢(老闆語氣)，服務生就自己乖乖的把架上的價錢改掉(好員工 :100:
> 
> >命令式 : 這枝筆我要調整價錢，你!就你這個服務生，你現在準備好調整後的價錢，然後去找筆這個商品在哪個架上，接著價錢換掉，換成調整後的價錢(順道一提JQuery就是命令式)
>
>感受到其中的差異了嗎? Vue更動畫面只需要==修改資料==，不像JQuery要去瘋狂的==操作DOM==

這邊不是一昧的指JQuery不好，JQuery非常方便，還是要看專案來考慮自己需要什麼，但BootStrap5要砍掉與JQuery的相依關係，不知道會不會使JQuery用戶變少就是了

> Object.defineProperty()



### 生命週期、生命週期鉤子(Hook)

![](https://i.imgur.com/PhUR9Zt.jpg)

Vue的生命週期，即意味著從他出生(建立instance)到他死掉(destroyed)的過程，生命週期主要還以Hook為主，我們可以透過Hook在各個階段去執行我們想要的事

>這邊分成**創建階段**與**運行階段**，顧名思義，創建階段只會跑過一次，而運行階段會一直執行直到destroyed

> el(element) - el為Vue實例掛載範圍(DOM element)

#### Hook

--- 創建階段 ---

* beforeCreate: 初始化instance，el尚未建立，options尚未初始化(methods、computed..等)，data尚未被定義，DOM尚未生成
* created: el尚未建立，options & data定義完成，可以調用data資料與options定義好的方法，DOM尚未生成，尚未綁定至el
>這邊開始已經可以開始調用宣告在data中的資料及options的方法，意謂這邊就可以開始處理資料

* beforeMount: el掛載前，DOM已經載入完成，樣板語法尚未被賦予值 
>這階段的網頁呈現，DOM已經被載入了，但樣板語法尚未被賦予值，所以有透過 {{ data }} 綁定在DOM元素裡的data，還尚未被放值進去，都還是文字的呈現

* mounted: el建立完成並掛載成功，樣板語法被賦予值
>創建階段的最後一個Hook了，創建階段結束

--- 運行階段 ---

* beforeUpdate: 當綁定的資料改變時，畫面要被重新re-render前觸發
>值得注意的事，當我綁定的資料沒放到畫面時，畫面不會被重新re-render
>補充: Vue還有個特性就是會複用相同的DOM元素，以便加速DOM的繪製(**[Virtual DOM](https://medium.com/%E6%89%8B%E5%AF%AB%E7%AD%86%E8%A8%98/build-a-simple-virtual-dom-5cf12ccf379f)**)

* updated: 資料改變後且畫面已經被re-render完畢後觸發

--- 銷毀階段 ---
>製作SPA時，其實在切換router時，當下資料的綁定就會被destroy掉，如果要主動destroy掉要透過指令```vm.$destroy```，但不建議主動去destroy，如官方文件說明
![](https://i.imgur.com/L9Hw2Dn.png)

* beforeDestroy: Vue instance銷毀前，此階段Vue instance中data還有options還可以被使用
>**!重要!在這個階段，可以拿來remove掉純JavaScript的監聽事件**

* destroyed: Vue instance已經被銷毀完畢，與資料的綁定被銷毀
>透過測試發現，如果destroy後還停留在當下的頁面，已經渲染在DOM上的畫面依舊會保留，且事件監聽依舊會存在，事件依舊會運行，資料依舊會變化，只是畫面與資料的綁定(ViewModel?)會銷毀，不會re-render

> codepen: https://codepen.io/xdcodetxt/pen/dyMRWLK?editors=1011


### 模板語法

#### v-on 綁定事件

```htmlmixed=
<button v-on:event="functionName">Click</button>
```
>v-on:觸發事件 = "執行函式"

```htmlmixed=
<button @event="functionName">Click</button>
<!-- 可以將v-on縮寫成@ -->
```
事件修飾符可以參考: https://vuejs.org/v2/api/#v-on


#### v-for 迴圈

<ul>
    <li>pen</li>
    <li>book</li>
</ul>

```htmlmixed=
<ul>
    <li v-for="item in Array" :key="item.id">{{ item.name }}</li>
</ul>
```
>

<ul>
    <li>0. pen</li>
    <li>1. book</li>
</ul>

```htmlmixed=
<ul>
    <li v-for="(item,index) in Array" :key="item.id">
        {{ index }}: {{ item.name }}
    </li>
</ul>
```

```javascript=
data: {
    Array: [
        {
            name: "pen",
            id: 1
        },
        {
            name: "book",
            id: 2
        }
    ]
}
```

>v-for中的==key==功用是什麼??
>要先了解Virtual DOM的目的，盡可能減少DOM的變化，提升效能，所以Vue會有複用DOM的特性
>key的目的就是用來判斷此項目是否要re-render，所以key不可重複，因此key的值盡量不要使用index，否則在陣列變化時，效能變差(如果是在陣列最前面插入內容，陣列中的index全會變化，變成全部re-render)
>參考說明: https://juejin.im/post/6844903577215827982


#### v-bind 綁定屬性(Attribute)

```htmlmixed=
<p v-bind:title="cool">mouse moves over on me</p>
```

```htmlmixed=
<p :title="cool">mouse moves over on me</p>
<!-- 可以將v-bind縮寫成: -->
```

> prop就是利用v-bind丟資料

#### v-model 雙向綁定

View變化後透過ViewModel監聽與Model做雙向溝通(主要用在input/select/textarea..等等form element上)
[form element參考](https://www.w3schools.com/html/html_form_elements.asp)

<form>
    <input type="text">
</form>

```htmlmixed=
<input v-model="account" />
```

```javascript=
data: {
    account: ""
}
```
v-model比較像是語法糖，原理其實就是v-bind綁value屬性 & v-on監聽變化後把資料帶回去
```htmlmixed=
<input v-bind:value="data" v-on:input="data = $event.target.value" />
```


修飾符可以參考: https://vuejs.org/v2/api/#v-model


#### v-if / v-else-if / v-else 畫面渲染

判斷是否渲染畫面，可以寫表達式

```htmlmixed=
<div v-if="boolean">
    <p>contant</p>
</div>
<div v-else-if="boolean">
    <p>contant</p>
</div>
<div v-else>
    <p>contant</p>
</div>
```

```htmlmixed=
<div v-if="text === 'cool'">
    <p>contant</p>
</div>
<div v-else>
    <p>contant</p>
</div>
```

>v-else-if & v-else必須緊接著v-if後面使用(同一層)，否則會跳出錯誤


#### v-show 畫面渲染

判斷是否渲染畫面，可以寫表達式
```htmlmixed=
<div v-show="boolean">
    <p>contant</p>
</div>
```

```htmlmixed=
<div v-show="text === 'cool'">
    <p>contant</p>
</div>
```

>**v-if V.S  v-show**
>你可能會想兩者都是畫面渲染，那其中的差異在哪？我該在什麼情況下使用？
>v-if的處理連DOM元素都不會被畫出來，而v-show的處理則是畫出了DOM並display:none
>兩者最大的差異在於性能上的選擇
>

>如果是頻繁操作(顯示、隱藏)使用**v-show - 初始成本高**(載入時DOM都畫好並加上display:none)
>如果是操作並不這麼頻繁、希望第一次載入速度越快越好使用**v-if - 切換成本高**(re-render)

以上是最常用、最基本的Vue提供的模板語法，當然Vue提供的不只這些
如果好奇的話可以到Vue官網翻閱: https://vuejs.org/v2/guide/installation.html

### Options

#### data

你可以把data理解為變數宣告的區域，我要宣告一個變數初始值是0

```javascript=
data: {
    num: 0
}
```

要在html結構中使用(文字插值)的話，透過Moustache模板引擎

```htmlmixed=
<p> 共 {{ num }} 元</p>
```

#### methods

可以直接把methods先理解為宣告function的區域，使用者行為觸發methods

```javascript=
methods: {
    functionName: function(){
        ...
    }
}
```

也可以縮寫成
```javascript=
methods: {
    functionName: {
        ...
    }
}
```

要在methods中使用data的值的話，要加上this
```javascript=
methods: {
    functionName: {
        this.num = this.num + 100;
    }
}
```


#### computed

可以把computed理解成資料的處理(資料產生資料)，寫法十分像methods，不過一定要加return，當data變化時，computed裡的值才會進行變化，且有cache機制，在處理資料更有優勢

>computed只會與vue中的data進行連動，不是vue的data則不會更新

```javascript=
data: {
    num: 100
},
computed: {
    numPlus: {
        return this.num*2;
    }
}
```
要插值的話，一樣使用Moustache
```htmlmixed=
<p> 共 {{ numPlus }} 元</p>
```

#### watch

監聽資料(data)，資料改變時去執行什麼事(methods、function..等)

```javascript=
data: {
    school: {
        students: {
            name: "Chris"
        },
        teachers: {
            name: "Cook"
        }
    }
}
```

```javascript=
watch: {
    // 監聽school這個data，變化時觸發下列的事
    school: function(val){
        // val為變化後代入的值
    } 
}
```

可以縮寫為

```javascript=
watch: {
    // 監聽school這個data，變化時觸發下列的事
    school(val) {
        // val為變化後代入的值
    } 
}
```

```javascript=
watch: {
    // 監聽data，變化時觸發method，這邊的method指的是vue裡methods中的function
    school : 'method' 
}
```

如果監聽的data是巢狀的物件時，如school中有student，student中有name，你使用上述的方法去監聽的話，無法監聽到school內物件的變化，只能監聽school這個資料的變化
如果需要監聽到整個物件，可以使用

```javascript=
watch: {
    school : {
        handler: 'method', // handler為觸發function
        deep: true // 加上deep: true，可以監聽整個物件，不管層級多深
    }
}
```
>上述方法當然也有缺點，就是資源耗費大，效能差，因為監聽了整個物件，包含物件裡所有物件的變化

```javascript=
watch: {
    // 監聽的物件 : 觸發funciton
    'school.students': 'method'
}
```
>如果希望能監聽到物件內的物件變化，又不希望全部監聽可以像上面那樣寫，只針對其中一個變化去監聽

```javascript=
watch: {
    school : {
        handler: 'method', 
        immediate: true // 加上immediate: true，在監聽前先觸發綁定的function
    }
}
```

當然也可以去監聽vuex內的變數

```javascript=
watch: {
    "$store.state.item" : funtion{
        // do some thing...
    }
}
```
>如果是這樣寫"xxx"，記得不能用縮寫!!


#### component


### Prop & $emit

### SPA

SPA，單頁式應用，全名為single-page application
與傳統MPA(多頁式應用multi-page application)差別在於當切換頁面時(補...)

### Vue-cli v4(與v3目錄結構不同，其他參照v3學習即可)

vue-cli為官方提供的開發工具，可以**快速建置開發環境**

#### 安裝

* node版本要求Node.js 8.9以上
```javascript=
node -v  // 檢查當前node.js版本
```
>node版本管理 : https://www.jianshu.com/p/c641dcc47b48


* 如果你先前有使用過vue-cli2的記得要先移除
```javascript=
npm uninstall vue-cli -g
```
>vue-cli -> v2
>@vue/cli -> v3
* 安裝vue-cli
```javascript=
npm install -g @vue/cli
```

* 確認Vue-cli版本
```javascript=
vue -V
```

#### 建立新專案
```javascript=
vue create projectName
```

第一個為以前使用過的紀錄，可以看到當使用了那些工具(babel、router、vuex...)

![](https://i.imgur.com/5TVVHXL.png)

default就基本的babel & eslint

也可以選Manually select features來自行選擇需要安裝那些工具

![](https://i.imgur.com/hrSUnB9.png)

這邊就視情況看自己的專案需要那些工具，這邊我選了babel、Router、Vuex、CSS預處理器、ESLint

![](https://i.imgur.com/hgttnko.png)

如果有選router的話，會跳出來詢問你router的mode要使用history還是hash
> History V.S Hash 可以到下面的vue-router查看差異


![](https://i.imgur.com/8W9bjkU.png)

有選CSS預處理器的話，這邊會讓你選擇你要使用哪種預處理器

![](https://i.imgur.com/zGHA7Fc.png)

有選ESLint的話，這邊會讓你選擇你想要的linter

![](https://i.imgur.com/HbOenni.png)

接著詢問檢查的時機點
* 存檔時檢查
* commit時檢查

![](https://i.imgur.com/wYZZRJD.png)

詢問babel、ESLint...等設定檔放哪


### Vue-Router

使用vue-router建構SPA的router系統，區分為**History mode** & **Hash mode**

>**History mode** :
>使用history mode會使網址更為美觀(...bookstore/book)，但要使用history mode必須要與後端(server)配合，否則當重新整理或使用路徑進入網頁時，會出現error

>**Hash mode**
>使用hash mode網址會比較醜(...bookstore/#book)，但不會有路徑上的問題

#### 設定router source

在目錄結構中找到router，進入index.js捨定，引入Vue & Vue-router，這兩個在create project時就會幫你用到好
我們只需要引入我們要呈現的頁面(紅線區塊)，並且設定好path、name..等等

![](https://i.imgur.com/Gtsgjb8.png)

可以切成多個部分作呈現

```javascript=
{
    path: "/path",    // 設定router路徑
    name: "pathName",
    // 此路徑下顯示在router-view的內容，router-view要設定name判斷顯示
    components: {    
      default: home,    
      nav: Nav,
      sidebar: Sidebar
    }
}
```
>也可以切成多個子組件(補

#### 設定router-link

有了資源在來要新增router-link在畫面上，點擊時切換router
```htmlmixed=
<router-link to="/path"> link Name </router-link>
```

#### 設定router-view

有了source、切換router的link，剩下的就剩應該在哪裡呈現切換的畫面
```htmlmixed=
<div id="app">
    <router-view />
</div>
```

將畫面切成多個部分作呈現
```htmlmixed=
<div id="app">
    <router-view id="nav" name="nav" />
    <router-view id="nav" name="language" />
    <router-view id="sidebar" name="sidebar" />
    <router-view id="frame"/>
</div>
```

#### 其他轉跳方式

除了可以將link寫在tag中透過path進行轉跳以外還可以透過

1. 透過name進行轉跳
```htmlmixed=
<router-link :to={ name: pathName }></router-link>
```

2. 透過Js轉跳
```javascript=
this.$router.push("/path");
```

```javascript=
this.$router.push({ name: pathName });
```

#### router rule

在透過router進行轉跳時，可以在裡面寫些規則或檢查，檢查是否要否要給使用者進行轉跳

```javascript=
router.beforeEach((to,from,next)) => {
    ...
}
```

> to.path -> 要去哪個path
> from.path -> 從哪個path來
> next(/path) -> 執行轉跳這個動作

```javascript=
router.beforeEach((to,from,next)) => {
    // 在轉跳前檢查path要轉跳到哪
    // 如果要轉跳到path 且 是登入狀態的話
    if(to.path === "/path" && signIn === true){
        // 轉跳到/path
        next("/path");
    }else{
        // 如果不符合上述條件轉跳到/signIn
        next("/signIn");
    }
}
```
>注意不要寫成無窮迴圈

#### router 網址列大小寫

除了透過點擊link、透過Js進行轉跳以外，其實還是可以透過修改網址列來進行轉跳
但透過修改網址列進行轉跳時要注意使用者在網址列輸入的內容，可能會打破router rule

```javascript=
router.beforeEach((to,from,next)) => {
    if(to.path === "/path"){
        next("/path");
    }else{
        next("/signIn");
    }
}
```
以上述rule為例子
當我在網址列輸入 https:.../path時，正常情形會進rule判斷，接著轉跳進/path

**問題:可是當我在網址列輸入 https:.../PatH時，會轉跳到哪??**

>答案一樣是轉跳進/path，就算你是用===
>**解決辦法: if(to.path.toLowerCase() === "/path") 一律用小寫或大寫來判斷**

備註: 上述方式都是使用history mode進行測試

### Vuex

### set & $set



### Vue-i18n


## API管理