Vue3 项目相关

vite 项目起步式

npm create vite

  - 1.命名项目名称
  - 2. 选择技术框架
  - 3. 进入项目文件夹 npm i 安装依赖,
  - 4. npm run dev 运行项目

Vue3 项目相关_第1张图片

配置 package.json 文件 ,使项目运行后自动再浏览器中打开。

在 dev 运行命令后添加一个 --open 即可。

  "scripts": {
    "dev": "vite --open",
    "build": "vue-tsc && vite build",
    "preview": "vite preview"
  },

eslint 相关配置

安装依赖

pnpm i eslint -D

生成配置文件:.eslint.cjs

npx eslint --init

安装 eslint 相关依赖指令

pnpm install -D eslint-plugin-import eslint-plugin-vue eslint-plugin-node eslint-plugin-prettier eslint-config-prettier eslint-plugin-node @babel/eslint-parser
1.2 修改.eslintrc.cjs 配置文件
// @see https://eslint.bootcss.com/docs/rules/

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
    jest: true,
  },
  /* 指定如何解析语法 */
  parser: 'vue-eslint-parser',
  /** 优先级低于 parse 的语法解析配置 */
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    parser: '@typescript-eslint/parser',
    jsxPragma: 'React',
    ecmaFeatures: {
      jsx: true,
    },
  },
  /* 继承已有的规则 */
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-essential',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  plugins: ['vue', '@typescript-eslint'],
  /*
   * "off" 或 0    ==>  关闭规则
   * "warn" 或 1   ==>  打开的规则作为警告(不影响代码执行)
   * "error" 或 2  ==>  规则作为一个错误(代码不能执行,界面报错)
   */
  rules: {
    // eslint(https://eslint.bootcss.com/docs/rules/)
    'no-var': 'error', // 要求使用 let 或 const 而不是 var
    'no-multiple-empty-lines': ['warn', { max: 1 }], // 不允许多个空行
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-unexpected-multiline': 'error', // 禁止空余的多行
    'no-useless-escape': 'off', // 禁止不必要的转义字符

    // typeScript (https://typescript-eslint.io/rules)
    '@typescript-eslint/no-unused-vars': 'error', // 禁止定义未使用的变量
    '@typescript-eslint/prefer-ts-expect-error': 'error', // 禁止使用 @ts-ignore
    '@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型
    '@typescript-eslint/no-non-null-assertion': 'off',
    '@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。
    '@typescript-eslint/semi': 'off',

    // eslint-plugin-vue (https://eslint.vuejs.org/rules/)
    'vue/multi-word-component-names': 'off', // 要求组件名称始终为 “-” 链接的单词
    'vue/script-setup-uses-vars': 'error', // 防止

在src文件夹目录下创建一个index.ts文件:用于注册components文件夹内部全部全局组件!!!

import SvgIcon from './SvgIcon/index.vue';
import type { App, Component } from 'vue';
const components: { [name: string]: Component } = { SvgIcon };
export default {
    install(app: App) {
        Object.keys(components).forEach((key: string) => {
            app.component(key, components[key]);
        })
    }
}

在入口文件引入src/index.ts文件,通过app.use方法安装自定义插件

import gloablComponent from './components/index';
app.use(gloablComponent);

vue3 批量全局注册 公共组件。

  1. 在 components 文件夹下面新建一个 index.js 文件,用于批量全局注册公共组件。

注意: components 文件下的 index.js 文件向外暴露的对象中,务必要有一个 install(){} 的函数。
且这个 install() 方法会有一个 app 入参,然后全局注册公共组件的时候直接 app.component()即可

//引入项目中全部的全局组件
import SvgIcon from './SvgIcons/index.vue'
import Pagination from './Pagination/index.vue'
// import Category from './Category/index.vue'
//引入element-plus提供全部图标组件
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
//全局对象
const allGloablComponent: any = { SvgIcon, Pagination }
//对外暴露插件对象
export default {
  //务必叫做install方法
  install(app: any) {
    //注册项目全部的全局组件
    Object.keys(allGloablComponent).forEach((key) => {
      //注册为全局组件
      app.component(key, allGloablComponent[key])
    })
    //将element-plus提供图标注册为全局组件
    for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
      app.component(key, component)
    }
  },
}
  1. 在入口文件引入 src/index.js 文件,通过 app.use 方法安装自定义插件
import gloablComponent from './components/index'
app.use(gloablComponent)

