1. 开发自由度与开发疑问
1.项目脚手架依赖的组件包来源于私有库子项目的 egova-component-web
![](https://img.haomeiwen.com/i19550826/e4f0d2ff54c55722.png)
2.egova-component-web 项目使用了npm7的workspaces特性,需要先npm i -g npm升级npm,然后会根据配置的workspaces来npm install这些工作区下的目录里的package.json依赖,以此填补了node_moudules的空间黑洞,非常给力,yarn旧版本就有,只不过我们yarn用的比较少
![](https://img.haomeiwen.com/i19550826/521b76f1e83b8794.png)
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. 接下来开始项目结构解析
![](https://img.haomeiwen.com/i19550826/540e69ce9a5d0078.png)
![](https://img.haomeiwen.com/i19550826/f2c44ae24b6b81f6.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的形式来引用子组件
网友评论