Vue+element+Nodejs學習記錄(6)

1.axios攔截

axios攔截就是axios的二次封裝,這樣便於權限管理和統一異常處理,全局攔截器可以根據接口錯誤碼進行統一處理,而不需要再每一個接口內部進行控制,第二個好處就是,可以做全局的loading效果,如果不在全局做,你就要在每一個接口前顯示loading,接口結束進行關閉,不便於代碼維護,前端儘可能的去統一管理代碼。

參考文章:
https://hooray.github.io/posts/1059e373/
https://juejin.im/post/5bab739af265da0aa3593177
https://segmentfault.com/a/1190000008383094
https://zhuanlan.zhihu.com/p/33918784
https://blog.csdn.net/qq_36575992/article/details/80338538
https://blog.csdn.net/qq_38145702/article/details/81558816

https://segmentfault.com/q/1010000017347607/a-1020000017350518
https://blog.csdn.net/well2049/article/details/85003062
https://blog.csdn.net/rickiyeat/article/details/77030124
https://blog.csdn.net/sjn0503/article/details/74729300
https://blog.csdn.net/qq_33207292/article/details/72867211
https://blog.csdn.net/moxiaoya1314/article/details/73650751

2.Express設置cors

1.installation

npm install cors

2.Usage

//1.simple usage(Enable All CORS Requests)
var express = require('express')
var cors = require('cors')
var app = express()

app.use(cors())

app.get('/products/:id', function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for all origins!'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

//2.Enable CORS for a Single Route
var express = require('express')
var cors = require('cors')
var app = express()

app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

//3.Configuring CORS
var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
  origin: 'http://example.com',
  optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for only example.com.'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

更多介紹可以參考文章:
http://expressjs.com/en/resources/middleware/cors.html#installation

https://www.jianshu.com/p/f650dfad5574
https://blog.csdn.net/sunq1982/article/details/77887655
https://www.jianshu.com/p/af2cad6d91fb

3.Vue中代理設置vue.config.js

我們可以在服務端進行設置跨域,我們在前端也可以設置代理,比如我們的Vue的端口是8080,後端的端口8000,這時就涉及到跨域,要進行代理設置,我們在vue.config.js中設置代碼是:

module.exports = {

	publicPath:'/',
	
	devServer:{

		open: true,
	    host: 'localhost',
	    port: 8080,
	    https: false,
	    hotOnly: false,


		proxy:{
			'/api':{
				target:'http://localhost:8000/api',
				changOrigin: true, //允許跨域
				pathRewrite:{
					'^/api':''
				}
			}
		}

	}

}

參考文章:
https://blog.csdn.net/qq_40190624/article/details/85257610
https://blog.csdn.net/weixin_38201500/article/details/84791835
https://segmentfault.com/a/1190000014474361
https://segmentfault.com/a/1190000016602951
https://darknesschaser.github.io/2018/07/26/vue%E5%85%A8%E5%AE%B6%E6%A1%B6%E9%85%8D%E7%BD%AEwebpack%E5%8F%8D%E4%BB%A3/?tdsourcetag=s_pcqq_aiomsg

4.Vuex再學習

參考imooc課程。

Vuex應用場景

1.多個視圖依賴於同一狀態(多組件之間狀態共享,讀狀態的作用)
2.來自不同視圖的行爲需要改變同一個狀態(不同組件可以改變同一狀態,改狀態的作用)

Vuex的組成介紹

在這裏插入圖片描述

1.state:數據倉庫
State在Vuex中代表的是數據的來源,Vuex所有數據都會存儲在State中,是數據的唯一來源。

2.getter:原來獲取數據
可類比Vuex中的computed屬性,對state中數據進行一些操作

3.Mutation:用來修改數據
Mutation的操作是同步的,異步的話會有很大的麻煩,Mutation本質上也是一個function

4.Action:用來提交mutation
Action可以進行異步的操作

安裝Vuex

1.安裝vuex包:npm install vuex
2.創建vuex實例:new Vuex.store()
3.main.js中將vuex實例掛載到vue對象上

Vuex使用

1.獲取Vuex中state的值(例如state中的count)

{{this.$store.state.count}}

2.修改state中的值

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);

