天天看點

Vue.js電商背景項目筆記1

菜雞新手向,這是我在學習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的開發依賴包

Vue.js電商背景項目筆記1

 然後就可以在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的值,就可以進行判斷

Vue.js電商背景項目筆記1
Vue.js電商背景項目筆記1

 思路時先設定一個數組,然後再進行判斷,最後把數組放到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文法導入的第三方依賴包,最終會被打包合并到同一個檔案中,進而導緻打包合并後,單檔案體積過大

Vue.js電商背景項目筆記1

為了解決上述問題,通過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的包會特别的大 ,影響頁面的加載,需要把不同路由對應的元件分割成不同的代碼塊,然後當路由被通路的時候才加載對應的元件,這樣效果會更加高效

Vue.js電商背景項目筆記1

下載下傳開發依賴包👆,然後在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")
})
           

繼續閱讀