vue3.0+vite+elementUI(一)

1,775 阅读9分钟

第一件事确认一下技术栈:

Vue3.0;
Vite2.0;脚手架
Vue-Router 4.0;路由
Vuex; 状态管理工具
Element-plus;页面UI
Echart 5.0;数据图形
axios;接口
node.js; 后端
mongodb;mysql数据库;
ts;作为js超集的语言
腾讯云; 服务器

第二件事确认一下项目:电商后台管理系统

搭建项目:

1.vite2.0+vue3.0

问题一:为什么使用vite2.0,而不是使用vue-cli?留着有空回答

首先检查node.js版本,需要>=12;

学习vite2.0

安装vite:

用npm:npm init @vitejs/app
用yarn:yarn create @vitejs/app

通过提示一步一步,就可以直接创建一个项目了。

或者直接用下面命令创建:

yarn create vite-app online-management

例如我的项目名称叫做:online-management,选择vue框架开发;

进入项目,安装依赖:

cd online-management
npm用:npm install
yarn用:yarn #

运行项目: 我们可以观察此时项目的package.json:

npx vite 或 npm run dev 或 yarn dev

打开http://localhost:3000/即可

这就是一个十分简单的vue3.0+Vite2.0的架子搭起来;

2.typescript

建议使用ts,有助于代码的规范化,如果对ts不熟悉可以继续使用js。

安装依赖:

yarn add typescript -D

配置tsconfig.json

如果是要自己配置可以初始化tsconfig.ts:
npx tsc --init

接下来先修改:

  1. 修改main.js为main.ts;
  2. 修改index.html里的引用:
  <script type="module" src="/src/main.ts"></script>
  1. 修改App.vue和HelloWorld.vue:
<script> 修改为 <script lang="ts">

tsconfig.json包括:

  • compileOnSave (保存时编译)
  • compilerOptions (配置编译选项)
  • exclude (排除)
  • extends (扩展)
  • files (指定待编译文件,即入口文件,是数组类型)
  • include (编译包括的文件)
  • references (依赖的工程)前后端分别打包
  • typeAcquisition (设置自动引入库类型定义文件(.d.ts)相关)

tsconfig.ts(根目录下):

