菜雞新手向,這是我在學習vue.js項目時遇到的一些小問題,用來記錄一下自己的學習經曆,大家一起加油^_^
1.axios的導入
設定axios的預設位址,再将axios挂載到Vue上,然後就可以愉快的使用this.$http.+請求發送網絡請求啦
// 導入axios
import axios from 'axios'
axios.defaults.baseURL = '' //輸入位址
Vue.prototype.$http =axios
2.登入功能中的token
首先是了解localStorage和sessionStorage,兩者唯一一點差別就是localStorage屬于永久性儲存,而sessionStorage屬于當對話結束的時候,sessionStorage中的值才會被清空
而token之應該再打開該網站時生效,是以在登陸功能中,
window.sessionStorage.setItem(key,value)
通過以上的方法可以将token存儲再sessionStorage中,傳入兩個參數,第一個時自定義名,可以設定為“token”,第二個就是實際中token的值。
3.路由守衛
一個簡單的路由守衛結構 ,如下(未涉及到token的驗證)
// 挂載路由導航守衛
router.beforeEach((to,from,next)=>{
// to代表将要通路的路徑
// from代表從哪個路徑跳轉而來
// next是一個函數,表示放行
// next()放行 next('/login')表示強制跳轉至目标'/login'路徑
if(to.path == '/login') return next()
// 先看路徑,如果路徑是登入頁面,那直接放行,如果不是,那就先擷取token
const tokenStr = window.sessionStorage.getItem('token')
if(!tokenStr) return next('/login')
next()
})
4.系統中的退出功能實作
通過清除sessionStorage中的token值實作退出,再指定跳轉的頁面即可
logout(){
window.sessionStorage.clear();
this.$router.push('/login')
}
5.在使用者頁面中,要使用需要授權的API,必須在請求頭中使用Authorization字段提供token令牌才行,可以通過axios攔截器添加token驗證,這樣,每一次向浏覽器發送需要授權的請求時,就會對進行token進行一次預驗證
axios.interceptors.request.use(config => {
config.headers.Authorization = window.sessionStorage.getItem("token")
// 最後必須return(固定寫法)
return config;
});
再将axios攔截器設定在 axios挂載之前,完美
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
axios.interceptors.request.use(config => {
config.headers.Authorization = window.sessionStorage.getItem("token")
// 最後必須return(固定寫法)
return config;
});
Vue.prototype.$http = axios
6.this.$router 和 this.$route(轉載 本文連結:https://blog.csdn.net/u014395524/article/details/88194842)
this.$router 相當于一個全局的路由器對象,包含了很多屬性和對象(比如 history 對象),任何頁面都可以調用其 push(), replace(), go() 等方法。
this.$route 表示目前路由對象,每一個路由都會有一個 route 對象,是一個局部的對象,可以擷取對應的 name, path, params, query 等屬性。
關于 push() 方法:
想要導航到不同的 URL,則使用 router.push 方法。這個方法會向 history 棧添加一個新的記錄,是以,當使用者點選浏覽器後退按鈕時,則回到之前的 URL。
當你點選 <router-link> 時,這個方法會在内部調用,是以說,點選 <router-link :to="..."> 等同于調用 router.push(...)。
push() 方法的調用:
//字元串
this.$router.push('home')
//對象
this.$router.push({path:'home'})
//命名的路由
this.$router.push({name:'user', params:{userId: '123'}})
//帶查詢參數,變成 /register?plan=private
this.$router.push({path:'register', query:{plan:private}})
注意:如果提供了 path,params 會被忽略,上述例子中的 query 并不屬于這種情況。取而代之的是下面例子的做法,你需要提供路由的 name 或手寫完整的帶有參數的 path:
const userId = '123';
this.$router.push({path:`/user/${userId}`}); //->/user/123
this.$router.push({name:'user', params:{userId}}); //->/user/123
//這裡的 params 不生效
this.$router.push({path:'/user', params:{userId}}); //->/user
params 傳參,push 裡面隻能是 name:'xxx',不能是 path:'/xxx',因為 params 隻能用 name 來引入路由,如果這裡寫成了 path ,接收參數頁面會是 undefined。
7.element-ui中清空表單
通過resetFields()完成
比如說想要在關閉dialog後清空位于dialog中的資料
<el-dialog title="添加使用者" :visible.sync="addDialogVisible" width="50%" @close='addDialogClosed'>
<!-- 内容主題區 -->
<el-form
:model="addForm"
:rules="addFormrules"
ref="addFormRef"
label-width="70px"
>
<el-form-item label="使用者名" prop="username">
<el-input v-model="addForm.username"></el-input>
</el-form-item>
<el-form-item label="密碼" prop="password">
<el-input v-model="addForm.password" type="password"></el-input>
</el-form-item>
</el-form>
<!-- 底部按鈕區 -->
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addDialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog>
在dialog上添加一個@close='addDialogClosed',然後在methods中定義這個函數,用resetFields()方法清空即可
addDialogClosed(){
this.$refs.addFormRef.resetFields()
}
8.深拷貝Vue的運作依賴包lodash
在Vue依賴中下載下傳lodash依賴包,然後再所需頁面的script标簽中導入
<script>
import _ from 'lodash'
然後使用lodash中的cloneDeep()就可以實作深拷貝了!!👇
const form = _.cloneDeep(this.addForm)
這樣就可以把addForm深拷貝一份form了
9.babel配置中移除console.log()
在項目開發階段保留console.log()用作調試,而在釋出階段需要移除項目中所有的console.log(),這是需要在項目的babel.config.js檔案中進行簡單的配置
首先要安裝babel-plugin-transform-remove-console的開發依賴包
然後就可以在babel.config.js檔案中進行相關的配置
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
],
'transform-remove-console'
]
}
在plugins的數組中加入'transform-remove-console'就可以了,但是這樣寫有弊端,無論是開發還是釋出階段,項目中的console.log()都會被移除,我們隻希望在釋出階段移除console.log(),那就需要做一個判斷
在項目開發階段時運作,mode值為development,而在項目釋出階段時,mode值為production,基于mode的值,就可以進行判斷
思路時先設定一個數組,然後再進行判斷,最後把數組放到plugins中,搞定
const proPlugins = []
if(process.env.NODE_ENV === 'production'){
proPlugins.push('transform-remove-console')
}
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
],
...proPlugins
]
}
10.vue.config.js的配置
注意,這裡相當于是定義了項目運作時的入口檔案,如果是再開發(process.env.NODE_ENV === 'development')模式下,将入口檔案main.js換成main-dev.js,如果是釋出模式(process.env.NODE_ENV === 'production'),則将入口檔案替換成main-prod.js,可以把src下的main.js複制一份再重命名(注意存放的路徑不能出錯,否則系統會找不到入口檔案,直接報錯!!!!)
module.exports = {
lintOnSave: false,
chainWebpack: config=>{
config.when(process.env.NODE_ENV === 'production',config =>{
config.entry('app').clear().add('./src/main-dev.js')
})
config.when(process.env.NODE_ENV === 'development', config=>{
config.entry('app').clear().add('./src/main-prod.js')
})
}
}
11.通過externals加載外部CDN資源
在預設的情況下,通過import文法導入的第三方依賴包,最終會被打包合并到同一個檔案中,進而導緻打包合并後,單檔案體積過大
為了解決上述問題,通過webpack的externals節點,在配置外部的CDN資源,凡是聲明在externals中的第三方依賴包,都不會被打包,在vue.config.js檔案中配置externals,這樣在運作的時候,如果發現用import導入了一個包,👇,如axios,就不會把這個包(axios)合并到上述的檔案中去,而是區window全局中尋找axios對象,然後直接來使用
module.exports = {
lintOnSave: false,
chainWebpack: config=>{
// 釋出模式
config.when(process.env.NODE_ENV === 'production',config =>{
config.entry('app').clear().add('./src/main-prod.js')
config.set('externals',{
vue:"Vue",
'vue-router': 'VueRouter',
axios: 'axios',
lodash:'_',
echarts : 'echarts',
nprogress:'Nprogress',
'vue-quill-editor': 'VueQuillEditor'
})
})
// 開發模式
config.when(process.env.NODE_ENV === 'development', config=>{
config.entry('app').clear().add('./src/main-dev.js')
})
}
}
做完上面的配置,還需要在public/index.html檔案的頭部加上CDN資源的引用,例如我的項目中的CDN引用如下👇,可以用https://www.bootcdn.cn/,在這裡面直接輸入要引入的包名就可以找到了!!
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico" target="_blank" rel="external nofollow" >
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
<!-- nprogress樣式表 -->
<link href="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css" target="_blank" rel="external nofollow" rel="stylesheet">
<!-- 富文本編輯器css -->
<link href="https://cdn.bootcdn.net/ajax/libs/quill/2.0.0-dev.3/quill.bubble.min.css" target="_blank" rel="external nofollow" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/quill/2.0.0-dev.3/quill.core.min.css" target="_blank" rel="external nofollow" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/quill/2.0.0-dev.3/quill.snow.min.css" target="_blank" rel="external nofollow" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script>
<!-- 富文本編輯器js檔案 -->
<script src="https://cdn.bootcdn.net/ajax/libs/quill/2.0.0-dev.4/quill.min.js"></script>
</head>
12.首頁内容定制
目标:希望在development下,在網頁上顯示dev-電商背景管理系統,而在production中顯示的是 電商背景管理系統,并且在dev中不需要加載CDN,
思路:依舊是需要判斷目前加載到底時development還是production,是以着手對号是在vue.config.js的配置中,在釋出模ls式和開發模式中,找到一個插件,html,然後通過tap()修改插件中的鍊式操作,在tap中定義一個回調函數,args時插件中的參數項,在args中加上一個自定義屬性,isProd,在釋出模式中定義isProd為true,而在生産模式中定義isProd為false
module.exports = {
lintOnSave: false,
chainWebpack: config=>{
// 釋出模式
config.when(process.env.NODE_ENV === 'production',config =>{
config.entry('app').clear().add('./src/main-prod.js')
config.plugin('html').tap(args=>{
args[0].isProd = true
return args
})
config.set('externals',{
vue:"Vue",
'vue-router': 'VueRouter',
axios: 'axios',
lodash:'_',
echarts : 'echarts',
nprogress:'Nprogress',
'vue-quill-editor': 'VueQuillEditor'
})
})
// 開發模式
config.when(process.env.NODE_ENV === 'development', config=>{
config.entry('app').clear().add('./src/main-dev.js')
config.plugin('html').tap(args=>{
args[0].isProd = false
return args
})
})
}
}
回到public中的index.html,htmlWebpackPlugin是參數名稱,options中是參數項,isProd就是👆定義的參數,用三元運算符判斷即可
<title>
<%= htmlWebpackPlugin.options.isProd ? '': 'dev-'%>電商背景管理系統
</title>
然後就是希望在開發模式下不要加載CDN,可以用👇的代碼把production中的CDN引入包裹起來,這樣在加載開發模式時,頁面就不會加載引入的CDN了
<% if(htmlWebpackPlugin.options.isProd){ %>
//CDN
<% }%>
13.路由懶加載
在打包項目時,javascript的包會特别的大 ,影響頁面的加載,需要把不同路由對應的元件分割成不同的代碼塊,然後當路由被通路的時候才加載對應的元件,這樣效果會更加高效
下載下傳開發依賴包👆,然後在babel.config.js檔案中👇
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
],
// 釋出産品時候的插件數組
...proPlugins,
'@babel/plugin-syntax-dynamic-import'
]
}
然後就可以在路由中把不同的路徑打包,如:👇,在webkpackChunkName中把login,home,welcome打包到一起加載,
const Login = () => import(/* webpackChunkName: 'login_home_welcome'*/ '../components/Login.vue')
const Home = () => import(/* webpackChunkName: 'login_home_welcome'*/ '../components/Home.vue')
const Welcome = () => import(/* webpackChunkName: 'login_home_welcome'*/ '../components/Welcome.vue')
14. 開啟gzip配置
分為3步
npm i compression -D //安裝相應的包
const compression = require("compression") //導入包
app.use(compression()) //啟動(要寫在靜态的前面)
const express = require("express")
const compression = require("compression")
const app = express()
//
app.use(compression())//一定要寫在靜态之前
app.use(express.static('./dist'))
app.listen(80 , ()=>{
console.log("server running at http://127.0.0.1")
})