Vue中大型项目的总结

VUE概述

概述

Vue.js(/vjuː/,或简称为Vue)是一个用于创建用户界面的开源JavaScript框架,也是一个创建单页应用的Web应用框架。【这里有个小故事,在注册view时发现被占用了,后来用的view的德语vue】。2016年一项针对JavaScript的调查表明,Vue有着89%的开发者满意度。在GitHub上,该项目平均每天能收获95颗星,为Github有史以来星标数第3多的项目同时也是一款流行的JavaScript前端框架,旨在更好地组织与简化Web开发。Vue所关注的核心是MVC模式中的视图层,同时,它也能方便地获取数据更新,并通过组件内部特定的方法实现视图与模型的交互。

vue.js的核心是一个允许采用简洁的模板语法来声明地将数据渲染进dom系统

Vue.js 是采用 Object.defineProperty 的 getter 和 setter,并结合观察者模式来实现数据绑定的。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

image-20230826113425072

Observer :数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者,内部采用Object.defineProperty的getter和setter来实现
  

  • Compile :指令解析器,它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
      
  • Watcher :订阅者,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数
      
  • Dep :消息订阅器,内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update 方法

从图中可以看出,当执行 new Vue() 时,Vue 就进入了初始化阶段,一方面Vue 会遍历 data 选项中的属性,并用 Object.defineProperty 将它们转为 getter/setter,实现数据变化监听功能;另一方面,Vue 的指令编译器Compile 对元素节点的指令进行扫描和解析,初始化视图,并订阅 Watcher 来更新视图, 此时Wather 会将自己添加到消息订阅器中(Dep),初始化完毕。

当数据发生变化时,Observer 中的 setter 方法被触发,setter 会立即调用Dep.notify(),Dep 开始遍历所有的订阅者,并调用订阅者的 update 方法,订阅者收到通知后对视图进行相应的更新。


Vue核心特性
数据驱动(MVVM)(异步通信为主)

MVVM表示的是 Model-View-ViewModel。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当下流行的MVVM框架有:Vue.js、AngularJS。

MVVM即模型-视图-视图模型。

  • 模型指的是后端传递的数据;
  • 视图指的是所看到的页面。
  • 视图模型是mvvm模式的核心,它是连接view和model的桥梁。它有两个方向:一是将模型转化成视图,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将视图转化成模型,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。这两个方向都实现的,我们称之为数据的双向绑定。
  • Model:模型层,负责处理业务逻辑以及和服务器端进行交互,对应data中的数据,在这里表示JavaScript对象
  • View:视图层:负责将数据模型转化为UI展示出来,可以简单的理解为HTML页面,模板,在这里表示DOM(HTML操作的元素)
  • ViewModel:视图模型层,连接视图和数据的中间件,Vue.js 就是MVVM中的ViewModel层的实现者,Vue 实例对象

这时候需要一张直观的关系图,如下

image-20230826115024207

image-20230826115001249

在MVVM架构中,是不允许数据和视图直接通信的,只能通过ViewModel来通信,而ViewModel就是定义了一个Observer观察者。

  • ViewModel 能够观察到数据的变化,并对视图对应的内容进行更新
  • ViewModel 能够监听到视图的变化,并能够通知数据发生变化

Vue.js 就是一个MVVM的实现者,他的核心就是实现了DOM监听 与 数据的绑定。ViewModel的作用:

  1. 该层向上与视图层进行双向数据绑定
  2. 向下与Model 层通过接口请求进行数据交互

image-20230826115107334

MVVM的组成部分:

image-20230826115434324
组件化

什么是组件化?一句话来说就是把图形、非图形的各种逻辑均抽象为一个统一的概念(组件)来实现开发的模式,在Vue中每一个.vue文件都可以视为一个组件。组件化开发,让前端重复的使用的代码可以单独拎出来成为一个组件来供整个项目各个页面的使用,Css、JavaScript的脚本的内容可以限定作用的域,从而大幅度减少了开发的冲突问题

image-20230826143051944

  • 组件化的优势:
  • 降低整个系统的耦合度,在保持接口不变的情况下,我们可以替换不同的组件快速完成需求,例如输入框,可以替换为日历、时间、范围等组件作具体的实现
  • 调试方便,由于整个系统是通过组件组合起来的,在出现问题的时候,可以用排除法直接移除组件,或者根据报错的组件快速定位问题,之所以能够快速定位,是因为每个组件之间低耦合,职责单一,所以逻辑会比分析整个系统要简单
  • 提高可维护性,由于每个组件的职责单一,并且组件在系统中是被复用的,所以对代码进行优化可获得系统的整体升级