{
  //"compileOnSave": true,  /* 设置保存文件的时候自动编译,但需要编译器支持。 */
  "compilerOptions": {
    /* Basic Options */
    "incremental": true,                   /* TS编译器在第一次编译之后会生成一个存储编译信息的文件,第二次编译会在第一次的基础上进行增量编译,可以提高编译的速度Enable incremental compilation */
    "target": "esnext",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "lib": ["DOM", "ES2015", "ScriptHost", "ES2019.Array"],                             /* 编译过程中需要引入的库文件的列表。 Specify library files to be included in the compilation. */
    "allowJs": true,                       /* Allow javascript files to be compiled. */
    "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    "declaration": true,                   /* 生成声明文件,开启后会自动生成声明文件 Generates corresponding '.d.ts' file. */
    // "declarationDir": "./file", // 指定生成声明文件存放目录
    // "declarationMap": true,                /* 为声明文件生成sourceMap Generates a sourcemap for each corresponding '.d.ts' file. */
    "sourceMap": true,                     /* 生成相应的 .map文件Generates corresponding '.map' file. */
    "emitDeclarationOnly": true,   /* 只生成声明文件,而不会生成js文件 */
    //"skipLibCheck": true,  /* 忽略所有的声明文件( *.d.ts)的类型检查。 */
    //"outFile": "./",                       /* 将多个相互依赖的文件生成一个文件,可以用在AMD模块中,即开启时应设置"module": "AMD", Concatenate and emit output to single file. */
    "outDir": "./dist",                        /* 指定输出目录 Redirect output structure to the directory. */
    // "rootDir": "./",                       /* 指定输出文件目录(用于输出),用于控制输出目录结构 Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* 增量编译文件的存储位置Specify file to store incremental compilation information */
    "removeComments": true,                /* Do not emit comments to output. */
    "preserveConstEnums": true,             /* Preserve the const and enum declarations*/
    // "noEmit": true,                        /* 不输出文件,即编译后不会生成任何js文件 Do not emit outputs. */
    //"noEmitOnError": true,  /* 发送错误时不输出任何文件 */
    //"noEmitHelpers": true, /* 不生成helper函数,减小体积,需要额外安装,常配合importHelpers一起使用 */
    "importHelpers": true,                 /* 通过tslib引入helper函数,文件必须是模块 从 tslib 导入辅助工具函数(比如 __extends, __rest等) */
    "downlevelIteration": true,            /* 降级遍历器实现,如果目标源是es3/5,那么遍历器会有降级的实现 Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    "isolatedModules": true,               /* 将每个文件转换为一个单独的模块Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* 不允许隐式的any类型 Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* 不允许把null、undefined赋值给其他类型的变量 Enable strict null checks. */
    // "strictFunctionTypes": true,           /* 不允许函数参数双向协变 Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* 严格的bind/call/apply检查 Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* 类的实例属性必须初始化 Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* 不允许this有隐式的any类型 Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* 在代码中注入'use strict' Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* 检查只声明、未使用的局部变量(只提示不报错) Report errors on unused locals. */
    // "noUnusedParameters": true,            /* 检查未使用的函数参数(只提示不报错) Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* 每个分支都会有返回值 Report error when not all code paths in function return a value. */
    "noFallthroughCasesInSwitch": true,    /* 防止switch语句贯穿(即如果没有break语句后面不会执行) Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    "moduleResolution": "node",            /* 决定如何处理模块:模块解析策略,ts默认用node的解析策略,即相对的方式导入。Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    "baseUrl": "./",                       /* 解析非相对模块名的基准目录,默认是当前目录 */
    "paths": {
      "@/*": [
        "src/*"
      ],
      //"jquery": ["node_modules/jquery/dist/jquery.min.js"]
    },                           /* 模块名到基于 baseUrl的路径映射的列表 A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* 将多个目录放在一个虚拟目录下,用于运行时,即编译后引入文件的位置可能发生变化,这也设置可以虚拟src和out在同一个目录下,不用再去改变路径也不会报错 List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* 声明文件目录,默认时node_modules/@types List of folders to include type definitions from. */
    // "types": [],                           /* 加载的声明文件包 Type declaration files to be included in compilation. */
    "allowSyntheticDefaultImports": true,  /* 允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。*/
    "esModuleInterop": true,                  /* 允许export=导出,由import from 导入 Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* 允许在模块中全局变量的方式访问umd模块 Allow accessing UMD globals from modules. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* 生成目标文件的inline SourceMap,inline SourceMap会包含在生成的js文件中 Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */

    /* Advanced Options */
    "forceConsistentCasingInFileNames": true,  /* Disallow inconsistently-cased references to the same file. */
    //"listEmittedFiles": true, /* 打印输出文件 */
    //"listFiles": true  /* 打印编译的文件(包括引用的声明文件) */
  },
  "exclude": [
    "node_modules"
  ]
}

配置 shim.d.ts来告诉ts,vue是一种文件类型,如果没有这个会发现import 的所有 vue 类型的文件都会报错。

如果要引入其他的插件,例如vue-echarts等等都需要在这里说明文件类型

shim.d.ts(根目录下):

declare module "*.vue" {
  import { Component } from "vue";
  const component: Component;
  export default component;
}
declare module 'vue-echarts'  // 引入vue-echarts

或者vue-cli可以这样写;

declare module '*.vue' { //declare声明宣告, 声明一个ambient module(即:没有内部实现的 module声明) 
  import Vue from 'vue'
  export default Vue
}

3.eslint-prettier

针对项目配置代码规范: 这里可以不配置

配置eslint:

yarn add -D eslint eslint-plugin-vue babel-eslint

.eslintrc.js:

module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    'plugin:prettier/recommended',
  ],
  parserOptions: {
    parser: 'babel-eslint',
  },
  plugins: ['prettier'],
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-unused-vars': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
  },
}

配置prettier:

 yarn add -D prettier eslint-config-prettier eslint-plugin-prettier

prettier.config.js(根目录):

module.exports = {
    printWidth: 500,
    tabWidth: 2,
    useTabs: false,
    semi: false, 
    vueIndentScriptAndStyle: true,
    singleQuote: true, 
    quoteProps: 'as-needed',
    bracketSpacing: true,
    trailingComma: 'none', 
    jsxBracketSameLine: false,
    jsxSingleQuote: false,
    arrowParens: 'always',
    insertPragma: false,
    requirePragma: false,
    proseWrap: 'preserve',
    htmlWhitespaceSensitivity: 'strict',
    embeddedLanguageFormatting: 'off',
    endOfLine: 'lf',
    editor:{
        wordWrap:'on',
        fontSize:'14',
    }
  }