scss 配置相关

  1. 首先在 src 目录下新建一个 styles 文件夹,并新建一个index.scss文件。用作设置全局样式
  2. 在 style 文件夹下 新建一个 reset.scss 文件用于清除浏览器自带的默认样式。
    • 配置好 reset.scss 文件之后,需要在 index.scss 文件@import 'reset.scss' 引入
  3. 在 style 文件夹下 新建一个 variable.scss 文件用于设置 scss 的全局变量

注意: 在 variable.scss 文件中配置 css 全局变量时,需要通过 $符号定义

在入口文件中引入 index.scss 文件

import '@/styles/index.scss'

配置全局变量需要 在 vite.config.js 文件中 配置相关属性,代码如下


export default defineConfig((config) => {
   // 只要 下面这些代码即可。
	css: {
      preprocessorOptions: {
        scss: {
          javascriptEnabled: true,
          additionalData: '@import "./src/styles/variable.scss";',
        },
      },
    },
	}
}

Mock 数据

  1. 安装相关依赖 pnpm install -D vite-plugin-mock mockjs
  2. 在 vite.config.ts 文件中 配置相关规则
import { UserConfigExport, ConfigEnv } from 'vite'
import { viteMockServe } from 'vite-plugin-mock'
import vue from '@vitejs/plugin-vue'
export default ({ command }) => {
  return {
    plugins: [
      vue(),
      viteMockServe({
        localEnabled: command === 'serve',
      }),
    ],
  }
}
  1. 在根目录创建 mock 文件夹:去创建我们需要 mock 数据与接口!!!
//用户信息数据
function createUserList() {
  return [
    {
      userId: 1,
      avatar:
        'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
      username: 'admin',
      password: '111111',
      desc: '平台管理员',
      roles: ['平台管理员'],
      buttons: ['cuser.detail'],
      routes: ['home'],
      token: 'Admin Token',
    },
    {
      userId: 2,
      avatar:
        'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
      username: 'system',
      password: '111111',
      desc: '系统管理员',
      roles: ['系统管理员'],
      buttons: ['cuser.detail', 'cuser.user'],
      routes: ['home'],
      token: 'System Token',
    },
  ]
}

export default [
  // 用户登录接口
  {
    url: '/api/user/login', //请求地址
    method: 'post', //请求方式
    response: ({ body }) => {
      //获取请求体携带过来的用户名与密码
      const { username, password } = body
      //调用获取用户信息函数,用于判断是否有此用户
      const checkUser = createUserList().find(
        (item) => item.username === username && item.password === password,
      )
      //没有用户返回失败信息
      if (!checkUser) {
        return { code: 201, data: { message: '账号或者密码不正确' } }
      }
      //如果有返回成功信息
      const { token } = checkUser
      return { code: 200, data: { token } }
    },
  },
  // 获取用户信息
  {
    url: '/api/user/info',
    method: 'get',
    response: (request) => {
      //获取请求头携带token
      const token = request.headers.token
      //查看用户信息是否包含有次token用户
      const checkUser = createUserList().find((item) => item.token === token)
      //没有返回失败的信息
      if (!checkUser) {
        return { code: 201, data: { message: '获取用户信息失败' } }
      }
      //如果有返回成功信息
      return { code: 200, data: { checkUser } }
    },
  },
]
  1. 安装 axios 测试 mock 的接口是否可以使用.
    pnpm install axios
// 引入 axios 测试 mock 是否引入成功
import axios from 'axios'

axios({
  method: 'post',
  url: '/api/user/login',
  data: { username: 'admin', password: '111111' },
}).then((res) => {
  console.log(res, 'mock假数据')
})

axios 二次封装

  1. 新建一个 utils 文件夹,并添加一个 request.js 文件,用于统一配置相关 接口规则.( 如请求拦截,相应拦截,基础路径,超时时间 等等.)
//进行axios二次封装:使用请求与响应拦截器
import axios from 'axios'
import { ElMessage } from 'element-plus'
//引入用户相关的仓库
import useUserStore from '@/store/modules/user'
//第一步:利用axios对象的create方法,去创建axios实例(其他的配置:基础路径、超时的时间)
const request = axios.create({
  //基础路径
  baseURL: import.meta.env.VITE_APP_BASE_API, //基础路径上会携带/api
  timeout: 5000, //超时的时间的设置
})
//第二步:request实例添加请求与响应拦截器
request.interceptors.request.use((config) => {
  //获取用户相关的小仓库:获取仓库内部token,登录成功以后携带给服务器
  const userStore = useUserStore()
  if (userStore.token) {
    config.headers.token = userStore.token
  }
  //config配置对象,headers属性请求头,经常给服务器端携带公共参数
  //返回配置对象
  return config
})

