--- tags: VUE 3 課程筆記 --- # VUE 3 課程筆記 (一) ## ES6 相關介紹 ### JavaScript 語法糖 (程式碼變簡潔,不過不會影響運作,邏輯跟原本一樣) #### 陣列裡面的函式縮寫 ```javascript const obj = { myName: '物件', fn: function() { return this.myName; } } //這邊的函式可以縮寫成 const obj = { myName: '物件', fn() { return this.myName; } } ``` #### 物件字面值 ```javascript const person = { name: '小明' }; const people = { person = person, } // 可以縮寫成 const people = { person , } ``` #### 展開 方便運用的 "..." , 可以運用在展開陣列以及物件 陣列的展開與合併: ```javascript= const groupA = ['小明', '杰倫', '阿姨']; const groupB = ['老媽', '老爸']; const groupAll = groupA.concat(groupB); // ['小明', '杰倫', '阿姨', '老媽', '老爸'] // 可以縮寫成 const groupAll = [...groupA,...groupB]; // ['小明', '杰倫', '阿姨', '老媽', '老爸'] ``` #### 物件的合併: ```javascript const methods = { fn1() { console.log(1); }, fn2() { console.log(1); }, } const newMethods = { fn3() { console.log(1); }, ... methods, } // newMethods 就會變成 const newMethods = { fn3() { console.log(1); }, fn1() { console.log(1); }, fn2() { console.log(1); }, ``` #### 陣列轉換: ```htmlembedded <ul> <li>1</li> <li>2</li> <li>3</li> </ul> ``` ```javascript const doms = document.querySelectorAll('li'); // 這邊的 doms 會是一個 NodeList 並不是純陣列哦是一個類陣列 let newDoms = [...doms] // 這邊的 newDoms 就會是一個 Array 了 ``` #### 預設值: ```javascript function sum(a, b) { // 請加入預設值避免錯誤 return a + b; } console.log(sum(1)); // 這邊因為沒有 b 的值,會是一個 NaN 要避免的話要把函式改寫成 function sum(a,b){ if (!b) {b = 2} return a + b; } // 可以改寫成 function sum(a, b=2) { return a + b; } ``` ### this 的指向觀念 this 的指向跟調用的方法有關 ```javascript callSomeone() { console.log(this.someone); } callSomeone(); // simple call 這邊 this 的指向是全域 var obj = { someone: '物件', callSomeone2() { console.log(this.someone); } } obj.callSomeone2(); // 這樣this 的指向就是前面的物件 var obj2 = { someone: '物件2', callSomeone2 } obj2.callSomeone2(); // 雖然callSomeone2() 是從 obj 調用的 //不過因為是在 obj2 裡面調用的,所以 this 的指向會是 obj2 ``` 另外像是 setTimeout 這種 callback function 是一種 simple call 的方式,所以指向會指向全域 ### 箭頭函式 ```javascript const arr = [1, 2, 3, 4, 5]; const filterArr = arr.filter(function(item) { return item % 2; }) // 用箭頭函式 可以把上面 filterArr 改寫成 const filterArr = arr.filter( item => item % 2 ); // 可以把 function 改成參數後面的 => // 並且移除 {} 以及 filter // 另外當參數如果只有一個 參數的 () 也可以移除 ``` 箭頭函式的 this 指向不太一樣 原本函式的 this 指向應該是: ```javascript var name = '全域' const person = { name: '小明', callName: function () { console.log('1', this.name); // 1 小明 setTimeout(function () { console.log('2', this.name); // 2 全域 console.log('3', this); // 3 指向 window }, 10); }, } person.callName(); ``` 箭頭函式的 this 指向會是: ```javascript var name = '全域' const person = { name: '小明', callName: function () { console.log('1', this.name); // 1 小明 setTimeout( () => { console.log('2', this.name); // 2 小明 console.log('3', this); // 3 指向 person }, 10); }, } person.callName(); ``` **箭頭函式沒有自己的 this ,只會指向外層作用域的 this** 所以這邊 setTimeout() 裡面的 this 會跟 外層的指向相同 #### 為了避免 this 指向不如預期可以有兩種方式: 1. this 先指向其他變數 ```javascript var someone = '全域'; function callSomeone() { console.log(this.someone); } var obj4 = { someone: '物件 4', fn() { const vm = this; // vm 在 Vue 中意指 ViewModel setTimeout(function () { console.log(vm.someone); }); } } obj4.fn(); ``` 2. 使用箭頭函式 ```javascript var someone = '全域'; function callSomeone() { console.log(this.someone); } var obj4 = { someone: '物件 4', fn() { setTimeout(() => { console.log(this.someone); }); } } obj4.fn(); ``` ### 關注點分離 如果要在輸入框中輸入文字並且存取到畫面上: 傳統方式是先提取輸入框內的文字,然後產生一個新的節點,並且帶入文字。 關注點分離的概念則是除了畫面上的輸入框之外,會有一個**資料集**,輸入框輸入的東西會先提取出來先寫入資料集,再把資料集的內容轉換成畫面。 好處是,畫面的程式碼跟操作還有資料的程式碼是分開的,所以就可以專注在資料的整理方面,程式碼相對會比較好管理。 ### 傳參考特性 物件、陣列、函式都是傳參考的特性,所以也會建立一個屬於自己的記憶體空間 ```javascript const person = { name : '小明', obj : {} // 這個 obj 也會有屬於自己的記憶體空間 } ``` ![](https://i.imgur.com/RxqvHzJ.jpg) 避免傳參考特性修改到原始資料,有兩個解決方案: 1. 淺層拷貝 ```javascript const person = { name : '小明', obj : {} } const person2 = Object.assign({},person); const person3 = { ...person } // 這兩種方式都可以進行淺層拷貝出新的記憶體空間 // 不過需要注意,淺層拷貝的部分 // 在拷貝的物件裡面包的物件是沒有創造出新的記憶體空間的哦 ``` 2. 深層拷貝 是將要拷貝的物件轉成字串再轉回物件的方式,所以包含再要拷貝物件裡面的子物件也會是完全不一樣的記憶體空間了 ```javascript const person = { name: '小明', obj: {} } const person2 = JSON.parse(JSON.stringify(person)); // JSON.stringify 是物件轉字串 JSON.parse 是字串轉物件 ``` ### promise 非同步 ![](https://i.imgur.com/hkzztqL.jpg) 呼叫 promise 之後會先進入一個 pending 的狀態,並且會先把所有程式碼執行完,最後才會執行 pending 的部分,並且等待 promise 的結果確認之後再回傳 resovle 或者 reject ,最後再依照成功或者失敗使用 then 或 catch 來進行資料接收 promise 是可以進行串接的 ```javascript promiseSetTimeout(true) .then(res => { ... }).catch(res => { ... }) // 串接的話就會變成 promiseSetTimeout(true) .then(res => { ... return promiseSetTimeout(true); }) .then(res => { ... }) .catch(err => { ... }) ``` promise 在原件上的應用: ```javascript const component = { data:{}, init(){ promiseSetTimeout() .then(res =>{ this.data.res = res; // 把非同步的資料寫回 data 裡面 }) .catch(err =>{ alert(err); }) } } component.init(); ``` axios 的 promise 使用方式: ```javascript const component = { data:{}, init(){ axios.get('APIURL') .then(res =>{ this.data.res = res; // 把非同步的資料寫回 data 裡面 }) .catch(err =>{ alert(err.response); }) } } component.init(); ``` ### ES Module 將 JS 模組化的作法,可以更有效的拆分以及管理檔案,匯出匯入本一體,先掌握匯出更容易理解匯入 1. 匯出 1.1 將標籤定義 ```<script type="module">``` 1.2 預設匯出 (defaultExport.js): export default 常見的匯出方式,通常用於匯出物件,在 Vue 開發中可用來匯出元件 ,每個檔案都是唯一的 ```javascript export default { data: [ . . . ], render(dom) { . . . }, }; ``` 1.3 具名匯出 (namedExport.js): export const XXX = ... 每個檔案可以匯出多個變數、函式... 比較像函式庫的概念!? 所以每個檔案都可以有多個具名匯出以及一個預設匯出 可用於匯出已定義的變數、物件、函式,專案開發中通常用於 “方法匯出” 第三方的框架、函式、套件很常使用具名定義 “方法” ```javascript export const a = 1; export function b() { console.log('1'); } export function c(a, b) { return a + b; } ``` 2. 匯入 2.1 預設匯出的匯入方式: ``` javascript import 自訂名稱 from 'XXX.js'; 自訂名稱.函式(); ``` 2.2 具名匯出的匯入方式: 2.2.1 單一匯入 ```javascript import {XXX} from 'XXX.js' // 這邊就可以直接使用了 ``` 2.2.2 全部匯入 (不過不建議,錯誤較難發現): ```javascript import * as all from 'XXX.js'; all.fn(); // 可以直接從 all 調用 ``` ### ES module 使用技巧 每個 ```<script type='module'>```作用域都是獨立的,不會互相影響 另外,只要有 "ESM" 的 CDN ,只要條件允許,都是可以使用 import 的方式載入的哦 ```htmlmixed <div id='app'>{{ ... }}</div> <script type='module'> import {createApp} from 'https://.../.js'; const XXX = { data(){ return { . . . } } }; createApp(XXX).mount('#app'); ``` 接好 CDN 掛上去就可以使用了