从项目开始学习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://xiahunao.cn/news/3015514.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【数据分享】2022年中国1km分辨率的河网密度数据(免费获取)

水系数据是我们在各项研究中经常使用的数据&#xff01;之前我们分享过一份来源于Open Street Map的2024年全国水系数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff01; 本次我们分享一份来源于Science Data Bank平台上的2022年中国1km分辨率的河网密度数据&am…

【正点原子Linux连载】 第四十章 Linux网络驱动实验 摘自【正点原子】ATK-DLRK3568嵌入式Linux驱动开发指南

1&#xff09;实验平台&#xff1a;正点原子ATK-DLRK3568开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id731866264428 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第四十…

java编程中,实现分页对象的类型转换

一、背景 当数据库分页查询返回的对象与接口要返回的对象类型不一致时&#xff0c;不可避免需要进行类型转换。 示例&#xff1a;数据库分页查询返回的对象是PageDTO&#xff0c;而接口返回的对象类型是PageVO。 PageDTO Data public class PageDTO<T> {/*** Current…

低代码系统能够解决哪些痛点?

不同的应用场景下&#xff0c;低代码系统解决的痛点是不一样的。工业应用场景中的组态软件应该说是最早的低代码系统了。以 Topstack 为代表的Web 组态软件&#xff0c;其核心功能设备数据采集、图形监控画面、数据报表、数据看板、业务逻辑开发等&#xff0c;都是无代码或低代…

观测云 VS ELK:谁是日志监控的王者?

前言 作为 IT 信息系统运行状态感知和故障分析的重要手段&#xff0c;日志在行业兴起之初便为运维和开发环节所广泛应用。当应用和系统发生故障或出现问题时&#xff0c;日志数据成为了排查和诊断问题的重要依据。通过分析日志&#xff0c;开发人员和运维人员可以了解系统的运…

Golang 开发实战day12 - Pointer

&#x1f3c6;个人专栏 &#x1f93a; leetcode &#x1f9d7; Leetcode Prime &#x1f3c7; Golang20天教程 &#x1f6b4;‍♂️ Java问题收集园地 &#x1f334; 成长感悟 欢迎大家观看&#xff0c;不执着于追求顶峰&#xff0c;只享受探索过程 Golang 开发实战day12 - 指针…

二十、Java内存泄漏概念、造成原因及检测方式(全)

文章目录 一、Java内存泄漏概念、造成原因及检测方式&#xff08;全&#xff09;二、其他1.jmap命令2.java VisualVM查看.hprof文件 一、Java内存泄漏概念、造成原因及检测方式&#xff08;全&#xff09; Java内存泄漏概念、造成原因及检测方式&#xff08;全&#xff09; 二…

去哪儿前端一面

谈谈你对mvvm的理解 MVVM分为三个部分:分别是M(Model,模型层 ),V(View,视图层),VM(ViewModel,V与M连接的桥梁,也可以看作为控制器) 1、 M:模型层,主要负责业务数据相关; 2、 V:视图层,顾名思义,负视图相关,细分下来就是html+css层; 3、 VM:V与M沟通的…

Rust 解决循环引用

导航 循环引用一、现象二、解决 循环引用 循环引用出现的一个场景就是你指向我&#xff0c;我指向你&#xff0c;导致程序崩溃 解决方式可以通过弱指针&#xff0c;而Rust中的弱指针就是Weak 在Rc中&#xff0c;可以实现&#xff0c;对一个变量&#xff0c;持有多个不可变引…

极致视觉盛宴,尽在Extreme Picture Finder!

在信息爆炸的时代&#xff0c;网络图片如同繁星点点&#xff0c;为我们的生活增添无尽的色彩。然而&#xff0c;如何在浩渺的网海中快速、准确地找到心仪的图片&#xff0c;却成了许多人的难题。此刻&#xff0c;Extreme Picture Finder如同一位贴心的向导&#xff0c;引领我们…

[一本Java+一本Java]5月7日简历指导直播

