JS作品實戰-Week4-登入實作

使用 Vue.js 實作一頁產品管理頁面(學習筆記)

Chun
9 min readAug 4, 2020

登入驗證流程實作

驗證碼 Token

不要將 Token 釋放在網路上面,因為 Token 只會存在自己的本機裡面,每個人登入的時候都會帶有獨立的 Token,且 Token 有其時效性,過了期效也會驗證失敗,必須再重新產生,每一次登入登出也都會做更換。

由於每一個頁面(登入頁、產品管理頁、訂單管理頁…)都會獨立對伺服器發送請求的 API,不同頁面的驗證碼 Token 是無法共用的,因此就需要使用到 cookie,來暫時存放 Token,並且讓相同網域不同頁面也可以共用 Token。

什麼是 cookie 呢?

cookie 是瀏覽器的運行狀態,若在網域上儲存了一個 cookie,那麼在該網域裡的所有頁面,都可以存取資料到 cookie。(如果頁面跳轉至不同的網域,則無法存取到這組 cookie),所以每一組 cookie 都獨立在每一個網域上,並且有一個獨立的名稱。

無痕模式

一般網頁模式和無痕模式的 cookie 是獨立開來的,一般網頁模式,瀏覽器關掉後,cookie 還會存在。但使用無痕模式,只要將瀏覽器關掉,cookie 也會同時被清掉。(重新整理資料還會在)

登入

向遠端伺服器發送登入請求後,打開開者工具,查看 Network 回傳結果,在 Preview 欄位內的 expired 和 Token 必須存取起來。(expired 為 Token 的到期日)點選 Application,可查看 cookie 內是否有正確存取到從遠端傳回來的 Token。存取完之後,再將之取出來使用。

登出

將 cookie 裡存取的 Token 和 expired 給清除。登出之後,若要從遠端取得資料就會出現驗證錯誤,因為驗證碼被清除。

JS 如何存取 cookie

1. 儲存 cookie

document.cookie = "myTokenName=true; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/";   // ; path=/ 可省略不寫
// myTokenName 自定義名稱
// true 代入遠端取回的 Token
// expires 到期日「值代入 new Date(expired * 1000)」

new Date()是 JavaScript 的 Date 物件,用來取得目前標準時間。至於(expired * 1000)為什麼是乘以 1000? 因為這裡從遠端伺服器傳回來的expired為秒數,而寫入 cookie 裡,必須使用毫秒(一秒=1000毫秒),所以expired要乘以 1000。

2. 取出 cookie

this.token = document.cookie.replace(/(?:(?:^|.*;\s*)myTokenName\s*\=\s*([^;]*).*$)|^.*$/, "$1");// 代入先前定義的 myTokenName
// this.token 此範例的 Token 是存在 Vue 裡面。

Vue.component 元件實作

元件概念簡述

  1. 獨立且可重複使用,並且帶有一個名字(自定義)。
  2. 元件內的 data 必須使用 function 將值 return 帶出來。(這樣是確保每個元件都是獨立的拷貝;若不這麼做會有物件傳參考特性,導致一個元件更動,所有相同元件也一併改動。)
// 定義一個名為 'my-component' 的新元件
Vue.component('my-component', {
data: function () {
return {
... // 要帶出來的值
}
},
template: '#x-template-id' // 或直接代 HTML 模板程式碼
})

元件可重複使用

<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
Vue.component('my-component', {
data: function () {
return {
... // 要帶出來的值
}
},
template: '#x-template-id' // 或直接代 HTML 模板程式碼
})

prop

  1. 用來向內元件(子組件)傳遞數據。(口訣:由外向內)
  2. 可以在組件上註冊的一些自定義 attribute。
  3. 一個組件默認可以擁有任意數量的 prop,任何值都可以傳遞給任何prop。
  4. 使用 v-bind(縮寫:)綁定 props 屬性,並將 Vue 實例內 data 的值代入到 props 屬性內。也就是所謂「由外向內元件傳遞數據」。
  5. 單向數據流,只能單向接收由外傳進來的資料,不能向外更改資料。
  6. HTML 中對「屬性名」的大小寫是不敏感的,故可用「-」烤肉串寫法取代駝峰設計。雖然 prop 的屬性名可以在 JS 使用駝峰寫法,到 HTML 改用烤肉串寫法,但是 emit 事件名不行,故建議皆使用烤肉串寫法,避免無法對應而出錯
Vue.component(‘blog-post’, {
props: [‘title’], // 自定義屬性名稱
template: ‘<h3>{{ title }}</h3>’
})
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>

emit

  1. 由內元件向外傳遞數據。(口訣:由內向外)
  2. 是一組事件,必須靠事件觸發來執行。

內層事件,用來呼叫 emit,並給 emit 一個名稱,這個名稱會用來觸發 HTML 的結構(也就是掛在 HTML 上的元件標籤),HTML 的結構再去呼叫外層的方法

v-bind

動態綁定 class 並給判斷,符合條件時,加上 class 名稱,不符合時,則不加上。

例如:
:class="{'disable': pages.current_page === 1}"
:class=”{‘class 名稱: 冒號後面給判斷}”

分頁模板註解

:class="{'disabled': pages.current_page === 1}">   
// 當前頁數 = 1 加上 disabled
@click.prevent="emitPages(pages.current_page - 1)">
// click 事件 修飾符.prevent:防止執行預設的行為
// 並代入當前頁數(item)- 1(往前一頁)
v-for="(item, index) in pages.total_pages" :key="index"
// 迴圈抓出 總頁數裡的 每一筆資料(item)頁數
// 因為不確定共有幾頁 所以用迴圈取資料 記得加上 :key
:class="{'active': item === pages.current_page}">
// 點擊的分頁 = 目前的頁面時 加上 active 標籤
@click.prevent="emitPages(item)">{{ item }}
// click 事件 修飾符.prevent:防止執行預設的行為
//並代入當前頁數(item)
:class="{'disabled': pages.current_page === pages.total_pages}">
// 當前頁數 = 總頁數:到最後一頁了 加上 disabled
@click.prevent="emitPages(pages.current_page + 1)">
// click 事件 修飾符.prevent:防止執行預設的行為

Vue.component 寫法

  1. 可直接寫在 HTML 上。
  2. 獨立拉出一個 js 檔,再用載入 js 檔案的方式載入。
// 在 JS 中是駝峰寫法
Vue.component(‘blog-post’, {
props: [‘postTitle’],
template: ‘<h3>{{ postTitle }}</h3>’
})
// 在 HTML 中是烤肉串寫法
<blog-post post-title="hello!"></blog-post>
Vue.component(‘myComponent’, { // 自定義元件名稱,用來設定 HTML 標籤名稱
template: ‘#x-template-id’ // 對應到 x-template 的 id
}); // 或直接將 Html 程式碼用字串的方式代入
<script type="type/x-template" id="x-template-id">
Html 程式碼...
</script>

元件可作為 HTML 標籤使用

對應到 Vue.component 裡的自定義元件名稱

<myComponent :pages="pagination" @emit-pages="getAllProducts"></myComponent>

實例

<! — 分頁(把定義好的分頁元件 用標籤的方式 掛在 HTML 上) →<pagination :pages=”pagination” @emit-pages=”getAllProducts”></pagination><! — 「:pages=”pagination”」 -> 動態綁定 props 屬性,將 Vue 實例裡的 pagination 的值代入 props(由外向內) →<! — 「@emit-pages=”getAllProducts”」 -> emit 事件觸發外層 getAllProducts 方法 →

--

--