zoukankan      html  css  js  c++  java
  • 第二节:三方库集成和配置(vue cliwebpack、elementplus、axios、vscode、区分不同环境)

    一. vue cli-webpack配置

    1. 说明

     在vue cli创建的项目中,配置文件为:vue.config.js

     vue.config.js 是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。

    2. vue cli 基本配置

    (详见:https://cli.vuejs.org/zh/config/#全局-cli-配置 ) 

    (1). outputDir

    (2). publicPath

    剖析:

      默认值为‘/’,生成的打包文件的引用的路径都是以/开头,没法直接在vscode中运行,需要部署后才能运行,

      如果改为'./',生成的打包文件的引用路径如下图,可以直接在vscode中运行

    3. webpack配置 

    (详见:https://cli.vuejs.org/zh/guide/webpack.html#简单的配置方式 ) 

     在vue cli创建的项目中,不能配置webpack.config.js文件,需要在vue.config.js中的configureWebpack 或 chainWebpack 属性中配置, configureWebpack 属性中的配置和webpack中的配置一样,自动就合并了。

    补充:cli中,@符号已经默认配置了,对应的就是src目录,当然可以重写。

    下面是几种写法: 

    const path = require('path');
    
    module.exports = {
        //CLI提供的属性
        outputDir: './build',
        // publicPath: './', //打包后的可以直接使用,不用发布,默认是 '/'
        // webpack写法1(json格式)
        // 和webpack属性完全一致, 最后会进行合并
        configureWebpack: {
            resolve: {
                alias: {
                    components: '@/components',
                },
            },
        },
        // webpack写法2(函数形式)
        // configureWebpack: (config) => {
        //   config.resolve.alias = {
        //     '@': path.resolve(__dirname, 'src'),
        //     components: '@/components'
        //   }
        // }
        // webpack写法3(链式编程)
        // chainWebpack: (config) => {
        //     config.resolve.alias
        //         .set('@', path.resolve(__dirname, 'src'))
        //         .set('components', '@/components');
        // },
    };

    二. element-plus配置

    1. 全局引用

    (1). 说明

      如果你对打包后的文件大小不是很在乎,那么使用完整导入会更方便。

    (2). 步骤

    A. 安装生产依赖 【npm install element-plus】

    B. 全局引用,在main.ts文件中导入

    import { createApp } from 'vue';
    import App from './App.vue';
    // 全局引入element-plus
    import ElementPlus from 'element-plus';
    import 'element-plus/dist/index.css';
    
    const app = createApp(App);
    app.use(ElementPlus); //全局引用element-plus
    app.use(golbalRegister); // 按需引入element-plus
    
    app.mount('#app');

    C. 在页面中直接使用任意组件即可

    <template>
        <div>
            <el-button>默认按钮</el-button>
            <el-button type="primary">主要按钮</el-button>
            <el-button type="success">成功按钮</el-button>
            <el-button type="info">信息按钮</el-button>
        </div>
    </template>
    
    <script lang="ts">
        import { defineComponent } from 'vue';
        export default defineComponent({
            setup() {
            },
        });
    </script>
    
    <style lang="less"></style>

    2. 按需引用

    (1).说明

      根据需要导入相应的组件和样式

    (2).步骤

     直接在对应页面导入组件和组件的样式,使用即可

    <template>
        <div>
            <el-button>默认按钮</el-button>
            <el-button type="primary">主要按钮</el-button>
            <el-button type="success">成功按钮</el-button>
            <el-button type="info">信息按钮</el-button>
        </div>
    </template>
    
    <script lang="ts">
        import { defineComponent } from 'vue';
        import { ElButton } from 'element-plus';
        import 'element-plus/theme-chalk/el-button.css';
        export default defineComponent({
            components: {
                ElButton,
            },
            setup() {
            },
        });
    </script>
    
    <style lang="less"></style>

    3. 按需引用-全局封装

    (1). 说明

     上述在每个页面导入组件和组件的样式过于繁琐,所以这里将element-plus的组件封装成全局,然后每个页面直接使用即可,采用插件的形式进行封装  (这里有个问题,高版本的按需导入样式存在问题,这里的封装仅仅按需导入插件,样式使用的总样式)

    (2). 步骤 

    A. 封装register-element.ts文件(插件形式)

    import { App } from 'vue';
    import 'element-plus/dist/index.css'; //全局样式
    import { ElButton, ElCheckbox } from 'element-plus';
    const components = [ElButton, ElCheckbox];
    
    export default function (app: App): void {
        // 注册全局组件
        for (const cItem of components) {
            app.component(cItem.name, cItem);
        }
    }

    B. 封装global文件夹下的index.ts文件,统一出口

    import { App } from 'vue';
    import registerElement from './register-element';
    
    // 插件的形式对外导出(函数模式)
    export function golbalRegister(app: App): void {
        app.use(registerElement);
    }

    C. 在main.ts中进行导入

    import { createApp } from 'vue';
    import App from './App.vue';
    // 按需引入element-plus
    import { golbalRegister } from './global';
    
    const app = createApp(App);
    app.use(golbalRegister); // 按需引入element-plus
    
    app.mount('#app');

    D. 页面中直接使用即可 

    <template>
        <div>
            <el-button>默认按钮</el-button>
            <el-button type="primary">主要按钮</el-button>
            <el-button type="success">成功按钮</el-button>
            <el-button type="info">信息按钮</el-button>
        </div>
    </template>
    
    <script lang="ts">
        import { defineComponent } from 'vue';
        export default defineComponent({
            setup() {
            },
        });
    </script>
    
    <style lang="less"></style>

    三. axios配置

    1.  说明

     axios的详细用法参考之前的文章:https://www.cnblogs.com/yaopengfei/p/12347199.html

     这里补充一个通过创建实例的方式进行请求Post表单提交(实际上axios对象也是一个实例)

    import axios from 'axios';
    const myAxiosInstance = axios.create({
        baseURL: 'http://xxxx:8002',
        timeout: 1000,
        headers: { 'X-Custom-Header': 'foobar' },
    });
    const params = new URLSearchParams();
    params.append('userAccount', 'admin');
    params.append('passWord', '122222');
    myAxiosInstance
        .post('/Api/AdminApi_Areas/SysMainApi/CheckLogin', params)
        .then((res) => {
            console.log(res.data);
        })
        .catch((err) => {
            console.log(err);
        });

    2. 封装思路

     封装1个类,然后创建一个实例,将实例进行对外导出,里面结合Element-plus的组件,进行请求加载效果的配置

    类型声明
    import type { AxiosRequestConfig, AxiosResponse } from 'axios';
    /* eslint-disable */
    export interface HYRequestInterceptors<T = AxiosResponse> {
        requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig;
        requestInterceptorCatch?: (error: any) => any;
        responseInterceptor?: (res: T) => T;
        responseInterceptorCatch?: (error: any) => any;
    }
    
    export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
        interceptors?: HYRequestInterceptors<T>;
        showLoading?: boolean;
    }
    类的封装
    // 以类的方式来封装axios
    import axios, { AxiosInstance } from 'axios';
    import type { HYRequestInterceptors, HYRequestConfig } from './type';
    import { ElLoading, ILoadingInstance } from 'element-plus';
    
    const DEAFULT_LOADING = true;
    
    class HYRequest {
        instance: AxiosInstance;
        interceptors?: HYRequestInterceptors;
        showLoading: boolean;
        loading?: ILoadingInstance;
    
        constructor(config: HYRequestConfig) {
            // 创建axios实例
            this.instance = axios.create(config);
    
            // 保存基本信息
            this.showLoading = config.showLoading ?? DEAFULT_LOADING;
            this.interceptors = config.interceptors;
    
            // 使用拦截器
            // 1.从config中取出的拦截器是对应的实例的拦截器
            this.instance.interceptors.request.use(
                this.interceptors?.requestInterceptor,
                this.interceptors?.requestInterceptorCatch,
            );
            this.instance.interceptors.response.use(
                this.interceptors?.responseInterceptor,
                this.interceptors?.responseInterceptorCatch,
            );
    
            // 2.添加所有的实例都有的拦截器
            this.instance.interceptors.request.use(
                (config) => {
                    if (this.showLoading) {
                        this.loading = ElLoading.service({
                            lock: true,
                            text: '正在请求数据....',
                            background: 'rgba(0, 0, 0, 0.5)',
                        });
                    }
                    return config;
                },
                (err) => {
                    return err;
                },
            );
            this.instance.interceptors.response.use(
                (res) => {
                    // 将loading移除
                    this.loading?.close();
    
                    const data = res.data;
                    if (data.returnCode === '-1001') {
                        console.log('请求失败~, 错误信息');
                    } else {
                        return data;
                    }
                },
                (err) => {
                    // 将loading移除
                    this.loading?.close();
    
                    // 例子: 判断不同的HttpErrorCode显示不同的错误信息
                    if (err.response.status === 404) {
                        console.log('404的错误~');
                    }
                    return err;
                },
            );
        }
    
        request<T>(config: HYRequestConfig<T>): Promise<T> {
            return new Promise((resolve, reject) => {
                // 1.单个请求对请求config的处理
                if (config.interceptors?.requestInterceptor) {
                    config = config.interceptors.requestInterceptor(config);
                }
    
                // 2.判断是否需要显示loading
                if (config.showLoading === false) {
                    this.showLoading = config.showLoading;
                }
    
                this.instance
                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
                    .request<any, T>(config)
                    .then((res) => {
                        // 1.单个请求对数据的处理
                        if (config.interceptors?.responseInterceptor) {
                            res = config.interceptors.responseInterceptor(res);
                        }
                        // 2.将showLoading设置true, 这样不会影响下一个请求
                        this.showLoading = DEAFULT_LOADING;
    
                        // 3.将结果resolve返回出去
                        resolve(res);
                    })
                    .catch((err) => {
                        // 将showLoading设置true, 这样不会影响下一个请求
                        this.showLoading = DEAFULT_LOADING;
                        reject(err);
                        return err;
                    });
            });
        }
    
        get<T>(config: HYRequestConfig<T>): Promise<T> {
            return this.request<T>({ ...config, method: 'GET' });
        }
    
        post<T>(config: HYRequestConfig<T>): Promise<T> {
            return this.request<T>({ ...config, method: 'POST' });
        }
    
        delete<T>(config: HYRequestConfig<T>): Promise<T> {
            return this.request<T>({ ...config, method: 'DELETE' });
        }
    
        patch<T>(config: HYRequestConfig<T>): Promise<T> {
            return this.request<T>({ ...config, method: 'PATCH' });
        }
    }
    
    export default HYRequest;
    View Code

     实例的封装

    // service统一出口
    import HYRequest from './request';
    import { BASE_URL, TIME_OUT } from './request/config';
    
    const hyRequest = new HYRequest({
        baseURL: BASE_URL,
        timeout: TIME_OUT,
        // 实例级别的拦截器
        interceptors: {
            requestInterceptor: (config) => {
                console.log('请求成功的拦截');
                return config;
            },
            requestInterceptorCatch: (err) => {
                console.log('请求失败的拦截');
                return err;
            },
            responseInterceptor: (res) => {
                console.log('响应成功的拦截');
                return res;
            },
            responseInterceptorCatch: (err) => {
                console.log('响应失败的拦截');
                return err;
            },
        },
    });
    
    export default hyRequest;
    View Code
    测试
    //测试自己封装的axios
    import hyRequest from './index';
    // 下面是表单提交到参数封装
    const params = new URLSearchParams();
    params.append('userAccount', 'admin');
    params.append('passWord', '123456');
    // 封装返回值类型
    interface DataType {
        status: string;
        msg: string;
        data: unknown;
    }
    hyRequest
        .post<DataType>({
            url: '/Api/AdminApi_Areas/SysMainApi/CheckLogin',
            data: params,
            // showLoading: false,
            // headers: {},
            // baseURL: '',
        })
        .then((res) => {
            console.log(res);
            console.log(res.status, res.msg, res.data);
        })
        .catch((err) => {
            console.log(err);
        });

    四. vscode配置

     1. 在vscode中设置选项中,输入配置,然后选择settings.json,进行配置

     

    2.  分享一个vscode的配置

    {
      "workbench.iconTheme": "vscode-great-icons",
      "editor.fontSize": 17,
      "eslint.migration.2_x": "off",
      "[javascript]": {
        "editor.defaultFormatter": "dbaeumer.vscode-eslint"
      },
      "files.autoSave": "afterDelay",
      "editor.tabSize": 2,
      "terminal.integrated.fontSize": 16,
      "editor.renderWhitespace": "all",
      "editor.quickSuggestions": {
        "strings": true
      },
      "debug.console.fontSize": 15,
      "window.zoomLevel": 1,
      "emmet.includeLanguages": {
        "javascript": "javascriptreact"
      },
      "explorer.confirmDragAndDrop": false,
      "workbench.tree.indent": 16,
      "javascript.updateImportsOnFileMove.enabled": "always",
      "editor.wordWrap": "on",
      "path-intellisense.mappings": {
        "@": "${workspaceRoot}/src"
      },
      "hediet.vscode-drawio.local-storage": "eyIuZHJhd2lvLWNvbmZpZyI6IntcImxhbmd1YWdlXCI6XCJcIixcImN1c3RvbUZvbnRzXCI6W10sXCJsaWJyYXJpZXNcIjpcImdlbmVyYWw7YmFzaWM7YXJyb3dzMjtmbG93Y2hhcnQ7ZXI7c2l0ZW1hcDt1bWw7YnBtbjt3ZWJpY29uc1wiLFwiY3VzdG9tTGlicmFyaWVzXCI6W1wiTC5zY3JhdGNocGFkXCJdLFwicGx1Z2luc1wiOltdLFwicmVjZW50Q29sb3JzXCI6W1wiRkYwMDAwXCIsXCIwMENDNjZcIixcIm5vbmVcIixcIkNDRTVGRlwiLFwiNTI1MjUyXCIsXCJGRjMzMzNcIixcIjMzMzMzM1wiLFwiMzMwMDAwXCIsXCIwMENDQ0NcIixcIkZGNjZCM1wiLFwiRkZGRkZGMDBcIl0sXCJmb3JtYXRXaWR0aFwiOjI0MCxcImNyZWF0ZVRhcmdldFwiOmZhbHNlLFwicGFnZUZvcm1hdFwiOntcInhcIjowLFwieVwiOjAsXCJ3aWR0aFwiOjExNjksXCJoZWlnaHRcIjoxNjU0fSxcInNlYXJjaFwiOnRydWUsXCJzaG93U3RhcnRTY3JlZW5cIjp0cnVlLFwiZ3JpZENvbG9yXCI6XCIjZDBkMGQwXCIsXCJkYXJrR3JpZENvbG9yXCI6XCIjNmU2ZTZlXCIsXCJhdXRvc2F2ZVwiOnRydWUsXCJyZXNpemVJbWFnZXNcIjpudWxsLFwib3BlbkNvdW50ZXJcIjowLFwidmVyc2lvblwiOjE4LFwidW5pdFwiOjEsXCJpc1J1bGVyT25cIjpmYWxzZSxcInVpXCI6XCJcIn0ifQ==",
      "hediet.vscode-drawio.theme": "Kennedy",
      "editor.fontFamily": "Source Code Pro, 'Courier New', monospace",
      "editor.smoothScrolling": true,
      "editor.formatOnSave": true,
      "editor.defaultFormatter": "esbenp.prettier-vscode",
      "workbench.colorTheme": "Atom One Dark",
      "vetur.completion.autoImport": false,
      "security.workspace.trust.untrustedFiles": "open",
      "eslint.lintTask.enable": true,
      "eslint.alwaysShowStatus": true,
      "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
      }
    }
    View Code

    五. 区分不同环境

    1. 方案1-手动修改

    (不可取)

    //写法1:每次手动改
    const BASE_URL = 'https://www.ypf.org/test';
    const BASE_NAME = 'ypf';
    export { BASE_URL, BASE_NAME };

    2. 方案2-根据process.env.NODE_ENV进行区分

    (推荐)

    原理:根据cli内置的一个值, process.env.NODE_ENV ,开发环境下为development,生产环境下为production,测试环境下为test,编写一个config.ts文件,if判断,从而对外导出。

    分享config.ts代码 

    //写法2:根据process.env.NODE_ENV进行区分
    // 开发环境: development
    // 生成环境: production
    // 测试环境: test
    let BASE_URL = '';
    if (process.env.NODE_ENV === 'development') {
        BASE_URL = 'http://127.0.0.1:8000/';
    } else if (process.env.NODE_ENV === 'production') {
        BASE_URL = 'http://ypf.org/prod';
    } else {
        BASE_URL = 'http://ypf.org/test';
    }
    export { BASE_URL }; 

    3. 方案3-编写不同环境变量配置文件 

    (推荐)

    详见:https://cli.vuejs.org/zh/guide/mode-and-env.html#模式

    (1). 定义3个不同的文件,分别如下,这三个名称是固定的,分别在里面定义变量。

      .env  (各种环境都可以获取)

      .env.development  (开发环境获取)

      .env.production        (生产环境获取)

    .env代码如下:

    /* 开发和生产环境都能获取 */
    VUE_APP_NAME=ypf0

    .env.development 代码如下:

    VUE_APP_BASE_URL=https://ypf.org/dev
    VUE_APP_BASE_NAME=ypf2

    .env.production代码如下:

    VUE_APP_BASE_URL=https://ypf.org/prod
    VUE_APP_BASE_NAME=ypf1

     特别注意:只有 NODE_ENV,BASE_URL 和以 VUE_APP_ 开头的变量将通过 webpack.DefinePlugin 静态地嵌入到客户端侧的代码中。

    (2). 测试代码 

      需要用process.env.xxx进行调用

        export default defineComponent({
            setup() {// 测试写法3
                console.log('测试写法3');
                console.log(process.env.VUE_APP_BASE_URL);
                console.log(process.env.VUE_APP_BASE_NAME);
                console.log(process.env.VUE_APP_NAME);
            },
        });

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    在位图上写字
    删除文件到回收站中
    Blog改名字了
    [C#]强类型
    [C#] 如何选择一个目录
    [.NET]Visual Studio 2003的一个bug
    PHP句法规则详解
    php获取本地实际IP
    从0开始学编程(1)115 大致了解
    httpd2.2.21 + php5.3.8 自动安装脚本
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/15573314.html
Copyright © 2011-2022 走看看