美文网首页
egova-treasure 项目架构观后有感

egova-treasure 项目架构观后有感

作者: 皮神雷卡丘 | 来源:发表于2021-11-22 17:01 被阅读0次

1. 开发自由度与开发疑问

1.项目脚手架依赖的组件包来源于私有库子项目的 egova-component-web

image

2.egova-component-web 项目使用了npm7的workspaces特性,需要先npm i -g npm升级npm,然后会根据配置的workspaces来npm install这些工作区下的目录里的package.json依赖,以此填补了node_moudules的空间黑洞,非常给力,yarn旧版本就有,只不过我们yarn用的比较少

image

3.npmrc文件的作用,就是配置npm源

4.先 npm run lib:dist npm run ui:dist来构建本地代码到node_modules下对应包的dist,来维持本地开发

5.npm run web:serve来测试修改或者开发的代码(公用组件),组件必须为受控支持v-model双向绑定

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


// require("@hapi/joi");

const path = require("path");

const { name } = require("./package");

const isProd = process.env.NODE_ENV === "production";

const pageConfig = require("./page.config");

module.exports = {

    //基本路径

    publicPath: "./",

    //输出文件目录

    outputDir: "dist",

    // eslint-loader 是否在保存的时候检查

    lintOnSave: true,

    //放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。

    assetsDir: "static",

    //以多页模式构建应用程序。

    pages: pageConfig.pages,

    //是否使用包含运行时编译器的 Vue 构建版本

    runtimeCompiler: true,

    //是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建,在适当的时候开启几个子进程去并发的执行压缩

    parallel: require("os").cpus().length > 1,

    //生产环境是否生成 sourceMap 文件,一般情况不建议打开

    productionSourceMap: false,

    // webpack配置

    //对内部的 webpack 配置进行更细粒度的修改 https://github.com/neutrinojs/webpack-chain see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md

    chainWebpack: (config) => {

        // 以便支持 @component({ template: require("./index.html") }) 这种模版加载方式

        // 注意:写include和exclude要在use和loader之前写

        config.module

            .rule("html")

            .test(/\.html$/)

            .exclude.add(/public/)

            .end()

            .use("raw-loader")

            .loader("raw-loader");

        // 只输出src下ts文件错误

        config.plugin("fork-ts-checker").tap((args) => {

            args[0].reportFiles = ["src/**/*.{ts,tsx}"];

            return args;

        });

        config.resolve.alias.set("@", path.join(__dirname, "src"));

        pageConfig.plugin(config);

    },

    //调整 webpack 配置 https://cli.vuejs.org/zh/guide/webpack.html#%E7%AE%80%E5%8D%95%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F

    configureWebpack: (config) => {

        const StyleLintPlugin = require("stylelint-webpack-plugin");

        config.plugins.push(

            new StyleLintPlugin({

                files: ["src/**/*.{vue,html,css,scss,sass,less}"],

                failOnError: false,

                cache: true,

                fix: false

            })

        );

        config.output.library = `${name}-[name]`;

        config.output.libraryTarget = "umd";

        config.output.jsonpFunction = `webpackJsonp_${name}`;

    },

    css: {

        // // 启用 CSS modules

        requireModuleExtension: true,

        // 是否使用css分离插件

        extract: isProd,

        // 开启 CSS source maps,一般不建议开启

        sourceMap: false,

        // css预设器配置项

        loaderOptions: {

            sass: {

                //设置css中引用文件的路径,引入通用使用的scss文件(如包含的@mixin)

                prependData: `

        $baseUrl: "/";

                @import '~@/assets/styles/common/_var.scss';

                @import '~@/assets/styles/common/_mixin.scss';

                @import '~@/assets/styles/common/_function.scss';

        `

            }

        }

    },

    // webpack-dev-server 相关配置 https://webpack.js.org/configuration/dev-server/

    devServer: {

        headers: {

            "Access-Control-Allow-Origin": "*"

        },

        host: "0.0.0.0",

        port: 8100, // 端口号

        https: false, // https:{type:Boolean}

        open: true, //配置自动启动浏览器  http://172.16.1.12:7071/rest/mcdPhoneBar/

        hot: true // 热更新

        // proxy: 'http://localhost:8000'   // 配置跨域处理,只有一个代理

    },

    // 第三方插件配置 https://www.npmjs.com/package/vue-cli-plugin-style-resources-loader

    pluginOptions: require("./dll.config")

};

2. 接下来开始项目结构解析

程序入口main.ts image.png
component的实际导出就是来自vue-class-component的vue类组件装饰器,并且默认将我们要实现的页面组件进行了钩子挂载,在类里实现对应的方法(应该是个迭代器方法)即可, 如:
@Component
class MyComp extends Vue {
  // class 组件现在可以处理 beforeRouteEnter 钩子和 
  // beforeRouteLeave 钩子作为 Vue Router 钩子
  beforeRouteEnter (to, from, next) {
    console.log('beforeRouteEnter')
    next() // 需要调用这个来确认导航
  }

  beforeRouteLeave (to, from, next) {
    console.log('beforeRouteLeave')
    next() // 需要调用这个来确认导航
  }
}

来看一下autoWired的代码

export function autowired(serviceType: Function) {
    return function (target: any, name: any) {
        let serviceInstanceName = serviceType;
        if (serviceInstanceName && !ObjectFactory.has(serviceInstanceName)) {
            ObjectFactory.set(serviceInstanceName, ObjectFactory.create(serviceType));
        }
        if (serviceInstanceName) {
            Object.defineProperty(target, name, {
                get: function () {
                    return ObjectFactory.get(serviceInstanceName);
                },
            });
        }
    };
}

serviceType service类
target 组件类
name 绑定的属性名

这个属性装饰器将service的flagwind.Activator.createInstance封装实例进行了在ObjectFactory的上的map静态属性挂载,并且也能通过组件的属性名来调用这个实例

import flagwind from "@egova/flagwind-core";

export class ObjectFactory {
  public static maps: Map<any, any> = new Map<any, any>();

  public static get(key: any): any {
    return this.maps.get(key);
  }

  public static set(key: any, value: any) {
    this.maps.set(key, value);
  }

  public static has(key: any): boolean {
    return this.maps.has(key);
  }

  public static match(head: any): Array<any> {
    let list = new Array<any>();
    this.maps.forEach((value, key) => {
      if (key.startsWith(head)) {
        list.push(value);
      }
    });
    return list;
  }

  public static create<T>(serviceType: Function | string, ...params: Array<any>) {
    return flagwind.Activator.createInstance<T>(serviceType, ...params);
  }
}

所以,这个ObjectFactory的实例可以通过原型链来获取所有组件注册的Service类,暂时不知道有啥用,还待研究。。。

3. 组件引用

@component({
  template: require("./index.html"),
  components: {
    "u-header": HeaderComponent
  }
})
<!DOCTYPE html>
<div class="v-layout-wrapper">
    <u-header v-if="!hideHeader"> </u-header>
    <section class="main-content">
        <keep-alive>
            <router-view v-if="$route.meta.keepAlive"> </router-view>
        </keep-alive>
        <router-view v-if="!$route.meta.keepAlive"> </router-view>
    </section>
</div>

采用配置key value的形式来引用子组件

相关文章

网友评论

      本文标题:egova-treasure 项目架构观后有感

      本文链接:https://www.haomeiwen.com/subject/fupbtrtx.html