Vue生态及实践 - 配置中心

news2024/9/29 3:27:21

目录

目标

配置中心

config/config.js

皮肤/国际化

config/theme.js

config/language.js

app.js

App.vue

权限管理

src/views/about.vue

src/views/403.vue

config/permission.js

src/router.js

src/store.js

献上一张通过ai生成的图片~


目标

  1. 配置中心
  2. 皮肤/国际化
  3. 权限控制

配置中心

config/config.js

// config/config.js
class Config {
  constructor() {// 构造函数
    this._config = {};
  }
  regist(type, value) { // 注册配置
    this._config[type] = value;
  }
  get(type) { // 获取配置
    return this._config[type];
  }
}
// 返回一个单例
export default new Config();

皮肤/国际化

config/theme.js

// config/theme.js
// 皮肤配置
import config from "./config";
// 启动加载数据
export const init = () => {
  config.regist("theme", {
    blue: {
      primary: "#007fff",
      highlight: "#00a6ff",
    },
    red: {
      primary: "#A83733",
      highlight: "rgb(195, 75, 73)",
    },
  });
};

config/language.js

// config/language.js
// 国际化,(中英切换)
import config from "./config";
import { LIST_TYPE } from "../module/topic/store";
export const init = () => {
  config.regist("language", {
    Chinese: {
      navs: [
        {
          name: "热门",
          path: LIST_TYPE.HOT,
        },
        {
          name: "最新",
          path: LIST_TYPE.NEW,
        },
        {
          name: "热榜",
          path: LIST_TYPE.TOP,
        },
        {
          name: "关于我",
          path: "about",
        },
      ]
    },
    English: {
      navs: [
        {
          name: "pop",
          path: LIST_TYPE.HOT,
        },
        {
          name: "new",
          path: LIST_TYPE.NEW,
        },
        {
          name: "hot",
          path: LIST_TYPE.TOP,
        },
        {
          name: "aboutMe",
          path: "about",
        },
      ]
    },
  });
};

app.js

import Vue from "vue";
import App from "./App.vue";
import { createStore } from "./store";
import { createRouter } from "./router";
import intersect from "./directive/intersect";
// 皮肤配置,初始化方法init重命名为themeInit
import { init as themeInit } from "./config/theme";
// 国际化
import { init as languageInit } from "./config/language";
// 权限
import { init as permissionInit } from "./config/permission";
// 注册指令
Vue.directive("intersect", intersect);
// app.$mount("#app");
export function createApp() {
  const store = createStore();
  const router = createRouter({ store });
  // 应用初始化之前,初始化皮肤相关配置信息
  themeInit();
  // 应用初始化之前,初始化国际化相关配置信息
  languageInit();
  // 初始化权限
  permissionInit();
  const app = new Vue({
    store,
    router,
    render: (h) => h(App),
  });
  return {
    app,
    store,
    router,
  };
}

App.vue

<template>
  <div id="app">
    <div class="m-top" :style="{ backgroundColor: theme.primary }">
      <u-link
        class="m-link"
        :style="{
          backgroundColor:
            $route.name === nav.path ? theme.highlight : theme.primary,// 读取配置
        }"
        v-for="nav in language.navs"
        :key="nav.path"
        :to="nav.path"
        :prefetch="true"
        >{{ nav.name }}</u-link>
    </div>
    <div class="m-content">
      <u-keep-alive max="2">
        <router-view></router-view>
      </u-keep-alive>
    </div>
    <div class="m-side">
      主题切换:
      <button @click="themeType = 'red'">红</button>
      <button @click="themeType = 'blue'">蓝</button>
    </div>
  </div>