指令系统

解释:指令 (Directives) 是带有 v- 前缀的特殊属性作用:当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM

  • 常用的指令
  • 条件渲染指令 v-if
  • 列表渲染指令v-for
  • 属性绑定指令v-bind
  • 事件绑定指令v-on
  • 双向数据绑定指令v-model
VueJS提供的功能
  1. 虚拟DOM

VueJS使用了虚拟DOM,这个虚拟DOM也被React,Ember等其他框架所使用。这个改变不是在DOM上进行的,而是创建了一个以JavaScript数据结构形式存在的DOM副本。 每当进行任何更改时,都会对JavaScript数据结构进行更改,并将后者与原始数据结构进行比较。 然后,最终的更改将更新为真实的DOM,用户将看到这种变化。 这在优化方面是很好的,它比较容易,可以以更快的速度进行改变。

  1. 数据绑定

数据绑定功能可以帮助操纵或分配HTML属性的值,改变样式,通过VueJS提供的称为v-bind的绑定指令来分配类。

  1. 组件

组件是VueJS的重要功能之一,可以帮助创建可以在HTML中重用的自定义元素。

  1. 事件处理

v-on是添加到DOM元素以监听VueJS中的事件的属性。

  1. 动画/过渡

VueJS提供了多种方式来在向DOM元素添加/更新或删除HTML元素时应用转换。 VueJS有一个内置的转换组件,需要将其包装在元素中以获得转换效果。 我们可以轻松地添加第三方动画库,也可以为界面添加更多的交互性。

  1. 计算属性

这是VueJS的重要特性之一。 它有助于倾听对UI元素所做的更改并执行必要的计算。 这不需要额外的编码。

  1. 模板

VueJS提供基于HTML的模板,将DOM与Vue实例数据绑定。Vue将模板编译为虚拟DOM渲染功能。 我们可以使用渲染函数的模板,这样必须用渲染函数替换模板。

  1. 指令

VueJS有内置的指令,例如:v-if,v-else,v-show,v-on,v-bind和v-model,这些指令用于在前端执行各种操作。

  1. 观察者

观察者(Watcher)被应用于改变的数据。 例如,表单输入元素。 在这里不必添加任何额外的事件。 观察者负责处理任何数据更改,使代码简单快捷。

  1. 路由

页面之间的导航是在vue-router的帮助下完成的。

  1. 轻量级

VueJS脚本非常轻便,性能也非常快。

  1. Vue公司-CLI

可以使用vue-cli命令行界面在命令行安装VueJS。 这有助于使用vue-cli轻松构建和编译项目。

Vue工程框架

首先,vue.js是一个数据ue驱动视图的一个js框架,操作数据,然后实时反应到dom元素上的一个动态视图框架,它也是一个渐进式开发框架,比如,我用vue-cli搭建了一个本地开发环境,用nodejs跑了起来,当把vue引进来之后,要做项目还是远远不够的,就用到了vue全家桶。

UI框架 : Ant Design Vue
http请求工具:axios(个人推荐用这个)
cookie工具:vue-cookie
构建工具:vue-cli
路由插件:vue-router
状态管理工具:vuex / Pinia
滚动条插件:vuescroll
兼容IE的插件:babel-polyfill(当然vue只兼容到IE9+)

如果平时项目中你用到了哪些框架及插件,就可以通过npm install,下载下来,引入到项目中去就ok了