export default new Vuex.Store({

	state:{
		city:'上海'
	},

	mutations:{
		changeCity(state,city){
			state.city = city
		}
	},

	action:{
		changeCity(ctx,city){
			ctx.commit('changeCity',city)
	}

});

Vue文件中如果修改Vuex

最原始寫法:this.$store.dispatch('changeCity',city) 使用dispatch觸發一個changeCity函數
或者直接使用mutations中commit:this.$store.commit('changeCity',city)

5.token和jwt

身份認證的兩種方式

1.基於cookie

基於cookie的服務端認證,就是我們所熟知session,在服務端生成用戶相關的 session 數據,而發給客戶端 sesssion_id 存放到 cookie 中,這樣用客戶端請求時帶上 session_id 就可以驗證服務器端是否存在 session 數據,以此完成用戶認證。

2.基於Token令牌

基於token的用戶認證是一種服務端無狀態的認證方式,服務端不用存放token數據。用戶驗證後,服務端生成一個token(hash或encrypt)發給客戶端,客戶端可以放到cookie或localStorage(sessionStorage)中,每次請求時在Header中帶上token,服務端受到token通過驗證後即可確認用戶身份。

JWT的組成

JWT的本質實際上就是一個字符串,它有三部分組成頭部+載荷+簽名。

// 1.Header
{
  "alg": "HS256",//所使用的簽名算法
  "typ": "JWT"
}

// 2.Payload
{
  //該JWT的簽發者
  "iss": "luffy",
  // 這個JWT是什麼時候簽發的
  "iat":1441593502,
  //什麼時候過期,這是一個時間戳
  "exp": 1441594722,
  // 接收JWT的一方
  "aud":"www.youdao.com",
  // JWT所面向的用戶
  "sub":"[email protected]",
  // 上面是JWT標準定義的一些字段,除此之外還可以私人定義一些字段
  "form_user": "fsdfds"
}

// 3.Signature 簽名
將上面兩個對象進行base64編碼之後用.進行連接,然後通過HS256算法進行加密就形成了簽名,一般需要加上我們提供的一個密匙,例如secretKey:'name_luffy'
const base64url = require('base64url')

const base64header = base64url(JSON.stringify(header));
const base64payload = base64url(JSON.stringify(payload));
const secretKey = 'name_luffy';
const signature = HS256(`${base64header}.${base64payload}`,secretKey);


// JWT
// 最後就形成了我們所需要的JWT:
const JWT = base64header + "." + base64payload + "." + signature;
// 它長下面這個樣子:
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM

JWT的工作原理

在這裏插入圖片描述

前後端如何用這個東西做身份驗證

接下來要詳細的說如何使用jwt來進行前後端的身份驗證了,具體思路如下:

用戶登錄註冊的邏輯不需要身份驗證,因爲沒有用戶的身份信息和登錄狀態;
用戶登錄之後後端生成token並返給前端,前端拿到token之後將token緩存在本地,可以使localStorage也可以是cookie,以便接下來使用。。
其他內容涉及到前後端交互的都需要前端把認證的token信息放在請求頭部傳給後端
後端收到請求先校驗token,如果token合法(也就是token正確且沒過期),則執行next(),否則直接返回401以及對應的message。

token登陸的具體實現細節

查看參考資料:https://juejin.im/post/5b06c6baf265da0db4791805

6.Vue中template中嵌套template

<template>
    <el-row class="menu_page">
         <el-col>

             <el-menu
                mode="vertical"
                background-color="#324057"
                text-color="#fff"
                active-text-color="#409eff" 
                class="el-menu-vertical-demo">

                <!--左側-首頁-->
                <router-link to="/home">
                    <el-menu-item index="0">
                        <i class="el-icon-s-home"></i>
                        <span slot="title">首頁</span>
                    </el-menu-item>
                </router-link>

                <!--用戶管理和信息管理-->
                <template  v-for="item in items" >

                    <el-submenu v-if="item.children" :index="item.path" :key="item.path">
                        <template slot="title">
                            <i :class="'fa fa-margin '+item.icon"></i>
                            <span slot="title">{{item.name}}</span>
                        </template>
                        <router-link v-for="(citem,cindex) in item.children" 
                            :to="citem.path" :key="cindex">
                            <el-menu-item 
                                :index='citem.path'>
                                <span slot="title">{{citem.name}}</span>
                            </el-menu-item> 
                        </router-link>
                    </el-submenu> 

                </template>

             </el-menu>

         </el-col>
    </el-row>
</template>
<script>
export default {
  name: "leftmenu",
  data() {
    return {
      items: [
        {
          icon: "el-icon-user",
          name: "用戶管理",
          path: "fund", //設置:key
          children: [{ path: "foundlist", name: "用戶信息" }]
        },
        {
          icon: "el-icon-edit",
          name: "信息管理",
          path: "info",
          children: [{ path: "infoshow", name: "個人信息" }]
        }
      ]
    };
  }
};
</script>
<style scoped>
.menu_page {
  position: fixed;
  top: 60px;
  left: 0;
  min-height: 100%;
  background-color: #324057;
  z-index: 99;
}
.el-menu {
  border: none;
}
.fa-margin {
  margin-right: 5px;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 180px;
  min-height: 400px;
}
.el-menu-vertical-demo {
  width: 35px;
}
.el-submenu .el-menu-item {
  min-width: 180px;
}

.hiddenDropdown,
.hiddenDropname {
  display: none;
}
a {
  text-decoration: none;
}
</style>

在這裏插入圖片描述
把中間的template標籤改成div效果是一樣的,用template有什麼別的作用嗎?

回答:template不會渲染成元素,用div的話會被渲染成元素。把if,show,for等語句抽取出來放在template上面,也就是和指令中的v-if/v-for一起用,把綁定的事件放在temlpate裏面的元素上,可以使html結構更加清晰,還可以改善一個標籤過長的情況。

參考文章: https://segmentfault.com/q/1010000010727886

更多參考資料:
https://segmentfault.com/a/1190000015718564
https://segmentfault.com/a/1190000014062679

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章