</template>
<script>
import UTopic from "./module/topic/views/UTopic.vue";
import { LIST_TYPE } from "./module/topic/store";
import config from "./config/config";// 读取配置
export default {
  components: {
    UTopic,
  },
  data() {
    return {
      themeType: "blue",
      languageType: "Chinese",
    };
  },
  //provide 全局注入主题颜色;
  //inject: ["theme"]获取;这个方案不对响应式数据进行传递
  // 用于一次性启动的配置,在生命周期中不进行修改
  // 性能考虑
  provide() { 
    return {
      theme: this.theme,
    };
  },
  computed: {
    theme() {
      return config.get("theme")[this.themeType];// 读取配置
    },
    language() {
      return config.get("language")[this.languageType];
    },
  },
};
</script>
<style>
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
    Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
  margin: 0;
  overflow-y: scroll;
}
a {
  text-decoration: none;
  color: #007fff;
}
.m-top {
  height: 60px;
  width: 100%;
  background: #007fff;
}
.m-content {
  width: 360px;
  border: 1px solid #eee;
  background: #fff;
  margin: 20px auto;
  padding: 0 20px;
}
.m-link {
  display: inline-block;
  color: #fff;
  height: 60px;
  line-height: 60px;
  font-size: 19px;
  padding: 0 20px;
}
.router-link-active {
  background: #00a6ff;
}
.m-side {
  position: fixed;
  left: 50%;
  margin-left: 220px;
  top: 100px;
}
</style>

权限管理

src/views/about.vue

<template>
  <div class="about">
    about me!!!
    <input type="text" v-model="x" />
  </div>
</template>
<script>
export default {
  data() {
    return {
      x: "",
    };
  },
};
</script>
<style scoped>
.about {
  padding: 30px;
  text-align: center;
}
</style>

src/views/403.vue

<template>
  <div class="stop">无权限访问页面</div>
</template>
<style scoped>
.stop {
  padding: 30px;
  text-align: center;
}
</style>

config/permission.js

// config/permission.js
// 权限配置文件
import config from "./config";
// 暴漏常量
export const PERMISSION_MAP = {
  ABOUT_PAGE: Symbol("ABOUT_PAGE"),
};
export const init = () => {
  config.regist("permission", {
    CEO: {
      [PERMISSION_MAP.ABOUT_PAGE]: true,
    },
    COO: {
      [PERMISSION_MAP.ABOUT_PAGE]: false,
    },
  });
};
// 获取身份权限
export const getPermissionByRole = (role) => config.get("permission")[role];

src/router.js

import Vue from "vue";
import VueRouter from "vue-router";
import { routes as topic } from "./module/topic/router";
import { PERMISSION_MAP, getPermissionByRole } from "./config/permission";
import store from "./store";
import { compose } from "./util/compose";
Vue.use(VueRouter);
export function createRouter({ store }) {
    // 1. 获取当前角色
  const getRole = () => store.state.user.role;
  	// 2.获取当前权限getPermissionByRole
  const getPermission = (permission) =>
    // 3.当前obj[permission]是否在PERMISSION_MAP上,从右往左执行
    compose((obj) => obj[permission], getPermissionByRole, getRole)();
  return new VueRouter({
    mode: "history",
    routes: [
      ...topic,
      {
        name: "about",
        path: "/about",
        component: () => import(/* webpackChunkName:"about" */ "./views/UAbout.vue"),
        beforeEnter(to, from, next) {  // 守卫钩子
          // 如果有权限就去to页面,没有就去403页面
          getPermission(PERMISSION_MAP.ABOUT_PAGE) ? next() : next("403");
        },
      },
      {
        name: "403",
        path: "/403",
        component: () => import(/* webpackChunkName:"403" */ "./views/403.vue"),
      },
      {
        path: "/",
        redirect: "/hot",
      },
    ],
  });
}

src/store.js

// 全局单例store
import Vue from "vue";
import Vuex from "vuex";
import { store as topic } from "./module/topic/store";
Vue.use(Vuex);
export function createStore() {
  return new Vuex.Store({
    state: {
      user: {
        role: "CEO",// 假装在后端请求到的身份
      },
    },
    modules: {
      topic,
    },
  });
}