image-20230826105234645

  • build 文件夹:用于存放 webpack 相关配置和脚本。开发中仅 偶尔使用 到此文件夹下 webpack.base.conf.js 用于配置 less、sass等css预编译库,或者配置一下 UI 库。

  • config 文件夹:主要存放配置文件,用于区分开发环境、线上环境的不同。 常用到此文件夹下 config.js 配置开发环境的 端口号、是否开启热加载 或者 设置生产环境的静态资源相对路径、是否开启gzip压缩、npm run build 命令打包生成静态资源的名称和路径等。

  • dist 文件夹:默认 npm run build 命令打包生成的静态资源文件,用于生产部署。

  • node_modules:存放npm命令下载的开发环境和生产环境的依赖包。

  • src: 存放项目源码及需要引用的资源文件。

  • src下assets:存放项目中需要用到的资源文件,css、js、images等。

  • src下componets:存放vue开发中一些公共组件:header.vue、footer.vue等。

  • src下emit:自己配置的vue集中式事件管理机制。

  • src下router:vue-router vue路由的配置文件。

  • src下service:自己配置的vue请求后台接口方法。

  • src下page:存在vue页面组件的文件夹。

  • src下util:存放vue开发过程中一些公共的.js方法。

  • src下vuex:存放 vuex 为vue专门开发的状态管理器。

  • src下app.vue:使用标签渲染整个工程的.vue组件。

  • src下main.js:vue-cli工程的入口文件。

  • index.html:设置项目的一些meta头信息和提供

    用于挂载 vue 节点。

  • package.json:用于 node_modules资源部 和 启动、打包项目的 npm 命令管理。

434f7a8ff9ea491b9b3ac162b418a302
  • beforeCreate

详细:在实例初始化之后,数据观测(data observer)和event/watcher事件配置之前的调用

  • created

详细:在实例创建完成后被立即调用,在这一步,实例已经完成以下的配置:数据观测(data observer),属性和方法的运算,watch/event事件回调,$el属性目前不可见。

  • beforeMount

详细:在挂载开始之前被调用:相关的render函数首次被调用 该钩子在服务器端渲染期间不被调用。

  • mounted

详细: el被新创建的vm.

el替换 ,并挂载到实例上去之后调用该钩子。如果root实例挂载了一个文档内元素,当mounted被调用时vm.el替换,并挂载到实例上去之后调用该钩子。如果root实例挂载了一个文档内元素,当mounted被调用时vm.el也在文档内。
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted:

mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}

钩子在服务器端渲染期间不被调用。

  • beforeUpdate

详细:数据更新时调,发生在虚拟DOM打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。

  • updated

详细
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。

注意 updated 不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉 updated:

updated: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-rendered
})
}

该钩子在服务器端渲染期间不被调用。

  • activated

详细:
keep-alive 组件激活时调用。

该钩子在服务器端渲染期间不被调用.

  • beforeDestroy

详细:实例销毁之前调用。在这一步,实例仍然完全可用。

该钩子在服务器端渲染期间不被调用。

  • destroy

详细:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

该钩子在服务器端渲染期间不被调用。

  • errorCaptured

类型:(err: Error, vm: Component, info: string) => ?boolean
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

你可以在此钩子中修改组件的状态。因此在模板或渲染函数中设置其它内容的短路条件非常重要,它可以防止当一个错误被捕获时该组件进入一个无限的渲染循环。

技术栈:

  1. 基于 @vue/cli 搭建基础模板(大家都比较了解,节省开发时间,远胜于从零开始搭建)。
  2. 开发一些中大型的系统,vue-router 和 vuex 都是必不可少的。
  3. 快速开发UI组件库 Element UI 或Ant Design Vue(相对美观一点)。
  4. 工具库选择 lodash。
  5. 根据业务需求自己定义封装各种开发中可能用到的功能,
    如:
  • 组件库
  • 状态管理
  • 过滤器
  • 指令
  • CSS内置变量
  • 表单验证
  • 工具函数

样式:

CSS 预处理器的选择:
  1. Sass/Scss
  2. Less
  3. Stylus

公司更倾向于使用 scss 开发,less 是为了覆盖 ant design vue 的样式,stylus 比较少人用。

局部样式与全局样式:
  • 局部样式:
    一般都是使用 scoped 方案:
<style lang="scss" scoped>
@import "base.css";
  ...
</style>
  • 全局样式:

    • variable.scss: 全局变量管理

    • mixins.scss: 全局 Mixins 管理

    • global.scss: 全局样式

其中 variable.scss 和 mixins.scss 会优先于 global.css 加载,并且可以不通过 import 的方式在项目中任何位置使用这些变量和 mixins。

// vue.config.js
module.exports = {
  css: {
    loaderOptions: {
      sass: {
        prependData: `
        @import '@/styles/variable.scss';
        @import '@/styles/mixins.scss';
        `,
      },
    },
  },
}

异步请求:

封装 Axios:

是Vue插件能够支持发起异步数据传输和接口交互,是一个基于promise的http库,用于前后端交互。

