Vue 3.x - 实战(JavaScript)

480 阅读4分钟

node 12.16.1 vue/cli 4.5.13 vite 2.4.4 vue 3.1.5 element-plus 1.0.2-beta.70 ...

1. 安装

Vue/cli 4.5版本以上作为 @vue/cli ,否则需要全局重新安装最新版本。

npm install -g @vue/cli

基于 vite2 创建 Vue3 项目

npm init vite-app 项目名称

Monster:Project chiang$ npm init vite-app abc
npx: 7 安装成功,用时 5.835Scaffolding project in /Users/chiang/Person/Project/abc...

Done. Now run:

  cd abc
  npm install (or `yarn`)
  npm run dev (or `yarn dev`)

  进入项目目录执行npm install 及 npm run dev 完成项目初始化启动。

目录结构

.
├── index.html
├── node_modules
├── package-lock.json
├── package.json
├── public
└── src
    ├── App.vue
    ├── assets
    ├── components
    └── main.js
  • index.html:主页。
  • node_modules:项目依赖的包均在该文件夹下。
  • package-lock.json:锁定安装时的包的版本号,保证所有项目成员依赖相同。
  • package.json:项目名称、版本、作者、github地址、 当前项目依赖了哪些第三方模块等。
  • public:放置公共资源,例如图片、全局CSS等。
  • src:项目根路径,所有功能基于该文件下开展。

src概述

  • App.vue:根组件。
  • main.js:入口文件。
  • asserts:静态资源文件夹,常放置图片、JSON文件等等静态资源。
  • components:组件文件夹,vue的特点之一就是组件化,业务逻辑组件放置该文件夹下。

1.1. 注意事项

  vue 和 @vue/compiler-sfc 版本需一致,若版本较低使用下方指令。

npm install vue@3.1.5 --S
npm install @vue/compiler-sfc@3.1.5 --S

2. vite

2.1. vs webpack

  vite 基于 ECMAScript 标准原生模块系统 (ES Modules) 实现,最突出的优点  (启动快,更新快...),依赖少,但只支持 vue3.0以上的版本,生态较差。 webpack 虽然各种优点不及 vite ,但周边生态好,简单说经过多年的积累,用户群体庞大。总之不同应用场景选择不同技术,扬长避短。

2.2. 启动参数  

"scripts": {
  "dev": "cross-env vite --mode dev",
  "prod": "cross-env vite --mode prod",
  "build": "vite build",
  "preview": "vite preview"
},

  根据项目的运行环境使用 vite cross-env 设置不同的启动参数。

cross-env安装

npm install cross-env --S

环境变量

  以 .env. 开头自定义环境名称结尾。例 .env.dev 

NODE_ENV=dev
VITE_BUILD_ENV=dev
VITE_APP_URL=http://127.0.0.1:8080

vite.config.js

  项目根路径下创建 vite.config.js 文件,用于配置服务端口、跨域、代理、路径、插件等...

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';

export default defineConfig({
  server: {
    port: '8000',
    open: true,
    cors: true,
    // 代理规则
    proxy: {
      '/api': {
        target: 'http://127.0.0.1:8080',
        changeOrigin: true,
        secure: false,
      },
    },
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '~@': path.resolve(__dirname, 'src/configurations'),
    },
  },
  plugins: [vue()],
});

3. vuex

安装

npm install vuex --S

目录结构

src
├── assets
├── components 
│   └── modules
├── configurations
│   └── store
│       └── index.js
├── App.vue
└── main.js

index.js

import Vuex from 'vuex';

/**
 * Web Storage
 */
export default new Vuex.Store({
  state: {
    token: sessionStorage.getItem('token'),
  },
  mutations: {
    /**
     * 改变token
     * @param {*} state 存储信息
     * @param {*} token 登录口令
     */
    change(state, token) {
      state.token = token;
      sessionStorage.setItem('token', token);
    },
    /**
     * 删除token
     * @param {*} state 存储信息
     */
    remove(state) {
      state.token = null;
      sessionStorage.removeItem('token');
    },
  },
});

4. vue-router

安装

npm install vue-router --S

目录结构

src
├── assets
├── components 
│   └── modules
├── configurations
│   ├── store
│   └── router
│	└── index.js
├── App.vue
└── main.js

index.js

import { createRouter, createWebHistory } from 'vue-router';
import store from '~@/store';

/**
 * 路由文件加载
 */
const files = import.meta.globEager('/src/components/modules/**/*.router.js');

/**
 * 路由配置
 */
const routes = Object.keys(files).map((item) => files[item].default);