分享的文章多是学习过程中记录的coding && 笔记~

献上一张通过ai生成的图片~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/730536.html

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

相关文章

编译SecureValueRecovery项目

准备 下载 git clone https://codeup.aliyun.com/6306306f95064d67d44656e5/lxr1907/SecureValueRecovery.git 进入目录 cd SecureValueRecovery编译enclave make -C ./enclave等待很长时间下载各种镜像后 报错&#xff1a; Fatal error: cant create build/kbupd_enclave_t.o:…

Dubbo详解,用心看这一篇文章就够了【重点】

1.1 Dubbo概述 Dubbo是阿里巴巴开源的基于 Java 的高性能RPC&#xff08;一种远程调用&#xff09; 分布式服务框架&#xff0c;致力于提供高性能和透明化的RPC远程服务调用方案&#xff0c;以及SOA服务治理方案。 每天为2千多个服务提供大于30亿次访问量支持&#xff0c;并被…

DataFun:数据基础架构

翼支付 数据向量化 经营范围是否相同 背景特征提取器 质量过滤通用背景过滤预制场景标记 虚假地址风险分析 CCKS地址解析标签体系 FaissMilvus余弦相似度 Zilliz 大模型幻觉问题 极限科技

数据结构与算法_堆排序

堆排序&#xff0c;即利用堆的思想来进行排序。要实现堆排序&#xff0c;首先要建堆&#xff0c;建堆又分为建大堆和建小堆&#xff1b;然后再一步一步地删除堆的元素来进行排序。 目录 一、堆排序的时间复杂度 二、建堆 向上调整 向下调整 三、堆排序 四、代码实现 向…

ROS-Moveit和Gazebo联合仿真(二)

文章目录 URDF功能包配置configlaunchCMakeLists.txtpackage.xmlurdf文件 Moveit功能包配置configlaunch 运行 URDF功能包配置 config 首先在SW2URDF生成的功能包下Config目录下新建文件joint_trajectory_controller.yaml robot_arm_controller:type: "position_contro…

51单片机--利用独立按键控制LED

文章目录 独立按键的原理独立按键控制LED灯的状态按键抖动控制LED灯的状态 独立按键控制二进制独立按键控制移位 独立按键的原理 独立按键是一种基本的电子元件&#xff0c;它通常由一个按钮和两个引脚组成。在单片机中&#xff0c;我们可以将按键的一个引脚连接到某个IO口&…

基于单片机智能台灯坐姿矫正器视力保护器的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;LCD1602液晶显示当前当前光线强度、台灯灯光强度、当前时间、坐姿距离等&#xff1b;按键设置当前时间&#xff0c;闹钟、提醒时间、坐姿最小距离&#xff1b;通过超声波检测坐姿&#xff0c;当坐姿不正容易对眼睛和身体腰部等造成…

《MySQL》表的约束

文章目录 空属性null 和 默认值列描述zerofill主键和auto_increment唯一键外键 空属性null 和 默认值 空属性null是MySQL里面特有表示空信息的一个属性。 空属性比较的方法&#xff1a;<> &#xff0c;is not/is null&#xff0c;真返回1&#xff0c;否则返回零 一个字段…

大模型高效训练基础知识:梯度检查点(Gradient Checkpointing)

prerequiste: 大模型训练基础知识&#xff1a;梯度累积&#xff08;Gradient Accumulationn&#xff09; 梯度检查点&#xff08;Gradient Checkpointing&#xff09; 如今&#xff08;2023年&#xff09;大模型的参数量巨大&#xff0c;即使将batch_size设置为1并使用梯度累积…

【点云配准】刚性物体的鲁棒姿态估计

目录 什么是刚性物体的鲁棒姿态估计&#xff1f; 刚性物体的姿态估计时可能会遇到的问题及解决方法&#xff1a; 采样一致性&#xff08;SAC&#xff09;算法的原理 预配准采样一致性&#xff08;Prerejective Sample Consensus, PRSAC&#xff09;算法的原理 SAC算法与PRS…