在 @/libs/request.js 路径下对 Axios 进行封装,封装了请求参数,请求头,以及错误提示信息、 request 拦截器、response 拦截器、统一的错误处理、baseURL 设置等。

import axios from 'axios';
import get from 'lodash/get';
import storage from 'store';
// 创建 axios 实例
const request = axios.create({
 // API 请求的默认前缀
 baseURL: process.env.VUE_APP_BASE_URL,
 timeout: 10000, // 请求超时时间
});
// 异常拦截处理器
const errorHandler = (error) => {
 const status = error.response?.status//缩写,表示如果error.response存在就拿error.response.status
 switch (status) {
   case 400: error.message = '请求错误'; break;
   case 401: error.message = '未授权,请登录'; break;
   case 403: error.message = '拒绝访问(登录过期,请重新登录)'; break;
   case 404: error.message = `请求地址出错,未找到资源: ${error.response.config.url}`; break;
   case 405: error.message = '请求方法未允许'; break;
   case 408: error.message = '请求超时'; break;
   case 500: error.message = '服务器内部错误'; break;
   case 501: error.message = '服务未实现'; break;
   case 502: error.message = '网关错误'; break;
   case 503: error.message = '服务不可用'; break;
   case 504: error.message = '网关超时'; break;
   case 505: error.message = 'HTTP版本不受支持'; break;
   default: break;
 }
 return Promise.reject(error);
};
// 声明一个 Map 用于存储每个请求的标识 和 取消函数
const pending = new Map()
/**
 * 添加请求
 * @param {Object} config 
 */
const addPending = (config) => {
    const url = [
        config.method,
        config.url,
        JSON.stringify(config.params),
        JSON.stringify(config.data)
    ].join('&')
    config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
        if (!pending.has(url)) { // 如果 pending 中不存在当前请求,则添加进去
            pending.set(url, cancel)
        }
    })
}
/**
 * 移除请求
 * @param {Object} config 
 */
const removePending = (config) => {
    const url = [
        config.method,
        config.url,
        JSON.stringify(config.params),
        JSON.stringify(config.data)
    ].join('&')
    console.log('url=', url)
    if (pending.has(url)) { // 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
        const cancel = pending.get(url)
        cancel(url)
        pending.delete(url)
    }
}
/**
 * 清空 pending 中的请求(在路由跳转时调用)
 */
export const clearPending = () => {
    for (const [url, cancel] of pending) {
        cancel(url)
    }
    pending.clear()
}
/** 
 * 请求拦截器 
 * 每次请求前,如果存在token则在请求头中携带token 
 */
request.interceptors.request.use((config) => {
		removePending(config) // 在请求开始前,对之前的请求做检查取消操作
    	addPending(config) // 将当前请求添加到 pending 中
        //Vue.ls本地储存的工具包
        const token = Vue.ls.get('ACCESS_TOKEN')
        if (token) {
            config.headers['Authorization'] = 'Bearer ' + token // 
        }
        return config;
}, errorHandler);

// 响应拦截器
request.interceptors.response.use((response) => {
 removePending(response.config) // 在请求结束后,移除本次请求
 const dataAxios = response.data;
 // 这个状态码是和后端约定的
 const { code } = dataAxios;
 // 根据 code 进行判断
 if (code === undefined) {
   // 如果没有 code 代表这不是项目后端开发的接口
   return dataAxios;
 } else {
   // 有 code 代表这是一个后端接口 可以进行进一步的判断
   switch (code) {
     case 200:
       // code === 200 代表没有错误
       return dataAxios.data;
     case 'xxx':
       // [ 示例 ] 其它和后台约定的 code
       return 'xxx';
     default:
       return '不是正确的code';
   }
 }
}, errorHandler);
export default request;

应用实例:

export const getBanner = () => {
    return instance({
        method: 'get',
        url: 'public/v1/home/swiperdata',
        params: {
            firstName: 'Fred',
            lastName: 'Flintstone'
        }
    });
}

将clearPending()方法添加到vue路由钩子函数中:

router.beforeEach(async (to, from, next) => {
    clearPending()
    next();
});

跨域问题:

跨域问题一般情况直接找后端解决了,你要是不好意思打扰他们的话,可以用 devServer 提供的 proxy 代理:

