# Vue3 學習筆記
## JavaScript ES6 複習
### 變數(var, let, const)
###### 使用 var:
這邊 if 判斷式中的 arr 變成了全域變數。
:thought_balloon: 何時用 var,自ES6版本開始後,我們將會只會用到 let 和 const 。
```javascript=
var arr = [a, b, c];
if(ture){
var arr=[];
}
console.log(arr);
// => []
```
###### 使用 let:
改用 let 將會把影響範圍限縮於判斷式內(區域變數),不再影響 arr 。
:thought_balloon: let 的範圍是由{}去界定的。
```javascript=
var arr = [a, b, c];
if(ture){ㄍ
let arr=[];
}
console.log(arr);
// => [a, b, c]
```
###### 使用 const:
使用 const 有不能夠被修改的特性。
:thought_balloon: 取 DOM 元素時,使用 const ,而非 let 因為我們並不會去修改 DOM 元素。
```htmlmixed=
<a id="link"></a>
<script>
const dom = document.getElementById('link');
</script>
```
比較嚴謹的狀況下,使用 const 來宣告物件以及矩陣。
:thought_balloon: 在 javaScript 中使用 const ,只有 Obj (物件)以及 Array(矩陣),可以增加其內容,但前提是不可以修改其原本的類型。
```javascript=
const a = { name: "mike"};
a["age"] = 12;
console.log(a);
// => { name: "mike", age: 12}
const b = [];
b = 123;
console.log(a);
// => Uncaught TypeError: Assignment to constant varible at ...
```
###### Vue3基本文法型態:
```javascript=
// Composition API plugin
const { **要叫出的工具** } = Vue;
// RootComponent
const App = {
setup() {
// Options
// Return variable
return { **要回傳的值** };
}
};
// Create Vue application
Vue.createApp(App).mount(" **洞元素** ");
```
### 解構賦值(Destructuring assignment)
告別 **Varible.Key**,擁抱解構方法,不需再一個個改,也和冗長複雜的結構說再見。
###### 方法一(嵌入新參數):
```javascript=
const data = {
name: "mike",
age: "12",
address: "Taiwan"
};
const { name, age, address } = data;
// console.log(data.name, data.age, data.address);
console.log(name, age, address);
// => mike 12 Taiwan
```
###### 方法二(嵌入新物件):
```javascript=
const data = {
name: "mike",
age: "12",
address: "Taiwan"
};
const user = {
data,
sextual: male
}
```
### 箭頭函式運算式(Arrow Function)
使用箭頭函式代替原本的function關鍵字。
###### 箭頭函示寫法:
```javascript=
(**值**) => {
// Options
};
```
###### 兩者的不同(this、e.target):
:thought_balloon: function關鍵字與箭頭函式**並不完全相同**,前者可以使用this,而後者並無this,只會指向其上一層(Windows)。
```htmlmixed=
<a id="link1" href="javascript:;">link1</a>
<a id="link2" href="javascript:;">link2</a>
<script>
// 使用this
document.getElementById("link1").addEventListener("click",function() {
console.log(this);
// => <a id="link2" href="javascript:;">link1</a>
});
// 使用e.target
document.getElementById("link2").addEventListener("click", (e)=>{
console.log(e);
// => <a id="link2" href="javascript:;">link2</a>
})
</script>
```
###### 宣告函式:
利用變數方式,來指定一個function的使用。
```javascript=
const Add = (a,b) => {
retrun a+b;
}
console.log(Add(1,3));
// => 4
```
:thought_balloon: 如果return只有**一行**的話,可以省略掉大括號(如下)
```javascript=
const Add = (a,b) => a+b;
```
### 預設值(Function Default)
範例將陣列中的數字型態轉為字串。
:thought_balloon: 使用預設值可以避免掉一些初階的函式錯誤。
```javascript=
// 原語法
const ArrToStr = (arr) => {
// 如arr為undefind,則設為空陣列
if(!arr) arr = [];
const mapStr = arr.map((item) => {
return item + "";
});
return mapStr;
}
// 使用預設值語法
const ArrToStr = (arr = []) => {
const mapStr = arr.map((item) => item + "");
return mapStr;
}
console.log(ArrToStr())
// => []
console.log(ArrToStr([1, 2, 3]))
// => ["1", "2", "3"]
```
### 字串模板(String template)
利用反斜線(Literal)建立字串模板,並利將參數放數錢字號大括號之中。
:thought_balloon: 字串模板支援換行的功能,用起來更加方便。
```javascript=
const add = (name, age) => {
// return "hi我叫"name+",我今年"+age+"歲"
return `hi我叫${name},我今年${age}歲`
}
console.log(add("mike", 12));
// =>hi我叫mike,我今年12歲
```
### 模組(Module)
:thought_balloon: Module 中,有 export default(**預設丟出**)與export (**選擇性丟出**),而一個 Module **只能有一個 export default**,另外 export 出去的類型只能夠是 **const**。
```javascript=
const Add = (a, b) =>{
return a+b;
}
// 透過解構取出
export const name = "mike";
export const age = 12;
export const Remove = (a, b) => a-b;
// 直接取出
export default Add;
```
:thought_balloon: 直接使用import的方式拉入,不用使用src拉入資源在寫入。
```htmlmixed=
<script type="module">
import Add, { name, age, Remove } from "URL"
</script>
```
## Vue 基礎入門
### 起手式(Create App)
###### 步驟:
1. 先將 Vue 掛載入檔案中。
2. 在 Body 中最外圍建構一 div 元素(Vue的控制範圍)。
3. 建立一 const 物件
4. 創造 Vue 應用程式本身,並渲染至指定的 ID。
###### 基本結構:
```htmlmixed=
<!-- 渲染目標 -->
<div id="app"></div>
<!-- 掛載 Vue -->
<script src="./js/vue.js"></script>
<script>
// 要從 Vue 解構的方法
const { 方法 } = Vue;
// Vue操作內容
const App = {
setUp() {
return { 參數 };
}
};
//創建 Vue 並渲染至目標
Vue.createApp(App).mount("#app");
</script>
```
### ref
透過 ref 包裝,才能做到資料的綁定以及修改。
:thought_balloon: 可以接受各型別的參數定義。
###### 解構與綁定:
```javascript=
// 解構 ref
const { ref } = Vue;
const App = {
setUp() {
// const text = Vue.ref("Mike");
const text = ref("Mike");
return { text };
}
};
Vue.createApp(App).mount("#app");
```
###### 資料修改:
:thought_balloon: 兩個大括號為 Vue 的**字串模板**。
```htmlmixed=
<div id="app">
<h1>{{text}}</h1>
</div>
```
:thought_balloon: 再 ref 包裝過後,會回傳一個物件,而如要修改資料的值則要透過物件中的 **value**。
```javascript=
const { ref } = Vue;
const App = {
setUp() {
const text = ref("Mike");
setTimeout(()=>{
text.value = "John";
},1000);
return { text };
}
};
Vue.createApp(App).mount("#app");
```
### reactive
:thought_balloon: 只能接受陣列或物件兩種類型的值。
```htmlmixed=
<div id="app">
<h1>{{message.text}}</h1>
</div>
```
```javascript=
const { reactive } = Vue;
const App = {
setUp() {
const message = reactive({ text: "Hello Vue" });
return { message };
}
};
Vue.createApp(App).mount("#app");
```
### 選擇 ref 還是 reactive
大多數情況下兩者可以交互使用,主要取決個人喜好或團隊習慣,根據具體情況去決定要使用那個好。
###### 兩者差異:
* ref:可以定義**任何型別的值**,但不會對物件或陣列內的屬性變動做監聽。
* reactive:只能定義物件或是陣列,可以**深層監聽**,以及**訪問資料不需要使用 .value**。
### 資料雙向綁定(Two way bind)
利用模板語法 **v-model** 對 input 以及資料做雙向綁定。
###### 範例一(輸入列綁定標題)
```htmlmixed=
<div id="app">
<h1>{{text}}</h1>
<input type="text" v-model="text">
</br>
<h1>{{message.text}}</h1>
<input type="text" v-model="message.text">
</div>
```
```javascript=
const { ref, reactive } = Vue;
const App = {
setup(){
const text = ref("Mike");
const message = reactive({ text: "Hello Vue" })
return { text, message };
}
};
vue.createApp(App).mount("#app");
```
### 事件綁定(On event)
使用 **v-on** 將return出的函式與事件綁定。
:thought_balloon: v-on:click 可簡寫為 @click。
###### 範例一(按鍵加減)
```htmlmixed=
<div id="app">
<h1>{{num}}</h1>
<button v-on:click=AddFn>Add</button>
<button v-on:click=MinusFn>Minus</button>
</div>
```
```javascript=
const { ref } = Vue;
const App = {
setUp(){
const num = ref(0);
const AddFn = () => num.value++;
const MinusFn = () => num.value--;
};
return { num, AddFn, MinusFn };
}
Vue.createApp(App).mount("#app");
```
### 唯讀 (readonly)
避免修改到參數,當修改到readonly定義後的參數,Vue 會返回失敗。
```htmlmixed=
<div id="app">
<button @click="Change">Add</button>
<button @click="ChangeCopy">CopyAdd</button>
</div>
```
```javascript=
const { ref, readonly } = Vue;
const App = {
setup() {
const Num = ref(0);
const CopyNum = readonly(Num);
const Change = () => Num++;
const ChangeCopy = () => CopyNum++;
}
return { Num, CopyNum, Change, ChangeCopy };
};
// =>Set operation on key "idx" failed: target is readonly.
```
### 列表渲染(v-for)
使用 v-for 在要渲染的 DOM 元素上。
:thought_balloon: v-show 透過使用 CSS 中的 display: block / none 來顯示以及隱藏 DOM 元素。
###### key的重要性:
使用v-for的時候,一定要給 **key**。
:thought_balloon: 使用 v-for 的時候**不要用索引值當 key**,請使用唯一值當作key的值。
###### 範例:
```htmlmixed=
<div id="app">
<ul>
<li
v-for="(item, idx) in listArr"
v-bind:key="item.name"
v-show="item.show"
>
{{item.name}}
</li>
</ul>
</div>
```
```javascript=
const { reactive } = Vue;
const App = {
setup() {
const listArr = reactive([
{ name: "2020 Vue3 專業職人 | 入門篇", show: true },
{ name: "2020 Vue3 專業職人 | 加值篇", show: false },
{ name: "2020 Vue3 專業職人 | 進階篇", show: true },
{ name: "現代 JavaScript 職人之路|入門篇", show: true },
{ name: "現代 JavaScript 職人之路|中階實戰篇", show: false }
]);
}
return { listArr };
}
```
### v-if 與 v-show
如何使用 Vue 來把 DOM 元素做顯示與隱藏。
:thought_balloon: 以上兩者使用情境完全不同,仔細思考應該使用哪一種才可達到目的。
* v-if 隱藏時會直接不做 DOM 元素的渲染,節省渲染的效能。
* v-show 隱藏時會直接套上 display:none; 的CSS屬性,增加切換時的速度。
###### 範例:
```htmlmixed=
<div id="app">
<h1 id="vue-if" v-if="isShow">{{Text}}</h1>
<h1 id="vue-show" v-show="isShow">{{Text}}</h1>
<button @click="handDomShow">Hand Dom Show</button>
</div>
```
```javascript=
const { ref } = Vue;
const App = {
setup() {
const isShow = ref(false);
const Text = ref("Hello Vue!");
const handDomShow = () => {
isShow.value = !isShow.value;
};
return {
Text,
isShow,
handDomShow,
};
},
};
Vue.createApp(App).mount("#app");
```
### 屬性綁定 (v-bind)
只要是屬性(Attribute),透過使用 v-bind ,都可以動態地把資料塞入,例如: class、src、alt。
:thought_balloon: v-bind 可以使用冒號來縮寫。
```
v-bind:class=""
:class=""
```
###### 範例(class):
```css=
.red {
color: red;
}
.blue {
color: blue;
}
```
```htmlmixed=
<div id="app">
<ul>
<li
v-for="(list, idx) in listArr"
v-bind:key="list.name"
v-bind:class="list.status"
>
{{idx + 1}}. {{list.name}}
</li>
</ul>
</div>
```
```javascript=
const { reactive } = Vue;
const App = {
setup() {
const listArr = reactive([
{ name: "2020 Vue3 專業職人 | 入門篇", status: "red" },
{ name: "2020 Vue3 專業職人 | 加值篇", status: "blue" },
{ name: "2020 Vue3 專業職人 | 進階篇", status: "red" },
{ name: "現代 JavaScript 職人之路|入門篇", status: "red" },
{ name: "現代 JavaScript 職人之路|中階實戰篇", status: "blue" },
]);
return {
listArr,
};
},
};
Vue.createApp(App).mount("#app");
```
### 計算屬性 (Computed)
可以靈活的緩存資料,而不需要像是Method一樣,只要資料變化,就需要再呼叫一次。
### 插槽 (Slot)
可以定義相對的插槽名稱,並將元件或DOM元素指入對應的插槽
```html=
</slot>
```
# 筆記區(尚未整理)
* 去除Vue3載入時,出現的大鬍子,要使用**v-clock**,等待所有載入都完成時,才會顯現出來。
* 多多善用Computed,可以靈活的緩存資料,而不需要像是Method一樣,只要資料變化,就需要再呼叫一次。
* readonly 就是讓你的 ref 或是 reactive 的資料只可以讀取不可以被修改,非常適合用在參數傳遞的時候避免不小心被修改資料 ex: const a = readonly(b);