一、直播预告 每周二、四、六16:30简历指导直播&#xff0c;前美团项目负责人、校招VIP CEO-大拿老师在线讲简历优化 二、简历内容 三、简历核心问题 【简历1】一本- Java 1 虽然项目名称有一定的包装&#xff0c;两个项目的内容都是一眼能看出来的烂大街的项目&#xff0c…

AIP美国物理联合会文献在家如何查看下载

AIP&#xff08;美国物理联合会&#xff0c;American Institute of Physics&#xff09;成立于1931年&#xff0c;其主要任务是物理知识和应用的推广普及&#xff0c;也是世界上居于领导地位的物理期刊出版社之一。主要的研究方向为物理学和天文物理学。 今天有位同学求助一篇…

呆滞物料规范管理了,问题就好办了

对于制造企业来说&#xff0c;库存是生存和发展的重要保障&#xff0c;过高的库存会占用企业大量的资金和管理成本&#xff0c;影响企业的正常生产&#xff0c;然而多数中小制造企业还在用人工干预管理&#xff0c;如何控制呆滞物料成为仓储管理的一大难题。 什么是呆滞料 呆滞…

#LLM入门 | langchain | RAG # 4.3_文档分割

上一章讨论了文档标准化加载&#xff0c;现在转向文档的细分&#xff0c;这虽简单却对后续工作有重大影响。 一、为什么要进行文档分割 模型大小和内存限制&#xff1a;大型GPT模型参数众多&#xff0c;需大量计算和内存&#xff0c;而硬件设备如GPU或TPU有内存限制&#xff…

Linux下GraspNet复现流程

Linux&#xff0c;Ubuntu中GraspNet复现流程 文章目录 Linux&#xff0c;Ubuntu中GraspNet复现流程1.安装cuda和cudnn2.安装pytorch3.编译graspnetAPIReference &#x1f680;非常重要的环境配置&#x1f680; ubuntu 20.04cuda 11.0.1cudnn v8.9.7python 3.8.19pytorch 1.7.0…

花园牛奶:从靠谱奶牛到新鲜牛奶的匠心之旅

在花园乳业有限公司&#xff0c;我们深知生产出优质牛奶的秘诀——从靠谱的奶牛开始。为此&#xff0c;我们特意引进了品质卓越的荷斯坦奶牛&#xff0c;它们以“黑白花”的优雅身姿&#xff0c;成为了我们牧场上的明星。荷斯坦奶牛以其出色的生产性能和高产奶量而著称&#xf…

CoPilot 产品体验:提升 OpenNJet 的控制管理和服务提供能力

文章目录 前言系统架构介绍CoPilot 配置CoPilot 插件规范 体验 CoPilot 实例CoPilot: Broker 实例CoPilot: Ctrl 实例 开发其他语言编写的 CoPilot目标主要思路具体实现执行 go 程序代码 功能扩展总结 前言 CoPilot 是 OpenNJet 的一个重要组成部分&#xff0c;它在 Master-Wo…

机器学习之基于Python多种混合模型的糖尿病预测

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 糖尿病是一种慢性代谢性疾病&#xff0c;其发病率在全球范围内逐年上升&#xff0c;已成为影响人类健…

xmind的13个快捷方式

1.新建导图 CtrlshiftN 2.编辑文字 空格键 3.插入图片 Ctrli 4. 插入主题 Enter键 5. 插入主题之前 ShiftEnter键 6. 插入子主题 Tab键 7. 放大导图 “Ctrl”“” 8. 缩小导图 “Ctrl”“-” 9. 复制 CtrlInsert 10. 粘贴 Shift Insert 11. 剪切 ShiftDelete 12. 截图 F7 13. 保…

【论文阅读笔记】MAS-SAM: Segment Any Marine Animal with Aggregated Features

1.论文介绍 MAS-SAM: Segment Any Marine Animal with Aggregated Features MAS-SAM&#xff1a;利用聚合特征分割任何海洋动物 Paper Code(空的) 2.摘要 最近&#xff0c;分割任何模型&#xff08;SAM&#xff09;在生成高质量的对象掩模和实现零拍摄图像分割方面表现出卓越…