不过proxy只能在开发环境使用,线上还得后端处理设置cors(如:Nodejs:res.header(“Access-Control-Allow-Origin”,"*"了解更多,点击这里),允许我们访问。

// vue.config.js
devServer: {
  proxy: {
    '/api': {
      target: 'http://47.100.186.132/your-path/api',
      ws: true,
      changeOrigin: true,
      pathRewrite: {
        '^/api': ''
      }
    }
  }
}

Mock 数据:

一个很常见的情况,后端接口没出来,前端在这干瞪眼。

Mock 数据功能是基于 mock.js (opens new window)开发,通过 webpack 进行自动加载 mock 配置文件。

规则:

  • 所有的 mock 配置文件均应放置在 @/mock/services 路径内
  • 在 @/mock/services 内部可以建立业务相关的文件夹分类存放配置文件
  • 所有的配置文件应按照 ***.mock.js 的命名规范创建
  • 配置文件使用 ES6 Module 导出 export default 或 export 一个数组

入口文件:

import Mock from 'mockjs';
Mock.setup({
  timeout: '500-800',
});
const context = require.context('./services', true, /.mock.js$/);
context.keys().forEach((key) => {
  Object.keys(context(key)).forEach((paramKey) => {
    Mock.mock(...context(key)[paramKey]);
  });
});

import Mock from 'mockjs';
const { Random } = Mock;
export default [
  RegExp('/example.*'),
  'get',
  {
    'range|50-100': 50,
    'data|10': [
      {
        // 唯一 ID
        id: '@guid()',
        // 生成一个中文名字
        cname: '@cname()',
        // 生成一个 url
        url: '@url()',
        // 生成一个地址
        county: Mock.mock('@county(true)'),
        // 从数组中随机选择一个值
        'array|1': ['A', 'B', 'C', 'D', 'E'],
        // 随机生成一个时间
        time: '@datetime()',
        // 生成一张图片
        image: Random.dataImage('200x100', 'Mock Image'),
      },
    ],
  },
];

es6:

新的javaScript语言标准,规定了语言的组成部分:语法、类型、语句、关键字、保留字、操作符、对象,在原有es5上做了延伸和拓展,使js可以用来编写复杂的大型应用程序。

路由:

布局三大类:

vue的核心插件,主要用于实现页面的跳转功能,让构建单页面应用变得简单。

  • frameIn:基于 BasicLayout,通常需要登录或权限认证的路由。
  • frameOut:不需要动态判断权限的路由,如登录页或通用页面。
  • errorPage:例如404页面。
动态路由原理:

路由需要分成两类,静态路由和动态路由。静态路由是任何菜单权限下都能查看的界面路由;动态路由是根据菜单权限动态生成的路由集合。

大体步骤:拦截路由->后台取到路由->保存路由到localStorage或vuex(用户登录进来只会从后台取一次,其余都从本地取,所以用户,只有退出在登录路由才会更新)

核心:beforeEach、addRoutes、localStorage

import axios from 'axios'

var getRouter //用来获取后台拿到的路由

router.beforeEach((to, from, next) => {
  if (!getRouter) {//不加这个判断,路由会陷入死循环
    if (!getObjArr('router')) {
      axios.get('https://www.easy-mock.com/mock/5a5da330d9b48c260cb42ca8/example/antrouter').then(res => {
        getRouter = res.data.data.router//后台拿到路由
        saveObjArr('router', getRouter) //存储路由到localStorage

        routerGo(to, next)//执行路由跳转方法
      })
    } else {//从localStorage拿到了路由
      getRouter = getObjArr('router')//拿到路由
      routerGo(to, next)
    }
  } else {
    next()
  }

})


function routerGo(to, next) {
  getRouter = filterAsyncRouter(getRouter) //过滤路由
  router.addRoutes(getRouter) //动态添加路由
  global.antRouter = getRouter //将路由数据传递给全局变量,做侧边栏菜单渲染工作
  next({ ...to, replace: true })
}

function saveObjArr(name, data) { //localStorage 存储数组对象的方法
  localStorage.setItem(name, JSON.stringify(data))
}

function getObjArr(name) { //localStorage 获取数组对象的方法
  return JSON.parse(window.localStorage.getItem(name));

}

或者vue3.0:

import { createRouter, createWebHashHistory } from "vue-router";
import {clearPending} from '../axios'

// 静态路由
const initRouter = [
    {
        path: "/",
        name: "login",
        component: () => import("@/views/login.vue"),
    },
    {
        path: "/home",
        name: "home",
        component: () => import("@/views/home.vue"),
    },
];
// 动态路由
const asyncRouter = [
    {
        path: "/a",
        name: "a",
    },
    {
        path: "/b",
        name: "b",
    },
];
const asyncRouterList = function () {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(asyncRouter)
        }, 300)
    })
}
const router = createRouter({
    history: createWebHashHistory(),
    routes: initRouter,
});