//第三步:响应拦截器
request.interceptors.response.use(
  (response) => {
    //成功回调
    //简化数据
    return response.data
  },
  (error) => {
    //失败回调:处理http网络错误的
    //定义一个变量:存储网络错误信息
    let message = ''
    //http状态码
    const status = error.response.status
    switch (status) {
      case 401:
        message = 'TOKEN过期'
        break
      case 403:
        message = '无权访问'
        break
      case 404:
        message = '请求地址错误'
        break
      case 500:
        message = '服务器出现问题'
        break
      default:
        message = '网络出现问题'
        break
    }
    //提示错误信息
    ElMessage({
      type: 'error',
      message,
    })
    return Promise.reject(error)
  },
)
//对外暴露
export default request

路由搭建

  1. npm i vue-router 安装路由依赖
  2. 新建一个 router 文件夹,并新增 index.js 文件用于统一配置相关路由
  3. main.js 文件中引入并注册

index.js 文件

//通过vue-router插件实现模板路由配置
import { createRouter, createWebHashHistory } from 'vue-router';
import { constantRoute } from './routes';
//创建路由器
let router = createRouter({
    //路由模式hash
    history: createWebHashHistory(),
    routes: constantRoute,
    //滚动行为
    scrollBehavior() {
        return {
            left: 0,
            top: 0
        }
    }
});
export default router;

routes.js 文件

//对外暴露配置路由(常量路由)
export const constantRoute = [
  {
    //登录
    path: '/login',
    component: () => import('@/views/login/index.vue'),
    name: 'login',
    meta: {
      title: '登录', //菜单标题
      hidden: true, //代表路由标题在菜单中是否隐藏  true:隐藏 false:不隐藏
      icon: 'Promotion', //菜单文字左侧的图标,支持element-plus全部图标
    },
  },
  {
    //登录成功以后展示数据的路由
    path: '/',
    component: () => import('@/layout/index.vue'),
    name: 'layout',
    meta: {
      title: '',
      hidden: false,
      icon: '',
    },
    redirect: '/home',
    children: [
      {
        path: '/home',
        component: () => import('@/views/home/index.vue'),
        meta: {
          title: '首页',
          hidden: false,
          icon: 'HomeFilled',
        },
      },
    ],
  },
  {
    //404
    path: '/404',
    component: () => import('@/views/404/index.vue'),
    name: '404',
    meta: {
      title: '404',
      hidden: true,
      icon: 'DocumentDelete',
    },
  },
  {
    //任意路由
    path: '/:pathMatch(.*)*',
    redirect: '/404',
    name: 'Any',
    meta: {
      title: '任意路由',
      hidden: true,
      icon: 'DataLine',
    },
  },
]

main.js 文件

//引入路由
import router from './router'
//注册模板路由
app.use(router)

Vue 项目路由动态加载需要注意问题。

出现问题:当项目访问异步路由的时候,浏览器可能会出现白屏的现象。

原因:当访问异步路由的时候,项目可能出现路由加载没完成的情况。也就是还没有这个路由的时候,就去访问,就会出现白屏的现象

解决办法:使用 next() 放行的时候,等路由加载完成之后再放行。

//万一:刷新的时候是异步路由,有可能获取到用户信息、异步路由还没有加载完毕,出现空白的效果,解决办法如下。
next({ ...to })

Vue 按钮权限相关方法

注册全局指令,然后根据后端返回的按钮权限的数组,使用 v-if 对按钮进行控制。

全局指令代码:
import pinia from '@/store'
import useUserStore from '@/store/modules/user'
const userStore = useUserStore(pinia)
export const isHasButton = (app: any) => {
  //获取对应的用户仓库
  //全局自定义指令:实现按钮的权限
  app.directive('has', {
    //代表使用这个全局自定义指令的DOM|组件挂载完毕的时候会执行一次
    mounted(el: any, options: any) {
      //自定义指令右侧的数值:如果在用户信息buttons数组当中没有
      //从DOM树上干掉
      if (!userStore.buttons.includes(options.value)) {
        el.parentNode.removeChild(el)
      }
    },
  })
}

// main.js 文件

//引入自定义指令文件
import { isHasButton } from '@/directive/has'
isHasButton(app)

// 使用:

<el-button  @click="addTrademark" v-has="`btn.Trademark.add`">添加品牌</el-button>

你可能感兴趣的:(javascript,开发语言,ecmascript)