從項目開始學習Vue——02(若依框架)

往期:
從項目開始學習Vue——01

目錄標題

    • 一、基礎插件
    • (一)路由Vue Router
    • (二)導航守衛(路由攔截器)
    • 二、Vuex
    • (一)什么是Vuex
        • Vuex的部分介紹內容:
    • (二)何時使用Vuex
    • (三)具體使用
      • State
      • getter
      • mutation
      • Action
      • Module
    • 三、element-ui
    • 四、布局插件
    • 五、js-cookie的使用方法
    • 六、Axios
    • 七、加密jsencrypt
    • 八、加載進度nprogress
    • 九、自定義vue指令,實現權限控制
    • 十、vue組件
    • 十一、其他
    • 十二、一邊學,一邊做(仿制若依框架)

一、基礎插件

(一)路由Vue Router

Vue Router 官方文檔

Vue Router 的作用簡單來說就是在同一個頁面中實現不同模塊頁面的動態加載,不需要刷新頁面和新建標簽頁。

比如這種系統:可以在同一個頁面加載不同模塊的頁面,打開、切換和關閉頁面都非常流暢,用戶體驗性大大提高。(單頁面系統SPA

若以開源框架地址
在這里插入圖片描述

一個簡單的demo。利用element-ui和Vue Router 實現

一般來說我們的頁面不可能像demo一樣簡單丑陋,一般需要結合layout(布局)使用,需要添加側邊導航欄,頂部導航欄,內容展示欄,個人中心欄,設置欄等。

(二)導航守衛(路由攔截器)

路由前攔截器

路由后攔截器

一個例子:

/*** 路由攔截器* */
import store from '../store'
import router from './index'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'NProgress.configure({ showSpinner: false })const whiteList = ['/login', '/register']//添加一個導航鉤子,它會在每次路由之前被執行。返回一個用來移除該鉤子的函數。//to: 即將要進入的目標 用一種標準化的方式
// from: 當前導航正要離開的路由 用一種標準化的方式
//在之前的 Vue Router 版本中,還可以使用 第三個參數 next
// 。這是一個常見的錯誤來源,我們經過 RFC 討論將其移除。
// 然而,它仍然是被支持的,這意味著你可以向任何導航守衛傳遞第三個參數。
// 在這種情況下,確保 next 在任何給定的導航守衛中都被嚴格調用一次。
// 它可以出現多于一次,但是只能在所有的邏輯路徑都不重疊的情況下,否則鉤子永遠都不會被解析或報錯。
router.beforeEach((to, from, next) => {//開啟加載進度條NProgress.start()if (getToken()) {/* has token*/if (to.path === '/login') {next({ path: '/' })NProgress.done()} else {if (store.state.user.roles.length === 0) {// 判斷當前用戶是否已拉取完user_info信息store.dispatch('GetInfo').then(() => {next({ path: '/' })}).catch(err => {store.dispatch('LogOut').then(() => {Message.error(err)next({ path: '/' })})})} else {next()}}} else {// 沒有tokenif (whiteList.indexOf(to.path) !== -1) {// 在免登錄白名單,直接進入next()} else {// 否則全部重定向到登錄頁next('/login')NProgress.done()}}
})//路由后
router.afterEach(() => {NProgress.done()
})

守衛方法()三個重要參數

  1. to: 即將要進入的目標
  2. from: 當前導航正要離開的路由
  3. next :在之前的 Vue Router 版本中,還可以使用 第三個參數 next 。這是一個常見的錯誤來源,我們經過 RFC 討論將其移除。然而,它仍然是被支持的,這意味著你可以向任何導航守衛傳遞第三個參數。在這種情況下,確保 next 在任何給定的導航守衛中都被嚴格調用一次。它可以出現多于一次,但是只能在所有的邏輯路徑都不重疊的情況下,否則鉤子永遠都不會被解析或報錯。

在這里插入圖片描述

二、Vuex

Vuex官網

(一)什么是Vuex

在這里插入圖片描述

如果你有了解過vue框架提供的狀態管理: store 模式 那么Vuex理解起來十分簡單,他們的作用是基本一致的。

Vuex 中管理的變量(內容)是全局唯一的,也就是單例模式。不同頁面獲取這個變量的內容都是一致的。

Vuex的部分介紹內容:

在這里插入圖片描述

(二)何時使用Vuex

如果您需要構建一個中大型單頁應用,您很可能會考慮如何更好地在組件外部管理狀態,Vuex 將會成為自然而然的選擇。

下面這種就是單頁應用:
在這里插入圖片描述

(三)具體使用

由以下部分組成:
在這里插入圖片描述

State

存儲在 Vuex 中的數據和 Vue 實例中的 data 遵循相同的規則。
創建

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: {name: 'lihua',},getters: {},mutations: {},actions: {},modules: {}
})