router.beforeEach(async (to, from, next) => {
    //路由跳转前,清空请求
    clearPending()
    // 请求后台路由
    const a = await asyncRouterList()
    //添加请求到的路由
    a.forEach(i => {
        router.options.routes.push(i);
        router.addRoute(i.name, i);
    })
    next();
});
export default router;

权限验证:

通过获取当前用户的权限去比对路由表,生成当前用户具的权限可访问的路由表,通过 router.addRoutes 动态挂载到 router 上。

  • 判断页面是否需要登陆状态,需要则跳转到 /user/login
  • 本地存储中不存在 token 则跳转到 /user/login
  • 如果存在 token,用户信息不存在,自动调用 vuex ‘/system/user/getInfo’

在路由中,集成了权限验证的功能,需要为页面增加权限时,在 meta 下添加相应的 key:

  • 1.auth

(类型:Boolean):当 auth 为 true 时,此页面需要进行登陆权限验证,只针对 frameIn 路由有效。

  • 2.permissions

(类型:Object):permissions 每一个 key 对应权限功能的验证,当 key 的值为 true 时,代表具有权限,若 key 为 false,配合 v-permission 指令,可以隐藏相应的 DOM。

import router from '@/router';
import store from '@/store';
import Vuefrom 'Vue';
import util from '@/libs/utils';
// 进度条
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
const loginRoutePath = '/user/login';
const defaultRoutePath = '/home';
/**
 * 路由拦截
 * 权限验证
 */
router.beforeEach(async (to, from, next) => {
  // 进度条
  NProgress.start();
  // 验证当前路由所有的匹配中是否需要有登录验证的
  if (to.matched.some((r) => r.meta.auth)) {
    // 是否存有token作为验证是否登录的条件
    const token = Vue.ls.get('ACCESS_TOKEN');
    if (token && token !== 'undefined') {
      // 是否处于登录页面
      if (to.path === loginRoutePath) {
        next({ path: defaultRoutePath });
        // 查询是否储存用户信息
      } else if (Object.keys(store.state.system.user.info).length === 0) {
        store.dispatch('system/user/getInfo').then(() => {
          next();
        });
      } else {
        next();
      }
    } else {
      // 没有登录的时候跳转到登录界面
      // 携带上登陆成功之后需要跳转的页面完整路径,方便登录后直接回到该页面
      next({
        name: 'Login',
        query: {
          redirect: to.fullPath,
        },
      });
      NProgress.done();
    }
  } else {
    // 不需要身份校验 直接通过
    next();
  }
});
router.afterEach((to) => {
  // 进度条
  NProgress.done();
  util.title(to.meta.title);
});

Vuex:

vue的核心插件,主要用于集中式管理数据,类似全局对象,所有组件都可以使用它中的数据。一般在构建大型应用中使用,将项目中组件共享的状态抽取出来,核心是store仓库,包含应用的state。

内置一些功能,主要是对以下这些功能做了一些封装:

  • 用户信息管理(储存信息、对 token 进行操作等)
  • 登陆(调接口)
  • 菜单管理(储存路由信息,生成菜单,模糊查询等功能)
  • 日志管理(消息提醒、日志留存、日志上报)
  • 全屏操作

组件库:

可手动封装复用组件

  • 数字动画
  • 大文件上传(切片、断点续传、秒传)需要与后端配合
  • 图片预览
  • Excel 导入导出
  • 富文本编辑器
  • pdf 生成 及预览
  • 国际化 vue-i18n
    等等…

过滤器:

过滤器是 Vue 提供的一个很好用的功能,vue3 已去除。

  • 格式化时间
  • 格式化数字金额
  • 格式化文本
    区分环境的链接(主要针对本地静态资源服务器和 OSS )

指令:

  • 组件权限验证
  • 文本复制
  • 图片懒加载
  • 焦点,文本框聚焦
  • 滚动至指定位置
  • 快捷键绑定
posted @ 2023-09-04 13:49  德琪  阅读(73)  评论(0编辑  收藏  举报