4.vue-router

此时我们先加入路由vue-router,Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。

问:vue-router和vue-next-router区别?

安装

npm用:npm install vue-router@next -S
yarn用:yarn add vue-router@next

在src目录下创建router文件夹:router/index.ts

index.ts:

import {createRouter, createWebHashHistory, RouteRecordRaw} from 'vue-router';
import HelloWorld from '../components/HelloWorld.vue';
const routes: Array<RouteRecordRaw> = [
    {
        path: "/",
        name: "HelloWorld",
        component: HelloWorld,
    },
    // {
    //     path: "/about",
    //     name: "About",
    //     // route level code-splitting
    //     // this generates a separate chunk (about.[hash].js) for this route
    //     // which is lazy-loaded when the route is visited.
    //     component: () =>
    //         import(/* webpackChunkName: "About" */ "../components/About.vue")
    // }
];

// 在 Vue-router新版本中,需要使用createRouter来创建路由
export default createRouter({
  // 指定路由的模式,此处使用的是hash模式
  history: createWebHashHistory(),
  // 路由地址
  routes
});

在main.ts中引入router:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import './index.css'

const app = createApp(App)
app.use(router)
app.mount('#app')

重启即可

yarn dev

5.vuex

看项目需要,如果复用较少且项目数据不复杂就大可不必引入

vuex是一个专为 Vue.js 应用程序开发的状态管理模式.

引入依赖:

yarn add vuex@next

在src目录下创建store文件夹:store/index.ts

import { InjectionKey } from 'vue'
import { createStore, Store } from 'vuex'

export interface State {
  name: string,  
  count: number
}

export const key: InjectionKey<Store<State>> = Symbol();

export const store = createStore<State>({
  state() {
    return {
      count: 0,
      name: '小明'
    }
  },
  mutations: {
    increment(state) {
      state.count++
    }
  }
})

在main.ts中引入store:

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
import router from './router/index'
import {store,key} from './store/index'

const app = createApp(App)
app.use(router)
app.use(store,key)
app.mount('#app')

6.Element-Plus

第一步:安装依赖:

npm install element-plus --save

element-plus考虑到项目的情况可以有两种选择:

全局使用:

这里我们可以就size和z-index进行全局配置: 引入main.ts

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
import router from './router/index'
import {store,key} from './store/index'
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';

const app = createApp(App)
app.use(router)
app.use(store,key)
app.use(ElementPlus,{size:'small',zIndex:1000})
app.mount('#app')
按需使用:

需要借助 babel-plugin-component,我们只引入需要的组件,减小项目体积。 安装:

npm install babel-plugin-component -D
yarn add babel-plugin-import -D

这里我们用的是vite,所以配置的是vite.config.json,plugins需要修改,或者如果用.babelrc需要修改为

{
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-plus",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

main.ts:

import { createApp } from 'vue'
import { ElButton, ElSelect } from 'element-plus';
import App from './App.vue';
const option = {size:'small',zIndex:1000}
const app = createApp(App)
app.config.globalProperties.$ELEMENT = option
app.component(myBtn, ElButton);
app.component(myElSe, ElSelect);

/* or
 * app.use(ElButton)
 * app.use(ElSelect)
 */

app.mount('#app')

我们都习惯了用less来写样式的,vite为.less,.scss等提供了内建文件。只需要安装依赖即可:

npm install less less-loader --dev

此时可能会报错: 将package.json中的:

 "less": "^4.1.1",
 "less-loader": "^8.0.0"

改到devDependencies对象里重新npm i即可。

7.vite配置文件

当以命令行方式运行 vite 时,Vite 会自动解析 项目根目录 下名为 vite.config.js 的文件:

如果在项目中不想用vite.config.ts,改用my-config.ts, 你可以显式地通过 --config 命令行选项指定一个配置文件(解析会相对于 cwd 路径)

npx vite --config my-config.ts

如果没有@vitejs/plugin-vue,安装@vitejs/plugin-vue依赖

yarn add @vitejs/plugin-vue

vite.config.ts

export default defineConfig({
  alias: {
    '@': pathResolve('./src'),
  },

  server: {
    open: false,
    https: false,
    proxy: {
      '/api': {
        target: 'http://',
        changeOrigin: true,
        ws: false,
        secure: false,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
    hmr: {
      overlay: true,
    },
  },

  build: {
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
      },
    },

    chunkSizeWarningLimit: 800, 
  },

  plugins: [vue()],
})