vue3后台管理系统[vue管理界面]
2023年07月24日 03:32
欧易okx交易所下载
欧易交易所又称欧易OKX,是世界领先的数字资产交易所,主要面向全球用户提供比特币、莱特币、以太币等数字资产的现货和衍生品交易服务,通过使用区块链技术为全球交易者提供高级金融服务。
最近有一位之前找过的用户问了我们小编的一个问题,我相信这也是很多币圈朋友经常会疑惑的问题:vue3后台管理系统相关问题,vue管理界面相关问题,带着这一个问题,让专业的小编告诉您原因。
# vue+element 后台管理系统-折叠侧边导航栏
## 1. 在头部组件中添加折叠按钮
**template:**
“`javascript
template
!– 折叠按钮 —
div class=”01a3-22aa-5e18-8b73 collapse-btn” @click=”collapseChage”
? ? i v-if=”!collapse” class=”22aa-5e18-8b73-d3d7 bg-icon bg-icon-el-icon-s-fold”/i
? ? i v-else class=”5e18-8b73-d3d7-3941 bg-icon bg-icon-el-icon-s-unfold”/i
/div
/template
“`
**script:**
“`javascript
script
// 通过bus通信
import eventBus from “@/utils/eventBus/eventBus.js”
data() {
? ? ? return {
? ? ? ? ? collapse: false,
? ? ? }
},
methods: {
? ? // 侧边栏折叠
? collapseChage() {
? ? ? this.collapse = !this.collapse;
? ? ? eventBus.$emit(‘collapse’, this.collapse);
? },
}
/script
“`
## 2. 在侧边导航栏的组件中添加控制的属性
**template:**
“`javascript
template
? ? el-menu class=”8b73-d3d7-3941-5b68 hc-menu” :collapse=”collapse”
? ? ? el-menu-item class=”d3d7-3941-5b68-9232 hc-menu-item”导航一/el-menu-item
? ? ? el-menu-item class=”3941-5b68-9232-b8db hc-menu-item”导航二/el-menu-item
? ? ? el-menu-item class=”5b68-9232-b8db-bc66 hc-menu-item”导航三/el-menu-item
? ? /el-menu
/template
“`
**script:**
“`javascript
script
// 通过bus通信
import eventBus from “@/utils/eventBus/eventBus.js”
data() {
? ? ? return {
? ? ? ? ? collapse: false,
? ? ? }
},
created() {
? ? eventBus.$on(‘collapse’, msg = {
? ? ? ? this.collapse = msg;
? ? });
}
/script
“`
当在做后台管理系统时,经常需要做到点击记住密码,然后登录进入系统后,一番操作后退出系统希望能够自动的记住上次登录的账号密码,这个功能实现并不算复杂。
记住密码的选项的值动态的绑定一个checked值,这个值默认为false,当选中的时候才去赋予一个true值,然后通过这个值当登录将账号密码提交的时候,根据checked的布尔值将账号密码存到本地存储中,如果为true则存账号密码,如果为false,则存个空对象进去。当用户操作完退出登录时,会退到登录页,此时会执行一次login组件的生命周期,就可以在生命周期中将本地存的值再次重新赋予到登录页的表单中去,这样就实现了登录时记住密码的功能。
3.1.1、登录的表单
3.1.2、从父组件接收过来的数据
loginForm:表单的账号密码的数据,hasChecked:是否选择记住密码
3.1.3、登录表单的校验
3.1.4、深度监听登录表单form
主要是监听退回登录页时,看表单页的数据是否填充,如果有数据填充,触发监听,并且执行init()初始化表单的方法。
3.1.5、init初始化
将选项布尔值重新赋值
3.2.1、子组件的引入
3.2.2、判断本地缓存中是否有数据,有的话那么就在生命周期中去给表单项进行赋值操作
3.2.4、提交按钮进行的逻辑操作
这部分需要判断是否选择了记住密码,如果勾选了,那么就将当前的账号密码存入,如果没有,那么就存入个空对象,一方面清空之前存入的账号密码,另一方面保证了下次登录不会带入数据。
3.2.5、保存用户设置的方法
这个方法是去保存用户是否勾选了记住密码的
最后大致的功能就实现了,当然为了安全性,最好在存入本地之前进行md5加密(其他的加密也行,比如:AES加密),然后在生命周期去赋值的时候再去进行解密赋值到表单项上去,这样安全性就提升了。
vue后台管理系统打开全屏界面方法:
首先安装系统全屏插件screenfull,安装完成后。在点击全屏这个事件上,做操作,引入插件,在点击事件上直接复制,这样我们的点击全屏功能就可以打开了。
Vue是一个目前比较流行的前端框架,在业界也算很有名气,今天这里为大家罗列一下基于Vue的后端管理的框架。使用这些框架你会发现它包括了我们常用的路由,状态,交互等等,我们只需要去复用它的代码,加上一下我们自己少量的逻辑就能轻松的完成项目。
会为你节约更多时间喝喝咖啡等,给你一种“框架在手,天下我有”的感觉。
vue后台的其他功能:
登录鉴权功能是后台管理项目的基本需求,登录控制,权限分配,这些都是很普遍的功能。 在框架中已经做好了这部分的工作,我们来了解一下是怎么做的,对以后在框架的基础上做改进是有很大的帮助的。
Passport项目是一个基于Nodejs的认证中间件,支持本地登录和第三方账号登录验证。Passport目的只是为了“登陆认证”,因此,代码干净,易维护,可以方便地集成到其他的应用中。
首先在app.vue里面有这么一段然后你所点击的按钮其实是这个东西,这个其实就是个封装完的a标签你在router里面配置完了相关路由之后就能在点击这个按钮的时候将router-view标签里面的组件替换掉了
一个星期左右。用vue重构一个中小型后台管理系统,无论是现在前端还是后端的角度,做一个后台管理系统,开发过程中的代码复用性远远大于开发前台程序,时间在一个星期左右。
响应式是 Vue 的特色,如果你简历里写了 Vue 项目,那基本都会问响应式实现原理。
而且不只是 Vue,状态管理库 Mobx 也是基于响应式实现的。
那响应式是具体怎么实现的呢?
与其空谈原理,不如让我们来手写一个简易版吧。
响应式
首先,什么是响应式呢?
响应式就是被观察的数据变化的时候做一系列联动处理。
就像一个 社会 热点事件,当它有消息更新的时候,各方媒体都会跟进做相关报道。
这里 社会 热点事件就是被观察的目标。
那在前端框架里,这个被观察的目标是什么呢?
很明显,是状态。
状态一般是多个,会通过对象的方式来组织。所以,我们观察状态对象的每个 key 的变化,联动做一系列处理就可以了。
我们要维护这样的数据结构:
图片
状态对象的每个 key 都上述文章内容就是联的一系列 effect 副作用函数,也就是变化的时候联动执行的逻辑,通过 Set 来组织。
每个 key 都是这样关联了一系列 effect 函数,那多个 key 就可以放到一个 Map 里维护。
这个 Map 是在对象存在的时候它就存在,对象销毁的时候它也要跟着销毁。(因为对象都没了自然也不需要维护每个 key 关联的 effect 了)
而 WeakMap 正好就有这样的特性,WeakMap 的 key 必须是一个对象,value 可以是任意数据,key 的对象销毁的时候,value 也会销毁。
所以,响应式的 Map 会用 WeakMap 来保存,key 为原对象。
这个数据结构就是响应式的核心数据结构了。
比如这样的状态对象:
const obj = {
a: 1,
b: 2
}
它的响应式数据结构就是这样的:
const depsMap = new Map();
const aDeps = new Set();
depsMap.set(‘a’, aDeps);
const bDeps = new Set();
depsMap.set(‘b’, bDeps);
const reactiveMap = new WeakMap()
reactiveMap.set(obj, depsMap);
创建出的数据结构就是图中的那个:
图片
图片
然后添加 deps 依赖,比如一个函数依赖了 a,那就要添加到 a 的 deps 集合里:
effect(() = {
console.log(obj.a);
});
也就是这样:
const depsMap = reactiveMap.get(obj);
const aDeps = depsMap.get(‘a’);
aDeps.add(该函数);
这样维护 deps 功能上没啥问题,但是难道要让用户手动添加 deps 么?
那不但会侵入业务代码,而且还容易遗漏。
所以肯定不会让用户手动维护 deps,而是要做自动的依赖收集。
那怎么自动收集依赖呢?
读取状态值的时候,就建立了和该状态的依赖关系,所以很容易想到可以代理状态的 get 来实现。
通过 Object.defineProperty 或者 Proxy 都可以:
const data = {
a: 1,
b: 2
}
let activeEffect
function effect(fn) {
activeEffect = fn
fn()
}
const reactiveMap = new WeakMap()
const obj = new Proxy(data, {
get(targetObj, key) {
let depsMap = reactiveMap.get(targetObj);
if (!depsMap) {
reactiveMap.set(targetObj, (depsMap = new Map()))
}
let deps = depsMap.get(key)
if (!deps) {
depsMap.set(key, (deps = new Set()))
}
deps.add(activeEffect)
return targetObj[key]
}
})
effect 会执行传入的回调函数 fn,当你在 fn 里读取 obj.a 的时候,就会触发 get,会拿到对象的响应式的 Map,从里面取出 a 对应的 deps 集合,往里面添加当前的 effect 函数。
这样就完成了一次依赖收集。
当你修改 obj.a 的时候,要通知所有的 deps,所以还要代理 set:
set(targetObj, key, newVal) {
targetObj[key] = newVal
const depsMap = reactiveMap.get(targetObj)
if (!depsMap) return
const effects = depsMap.get(key)
effects effects.forEach(fn = fn())
}
基本的响应式完成了,我们测试一下:
图片
打印了两次,第一次是 1,第二次是 3。
effect 会先执行一次传入的回调函数,触发 get 来收集依赖,这时候打印的 obj.a 是 1
然后当 obj.a 赋值为 3 后,会触发 set,执行收集的依赖,这时候打印 obj.a 是 3
依赖也正确收集到了:
图片
结果是对的,我们完成了基本的响应式!
当然,响应式不会只有这么点代码的,我们现在的实现还不完善,还有一些问题。
比如,如果代码里有分支切换,上次执行会依赖 obj.b 下次执行又不依赖了,这时候是不是就有了无效的依赖?
这样一段代码:
const obj = {
a: 1,
b: 2
}
effect(() = {
console.log(obj.a ? obj.b : ‘nothing’);
});
obj.a = undefined;
obj.b = 3;
第一次执行 effect 函数,obj.a 是 1,这时候会走到第一个分支,又依赖了 obj.b。
把 obj.a 修改为 undefined,触发 set,执行所有的依赖函数,这时候走到分支二,不再依赖 obj.b。
把 obj.b 修改为 3,按理说这时候没有依赖 b 的函数了,我们执行试一下:
图片
第一次打印 2 是对的,也就是走到了第一个分支,打印 obj.b
第二次打印 nothing 也是对的,这时候走到第二个分支。
但是第三次打印 nothing 就不对了,因为这时候 obj.b 已经没有依赖函数了,但是还是打印了。
打印看下 deps,会发现 obj.b 的 deps 没有清除
图片
所以解决方案就是每次添加依赖前清空下上次的 deps。
怎么清空某个函数关联的所有 deps 呢?
记录下就好了。
我们改造下现有的 effect 函数:
let activeEffect
function effect(fn) {
activeEffect = fn
fn()
}
记录下这个 effect 函数被放到了哪些 deps 集合里。也就是:
let activeEffect
function effect(fn) {
const effectFn = () = {
activeEffect = effectFn
fn()
}
effectFn.deps = []
effectFn()
}
对之前的 fn 包一层,在函数上添加个 deps 数组来记录被添加到哪些依赖集合里。
get 收集依赖的时候,也记录一份到这里:
图片
这样下次再执行这个 effect 函数的时候,就可以把这个 effect 函数从上次添加到的依赖集合里删掉:
图片
cleanup 实现如下:
function cleanup(effectFn) {
for (let i = 0; i effectFn.deps.length; i++) {
const deps = effectFn.deps[i]
deps.delete(effectFn)
}
effectFn.deps.length = 0
}
effectFn.deps 数组记录了被添加到的 deps 集合,从中删掉自己。
全删完之后就把上次记录的 deps 数组置空。
我们再来测试下:
图片
无限循环打印了,什么鬼?
问题出现在这里:
图片
set 的时候会执行所有的当前 key 的 deps 集合里的 effect 函数。
而我们执行 effect 函数之前会把它从之前的 deps 集合中清掉:
图片
执行的时候又被添加到了 deps 集合。
这样 delete 又 add,delete 又 add,所以就无限循环了。
解决的方式就是创建第二个 Set,只用于遍历:
图片
这样就不会无限循环了。
再测试一次:
图片
现在当 obj.a 赋值为 undefined 之后,再次执行 effect 函数,obj.b 的 deps 集合就被清空了,所以需改 obj.b 也不会打印啥。
看下现在的响应式数据结构:
图片
确实,b 的 deps 集合被清空了。
那现在的响应式实现是完善的了么?
也不是,还有一个问题:
如果 effect 嵌套了,那依赖还能正确的收集么?
首先讲下为什么要支持 effect 嵌套,因为组件是可以嵌套的,而且组件里会写 effect,那也就是 effect 嵌套了,所以必须支持嵌套。
我们嵌套下试试:
effect(() = {
console.log(‘effect1’);
effect(() = {
console.log(‘effect2’);
obj.b;
});
obj.a;
});
obj.a = 3;
按理说会打印一次 effect1、一次 effect2,这是最开始的那次执行。
然后 obj.a 修改为 3 后,会触发一次 effect1 的打印,执行内层 effect,又触发一次 effect2 的打印。
也就是会打印 effect1、effect2、effect1、effect2。
我们测试下:
图片
打印了 effect1、effet2 这是对的,但第三次打印的是 effect2,这说明 obj.a 修改后并没有执行外层函数,而是执行的内层函数。
为什么呢?
看下这段代码:
图片
我们执行 effect 的时候,会把它赋值给一个全局变量 activeEffect,然后后面收集依赖就用的这个。
当嵌套 effect 的时候,内层函数执行后会修改 activeEffect 这样收集到的依赖就不对了。
怎么办呢?
嵌套的话加一个栈来记录 effect 不就行了?
也就是这样:
图片
执行 effect 函数前把当前 effectFn 入栈,执行完以后出栈,修改 activeEffect 为栈顶的 effectFn。
这样就保证了收集到的依赖是正确的。
这种思想的应用还是很多的,需要保存和恢复上下文的时候,都是这样加一个栈。
我们再测试一下:
图片
现在的打印就对了。
至此,我们的响应式系统就算比较完善了。
全部代码如下:
const data = {
a: 1,
b: 2
}
let activeEffect
const effectStack = [];
function effect(fn) {
const effectFn = () = {
cleanup(effectFn)
activeEffect = effectFn
effectStack.push(effectFn);
fn()
effectStack.pop();
activeEffect = effectStack[effectStack.length – 1];
}
effectFn.deps = []
effectFn()
}
function cleanup(effectFn) {
for (let i = 0; i effectFn.deps.length; i++) {
const deps = effectFn.deps[i]
deps.delete(effectFn)
}
effectFn.deps.length = 0
}
const reactiveMap = new WeakMap()
const obj = new Proxy(data, {
get(targetObj, key) {
let depsMap = reactiveMap.get(targetObj)
if (!depsMap) {
reactiveMap.set(targetObj, (depsMap = new Map()))
}
let deps = depsMap.get(key)
if (!deps) {
depsMap.set(key, (deps = new Set()))
}
deps.add(activeEffect)
activeEffect.deps.push(deps);
return targetObj[key]
},
set(targetObj, key, newVal) {
targetObj[key] = newVal
const depsMap = reactiveMap.get(targetObj)
if (!depsMap) return
const effects = depsMap.get(key)
// effects effects.forEach(fn = fn())
const effectsToRun = new Set(effects);
effectsToRun.forEach(effectFn = effectFn());
}
})
总结
响应式就是数据变化的时候做一系列联动的处理。
核心是这样一个数据结构:
图片
最外层是 WeakMap,key 为对象,value 为响应式的 Map。这样当对象销毁时,Map 也会销毁。
Map 里保存了每个 key 的依赖集合,用 Set 组织。
我们通过 Proxy 来完成自动的依赖收集,也就是添加 effect 到对应 key 的 deps 的集合里。set 的时候触发所有的 effect 函数执行。
这就是基本的响应式系统。
但是还不够完善,每次执行 effect 前要从上次添加到的 deps 集合中删掉它,然后重新收集依赖。这样可以避免因为分支切换产生的无效依赖。
并且执行 deps 中的 effect 前要创建一个新的 Set 来执行,避免 add、delete 循环起来。
此外,为了支持嵌套 effect,需要在执行 effect 之前把它推到栈里,然后执行完出栈。
解决了这几个问题之后,就是一个完善的 Vue 响应式系统了。
当然,现在虽然功能是完善的,但是没有实现 computed、watch 等功能,之后再实现。
最后,再来看一下这个数据结构,理解了它就理解了 vue 响应式的核心:
图片
相信经过小编对vue3后台管理系统和vue管理界面的介绍,你对vue3后台管理系统了解更加地透彻了,感谢你对我们地支持与关注!
推荐阅读
-
公安比特币病毒(公安比特币病毒最新消息)
1970-01-01
deps) { depsMap.set(key, (deps = new Set())) }deps.add(activ...
-
比特币交易赌博,比特币交易算赌博吗
1970-01-01
deps) { depsMap.set(key, (deps = new Set())) }deps.add(activ...
-
达程国际期货a50手续费,达程国际期货a50手续费多少
1970-01-01
deps) { depsMap.set(key, (deps = new Set())) }deps.add(activ...
-
格林大华期货电话 格林大华期货有限公司
1970-01-01
deps) { depsMap.set(key, (deps = new Set())) }deps.add(activ...
-
比特币每天开采量?比特币每天开采量多少
1970-01-01
deps) { depsMap.set(key, (deps = new Set())) }deps.add(activ...
-
菜粕期货供过于求 菜粕期货价格下跌
1970-01-01
deps) { depsMap.set(key, (deps = new Set())) }deps.add(activ...