在vue中調用state:
通過在根實例中注冊 store 選項,該 store 實例會注入到根組件下的所有子組件中,且子組件能通過 this.$store 訪問到。讓我們更新下 Counter 的實現:

  1. 在根實例中注冊 store 選項
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'Vue.config.productionTip = falsenew Vue({router,store, // 在根實例中注冊 store 選項render: function (h) { return h(App) }
}).$mount('#app')
  1. 調用:
<template><div><div>{{name}}</div><button v-on:click="onEvent">獲取Vuex State變量</button></div>
</template><script>export default {data() {return {name: '1',}},name: 'HelloWorld',props: {msg: String},methods: {onEvent: function () {this.name = this.$store.state.name// console.log(this.$store.state.name)},},}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>

getter

Vuex 允許我們在 store 中定義“getter”(可以認為是 store 的計算屬性)。就像計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。
在這里插入圖片描述

具體使用

mutation

更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,并且它會接受 state 作為第一個參數:

在這里插入圖片描述

Action

Action 類似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接變更狀態。
  • Action 可以包含任意異步操作。

Module

為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割:

例子:
在這里插入圖片描述

三、element-ui

官方文檔

四、布局插件

Vue Grid Layout -? 適用Vue.js的柵格布局系統

五、js-cookie的使用方法

js-cookie的使用方法

這個插件多用于保存一下token到瀏覽器的cookie中

例子:

import Cookies from 'js-cookie'const TokenKey = 'Admin-Token'export function getToken() {return Cookies.get(TokenKey)
}export function setToken(token) {return Cookies.set(TokenKey, token)
}export function removeToken() {return Cookies.remove(TokenKey)
}

六、Axios

Axios 是一個基于 promise 網絡請求庫

一個例子:

import axios from 'axios'
import { Notification, MessageBox, Message, Loading } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import cache from '@/utils/cache'axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 創建axios實例
const service = axios.create({// axios中請求配置有baseURL選項,表示請求URL公共部分// 請求路徑前綴,一般從.env.production .env.development 環境變量中獲取// baseURL: process.env.VUE_APP_BASE_API,baseURL:'/dev-api',// 超時timeout: 10000
})
/*** 參數處理* @param {*} params  參數*/
function tansParams(params) {let result = ''for (const propName of Object.keys(params)) {const value = params[propName];var part = encodeURIComponent(propName) + "=";if (value !== null && value !== "" && typeof (value) !== "undefined") {if (typeof value === 'object') {for (const key of Object.keys(value)) {if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {let params = propName + '[' + key + ']';var subPart = encodeURIComponent(params) + "=";result += subPart + encodeURIComponent(value[key]) + "&";}}} else {result += part + encodeURIComponent(value) + "&";}}}return result
}
// request攔截器
service.interceptors.request.use(config => {// 是否需要設置 tokenconst isToken = (config.headers || {}).isToken === false// 是否需要防止數據重復提交const isRepeatSubmit = (config.headers || {}).repeatSubmit === falseif (getToken() && !isToken) {config.headers['Authorization'] = 'Bearer ' + getToken() // 讓每個請求攜帶自定義token 請根據實際情況自行修改}// get請求映射params參數if (config.method === 'get' && config.params) {let url = config.url + '?' + tansParams(config.params);url = url.slice(0, -1);config.params = {};config.url = url;}//防止重復提交if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {const requestObj = {url: config.url,data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,time: new Date().getTime()}const sessionObj = cache.session.getJSON('sessionObj')if (sessionObj === undefined || sessionObj === null || sessionObj === '') {cache.session.setJSON('sessionObj', requestObj)} else {const s_url = sessionObj.url;                  // 請求地址const s_data = sessionObj.data;                // 請求數據const s_time = sessionObj.time;                // 請求時間const interval = 1000;                         // 間隔時間(ms),小于此時間視為重復提交if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {const message = '數據正在處理,請勿重復提交';console.warn(`[${s_url}]: ` + message)return Promise.reject(new Error(message))} else {cache.session.setJSON('sessionObj', requestObj)}}}return config
}, error => {console.log(error)Promise.reject(error)
})// 響應攔截器
service.interceptors.response.use(res => {// 未設置狀態碼則默認成功狀態const code = res.data.code || 200;// 獲取錯誤信息const msg = errorCode[code] || res.data.msg || errorCode['default']// 二進制數據則直接返回if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {return res.data}if (code === 401) {MessageBox.confirm('登錄狀態已過期,您可以繼續留在該頁面,或者重新登錄', '系統提示', { confirmButtonText: '重新登錄', cancelButtonText: '取消', type: 'warning' }).then(() => {}).catch(() => {});return Promise.reject('無效的會話,或者會話已過期,請重新登錄。')} else if (code === 500) {Message({ message: msg, type: 'error' })return Promise.reject(new Error(msg))} else if (code === 601) {Message({ message: msg, type: 'warning' })return Promise.reject('error')} else if (code !== 200) {Notification.error({ title: msg })return Promise.reject('error')} else {return res.data}},error => {console.log('err' + error)let { message } = error;if (message === "Network Error") {``message = "后端接口連接異常";} else if (message.includes("timeout")) {message = "系統接口請求超時";} else if (message.includes("Request failed with status code")) {message = "系統接口" + message.substr(message.length - 3) + "異常";}Message({ message: message, type: 'error', duration: 5 * 1000 })return Promise.reject(error)}
)export default service

七、加密jsencrypt

可以用于加密前端賬號、密碼和一些敏感信息。

import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'// 密鑰對生成 http://web.chacuo.net/netrsakeypairconst publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +'UP8iWi1Qw0Y='// 加密
export function encrypt(txt) {const encryptor = new JSEncrypt()encryptor.setPublicKey(publicKey) // 設置公鑰return encryptor.encrypt(txt) // 對數據進行加密
}// 解密
export function decrypt(txt) {const encryptor = new JSEncrypt()encryptor.setPrivateKey(privateKey) // 設置私鑰return encryptor.decrypt(txt) // 對數據進行解密
}

八、加載進度nprogress

在這里插入圖片描述

可以在請求攔截器中使用

import NProgress from 'nprogress'
import 'nprogress/nprogress.css'NProgress.configure({ showSpinner: false })
router.beforeEach((to, from, next) => {//開啟加載進度條NProgress.start() 
})//路由后
router.afterEach(() => {// 關閉進度條NProgress.done()
})

九、自定義vue指令,實現權限控制

在這里插入圖片描述
hasPermi.js

 /*** v-hasPermi 操作權限處理* Copyright (c) 2019 ruoyi*/import store from '@/store'export default {inserted(el, binding, vnode) {const { value } = bindingconst all_permission = "*:*:*";const permissions = store.getters && store.getters.permissionsif (value && value instanceof Array && value.length > 0) {const permissionFlag = valueconst hasPermissions = permissions.some(permission => {return all_permission === permission || permissionFlag.includes(permission)})if (!hasPermissions) {el.parentNode && el.parentNode.removeChild(el)}} else {throw new Error(`請設置操作權限標簽值`)}}
}

匯總指令
index.js

import hasRole from './permission/hasRole'
import hasPermi from './permission/hasPermi'const install = function(Vue) {Vue.directive('hasRole', hasRole)Vue.directive('hasPermi', hasPermi)
}if (window.Vue) {window['hasRole'] = hasRolewindow['hasPermi'] = hasPermiVue.use(install); // eslint-disable-line
}export default install

在main.js中導入

import directive from './directive' // directiveVue.use(directive)

使用

<div  v-hasPermi="['system:user:edit']" >111</div>
<div  v-has-permi="['1:2:3']" >111</div>

十、vue組件

https://www.cnblogs.com/cq1715584439/p/11734041.html

十一、其他

新手可能像我一樣對js文件里面的 import 、export 、export default 有些懵逼。

其實看名字就能大概猜出他們的意思,一個是導入、一個是導出。

如果有大量js文件,那么js之間的變量、函數、對象、類應該如果調用和管理呢。如果js文件很多,js之間調來調去就會很亂,可維護性很低。這個時候就凸顯出import 、export 字段的用處了,如果一個js,需要引入其他js的變量、函數,那么你就用import 導入一個變量、函數、對象。export 、export default 與 import 相反,就是你需要給這個 js 導出什么給外部js調用。

其他更多可以參考這篇了解

十二、一邊學,一邊做(仿制若依框架)

未完結
在這里插入圖片描述

**注意:**需要啟動后端接口,去拉取若依后端代碼,并啟動

代碼位置

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/9909.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/9909.shtml
英文地址,請注明出處:http://en.pswp.cn/web/9909.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

QQ超大文件共享(別用,傳進去后,壓縮都顯示不出來,LJ qq!)(共享文件)

文章目錄 需要共享雙方同時在線開啟方法第一次會提示設置默認共享目錄&#xff0c;默認是E:\QQFileShare\<qq號>\&#xff1a;然后新建共享會在其后創建共享目錄&#xff0c;共享目錄中只能共享文件。需要點擊添加文件&#xff0c;直接把文件拷貝到目錄里好像還不行&…

C語言/數據結構——(相交鏈表)

一.前言 今天在力扣上刷到了一道題&#xff0c;想著和大家一起分享一下這道題——相交鏈表https://leetcode.cn/problems/intersection-of-two-linked-lists廢話不多說&#xff0c;讓我們開始今天的分享吧。 二.正文 1.1題目描述 是不是感覺好長&#xff0c;我也這么覺得。哈…

網絡編程套接字和傳輸層tcp,udp協議

認識端口號 我們知道在網絡數據傳輸的時候&#xff0c;在IP數據包頭部有兩個IP地址&#xff0c;分別叫做源IP地址和目的IP地址。IP地址是幫助我們在網絡中確定最終發送的主機&#xff0c;但是實際上數據應該發送到主機上指定的進程上的&#xff0c;所以我們不僅要確定主機&…

OAuth 2.0 和 OAuth 2.1

OAuth 2.0 和 OAuth 2.1比較&#xff1a; OAuth 2.0 和 OAuth 2.1 是授權框架的不同版本&#xff0c;它們用于允許應用程序安全地訪問用戶在另一個服務上的數據。以下是它們之間的一些主要區別&#xff1a; 安全性增強&#xff1a;OAuth 2.1 旨在提高安全性&#xff0c;它整合…

什么是云原生架構,我們該如何做好云原生安全,引領云計算時代的應用程序革新

隨著云計算技術的飛速發展&#xff0c;企業面臨著前所未有的機遇和挑戰。在這個高度競爭的市場中&#xff0c;傳統的應用程序架構因其僵化、不易擴展和維護的特點&#xff0c;已難以滿足當今企業對靈活性、可伸縮性和高效性的追求。在這樣的背景下&#xff0c;云原生架構應運而…

git rebase 合并當前分支的多個commit記錄

git rebase 合并當前分支的多個commit記錄 git rebase 相關的選項和用法step1&#xff1a;找到想要合并的 commitstep2. 使用 rebase -istep3. 編輯提交歷史&#xff1a;step4.編輯合并后的提交信息step5.完成 rebase 過程&#xff1a;step6.**推送更新&#xff1a;**step6.**再…

使用ollama離線部署小模型

在有網的機器下載ollama和模型 啟動服務 docker run --rm -it -v ./ollama:/root/.ollama -p 8000:11434 --name ollama ollama/ollama下載模型 docker exec -it ollama ollama pull qwen:0.5b將鏡像和ollama目錄復制到離線的機器中 docker啟動ollama服務 驗證 curl ht…

FFmpeg常用API與示例(三)—— 音視頻解碼與編碼

編解碼層 1.解碼 (1) 注冊所有容器格式和 CODEC:av_register_all() (2) 打開文件:av_open_input_file() (3) 從文件中提取流信息:av_find_stream_info() (4) 窮舉所有的流&#xff0c;查找其中種類為 CODEC_TYPE_VIDEO (5) 查找對應的解碼器:avcodec_find_decoder() (6) …

C++ 實現以xml的格式寫入文件

C XML類 該類主要將xml中的標簽分為兩類&#xff0c;無內容標簽統一稱為父標簽&#xff0c;有內容的就以鍵值對的方式直接輸出。 后面可能會優化通過函數參數的方式管控層級關系&#xff0c;現在是通過類里自動記錄層級深度來表示的。 #include <fstream> #include <…

【QT教程】QT6硬件圖形界面編程 QT硬件編程

QT6硬件圖形界面編程 使用AI技術輔助生成 QT界面美化視頻課程 QT性能優化視頻課程 QT原理與源碼分析視頻課程 QT QML C擴展開發視頻課程 免費QT視頻課程 您可以看免費1000個QT技術視頻 免費QT視頻課程 QT統計圖和QT數據可視化視頻免費看 免費QT視頻課程 QT性能優化視頻免費看…

數據結構-二叉樹結尾+排序

一、二叉樹結尾 1、如何判斷一棵樹是完全二叉樹。 我們可以使用層序遍歷的思路&#xff0c;利用一個隊列&#xff0c;去完成層序遍歷&#xff0c;但是這里會有些許的不同&#xff0c;我們需要讓空也進隊列。如果隊列里到最后只剩下空那么這棵樹就是完全二叉樹。具體的實現如下…

js 數據格式轉換,對象轉數組,數組轉對象

1.對象轉數組 // 對象obj轉換成數組格式 let obj { orgCode:分局編碼, alertId:告警ID, name:告警名稱 } let arr [] for(let key in obj) { console.log(11,key,obj[key]); // 定義一個對象&#xff0c;賦值 let o { id: key, // key是obj對象的鍵值 label: obj[key] …

學習Vue 3.0中的onMounted和onUnmounted鉤子函數

學習Vue 3.0中的onMounted和onUnmounted鉤子函數 一、什么是onMounted和onUnmounted&#xff1f;二、如何使用onMounted和onUnmounted&#xff1f;1、使用onMounted2、使用onUnmounted 三、總結 一、什么是onMounted和onUnmounted&#xff1f; Vue 3.0帶來了許多令人興奮的新特…

Modal h函數寫法

Modal h函數寫法 if (res.data.flag) {const ocapWarn res.data.ocaplList;Modal.warning({title: "提示",content: h("div", {}, [ocapWarn.map((item, index) > {return h("div", {}, [h("p",${index 1}、${item.defectItem}(…

IntersectionObserver對象

IntersectionObserver對象 IntersectionObserver對象&#xff0c;從屬于Intersection Observer API&#xff0c;提供了一種異步觀察目標元素與其祖先元素或頂級文檔視窗viewport交叉狀態的方法&#xff0c;祖先元素與視窗viewport被稱為根root&#xff0c;也就是說Intersectio…

c#---多態

在 C#語言中體現多態有三種方式&#xff1a;虛方法&#xff0c;抽象類&#xff0c; 接口 一、虛方法 什么是虛方法&#xff1f; 在父類中使用 virtual 關鍵字修飾的方法&#xff0c; 就是虛方法。在子類中可以使用 override 關鍵字對該虛方法進行重寫。 class Animal {public…

android apk沒有源碼如何修改程序

如果您擁有一個APK文件但沒有源代碼&#xff0c;您可以嘗試以下幾種方法來進行修改&#xff1a; 反編譯APK&#xff1a;使用工具如apktool對APK文件進行反編譯&#xff0c;這將為您提供源代碼和資源文件。 動態調試&#xff1a;使用調試工具連接設備或模擬器&#xff0c;并動態…

重裝前端整體流程

用戶管理 --匯總 -- 明細-CSDN博客 一、node 這個看環境變量 2023最新版Node.js下載安裝及環境配置教程&#xff08;非常詳細&#xff09;從零基礎入門到精通&#xff0c;看完這一篇就夠了_nodejs安裝及環境配置-CSDN博客 配置到國內鏡像的時候&#xff0c;去看&#xff0c;淘…

理解固化的Maven依賴:spring-boot-starter-parent 與 spring-boot-dependencies

目錄 理解固化的Maven依賴&#xff1a;spring-boot-starter-parent 與 spring-boot-dependencies1. spring-boot-starter-parent1.1 簡介1.2 特點 2. spring-boot-dependencies2.1 簡介2.2 特點 3. 異同點對比3.1 相同點3.2 不同點案例一&#xff1a;使用 spring-boot-starter-…

Java方法的重載

方法重載 1. 為什么需要方法重載 public class TestMethod{public static void main (String[] args){int a 10;int b 20;int ret add(a,b);System.out.println("ret "ret);double a2 10.5;double b2 20.5;double ret2 add(a2,b2);System.out.println("…