/**
 * 路由配置
 * history: 1.createWebHistory(), 2.createWebHashHistory()
 * routes: 路由跳转配置
 */
const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      component: () => import('@/components/layout/container.vue'),
      children: routes,
    },
  ],
});

/**
 * 路由前置守卫
 */
router.beforeEach((to, from, next) => {
  let token = store.state.token;
  if (token === null || token === '') {
    // 当路由跳转不满足定义的条件时,实现某个操作
  } else {
    next();
  }
});

export default router;

5. axios

安装

npm install axios --S

目录结构

src
├── assets
├── components 
│   └── modules
├── configurations
│   ├── store
│   ├── router
│   └── http
│	└── index.js
├── App.vue
└── main.js

index.js

import axios from 'axios';
import store from '~@/store';

/**
 * axios配置
 */
const instance = axios.create({
  // 接口域名
  baseURL: import.meta.env.VITE_APP_URL,
  // 超时时限
  timeout: 6000,
  // 请求头
  headers: {
    'Content-Type': 'application/json;charset=UTF-8;',
  },
});

/**
 * 请求拦截器
 */
instance.interceptors.request.use(
  (config) => {
    const token = store.state.token;
    token && (config.headers.token = token);
    if (config.method === 'POST') {
      config.data = JSON.stringify(config.data);
    }
    return config;
  },
  (error) => Promise.reject(error)
);

/**
 * 响应拦截器
 */
instance.interceptors.response.use(
  (response) => {
    if (response.status != 200 && valid(response.data)) {
      throw new Error(response);
    }
    return handle(response.data);
  },
  (error) => Promise.reject(error)
);

/**
 * 响应参数格式检验
 * @param {*} object response.data
 * @returns true: 满足, false: 不满足
 */
const valid = (object) => {
  if (!object.code || !object.message || !object.data) {
    console.error('data struct is not match');
    return false;
  }
  return true;
};

/**
 * 出参业务判定处理
 * @param {*} object response.data
 * @returns
 * 200: object.data
 * 401: 移除登录信息
 */
const handle = (object) => {
  if (object.code === '200') {
    return object.data;
  } else if (object.code === '401') {
    store.commit('remove');
    console.warn('token invalid');
  } else {
    // todo
  }
};

export default instance;

6. element-plus

element-plus.gitee.io/#/zh-CN/com…

6.1. 安装

element-plus

npm install element-plus --save

@vitejs/plugin-vue

npm install @vitejs/plugin-vue

6.2. 配置

  官方提示:强烈建议直接引入全部的样式文件。

main.js

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

createApp(App).use(ElementPlus).mount('#app');

6.3. 布局

目录结构

.
└── layout
    ├── affix.vue
    ├── aside.vue
    ├── container.vue
    ├── header.vue
    └── menu.vue
  • affix:图钉,用于控制“抽屉”展示与收起。
  • aside:左侧菜单栏整体布局。
  • menu:动态数据生成菜单的基础组件,可理解 aside 内容之一。
  • header:页头。
  • container:布局整体容器。

7. echarts

安装

npm install echarts --S
#用于声明元素唯一ID
npm install vue-uuid --S

目录结构

src
├── assets
│   ├── components
│   │   ├── data
│   │   ├── layout
│   │   ├── login.vue
│   │   ├── modules
│   │   ├── plugins
│   │   │   └── echarts
│   │   │	└── echarts.vue
│   │   └── login.vue
│   └── configurations
│       ├── http
│       ├── router
│       └── store
├── App.vue
└── main.js

echarts.vue

<template>
  <div :style="{height: height}" :id="id"></div>
</template>

<script>
import { defineComponent, onMounted, watch } from "vue";
import * as echarts from "echarts";
import { uuid } from "vue-uuid";
import store from "~@/store";

export default defineComponent({
  props: {
    height: {
      type: String,
    },
    option: {
      type: Object,
    },
  },
  setup(context) {
    // 图表div唯一标志
    const id = uuid.v4();
    onMounted(() => {
      let dom = document.getElementById(id);
      let chart = echarts.init(dom);
      chart.setOption(context.option);
      // 监听导航折叠状态
      watch(
        () => store.state.collapse,
        () => {
          setTimeout(() => chart.resize(), 400);
        }
      );
      // 监听浏览器窗口变化
      window.onresize = () => {
        chart.resize();
      };
    });
    return {
      id,
    };
  },
});
</script>

<style scoped></style>

Gitee:gitee.com/tinychiang/…
Github:github.com/tinychiang/…