Java用for循环打印三角形菱形

目录 一、打印矩形 二、打印直角三角形 1.直角三角形 2.打印九九乘法表 三、打印等腰三角形 四、打印平行四边形 五、打印菱形 六、打印两个直角三角形 1.打印两个直角三角形 2.打印倒着的两个直角三角形 七、打印“蝴蝶” 一、打印矩形 //打印矩形for (int i 0; i < a;…

[USACO23FEB] Equal Sum Subarrays G

题目描述 FJ gave Bessie an array aa of length N ( 2 ≤ N ≤ 500 , − 1 0 15 ≤ a i ≤ 1 0 15 ) N(2≤N≤500,−10^{15}≤ai≤10^{15}) N(2≤N≤500,−1015≤ai≤1015) with all N ( N 1 ) 2 \frac{N(N1)}2 2N(N1)​​ contiguous subarray sums distinct. For each i…

【随手记】使用Flask做代理为虚拟机提供pip源

最近在重做虚拟机环境&#xff0c;虚拟机不可连外网&#xff0c;最初python包都是通过离线whl进行安装。但是离线文件已经找不到了&#xff0c;不想重新去一个个下载&#xff0c;而且本地环境跟虚拟机环境也不一致&#xff0c;pip download可能会遇到版本问题&#xff0c;遂考虑…

【SQL】群辉 NAS 安装 Mysql 远程访问连接

群辉安装MySQL具有高效、安全、可靠、灵活等优势&#xff0c;可以为用户提供一个优秀的数据管理和分析环境。同时具有良好的硬件性能和稳定性&#xff0c;可以保障MySQL数据库的高效运行和数据安全. cpolar 是一款内网穿透工具,通过简单的设置,我们即可实现远程访问群辉中mysq…

地下饮用水除硝酸盐技术、生活用水提质增效

项目名称 北京某地下水除硝酸盐项目&#xff0c;出水未检出 工艺选择 两处水源&#xff0c;运行方式为一用一备 工艺原理 树脂官能团耐受硫酸盐、氯离子的干扰&#xff0c;实现选择性吸附硝酸根 项目背景 近年来由于农业活动及排污物的影响&#xff0c;部分地表…

qt---应用窗口创建

运行结果&#xff1a; 此处仅显示widget.cpp文件的代码 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {this->setFixedSize(500,500); //设置固定尺寸this->setWindowTitle("QQ2024");//设置标题this->setWindowIcon(Q…

c++语言基本语法

今天&#xff0c;我带来c语言基本语法。互联网流行着一个段子&#xff0c;求职者在自己的简历上写精通c&#xff0c;面试官看完以后&#xff0c;微微一笑&#xff0c;疯狂拷问&#xff0c;最后&#xff0c;求职的人回答不出来一两个问题。正如段子所表达的意思&#xff0c;c语言…

【Java基础】CAS (Compare And Swap) 操作

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、使用场景四、原理五、优劣5.1 缺点&#xff1…

【Linux之拿捏信号2】核心转储文件core dump

文章目录 核心转储文件的概念ulimit命令Term和core 核心转储文件的概念 Linux系统级别提供了一种能力&#xff0c;在一个进程出现异常的时候&#xff0c;OS可以将该异常进程的核心代码部分进行核心转储&#xff0c;将内存中进程的相关代码数据&#xff0c;全部dump到磁盘中&am…

飞桨出海!百度飞桨携手联合国教科文组织共促全球高等教育数字化进程

百度飞桨响应联合国教科文组织&#xff0c;积极践行“共商、共建、共享”的全球合作理念&#xff0c;紧跟全球教育创新的步伐&#xff0c;推出面向全球高校教学人员的微认证英文课程——《AI科普与零代码实践》。百度基于丰厚的人工智能技术沉淀打造了本系列课程&#xff0c;携…