1. 開(kāi)發(fā)自由度與開(kāi)發(fā)疑問(wèn)
1.項(xiàng)目腳手架依賴的組件包來(lái)源于私有庫(kù)子項(xiàng)目的 egova-component-web

2.egova-component-web 項(xiàng)目使用了npm7的workspaces特性,需要先npm i -g npm升級(jí)npm,然后會(huì)根據(jù)配置的workspaces來(lái)npm install這些工作區(qū)下的目錄里的package.json依賴,以此填補(bǔ)了node_moudules的空間黑洞,非常給力,yarn舊版本就有,只不過(guò)我們yarn用的比較少

3.npmrc文件的作用,就是配置npm源
4.先 npm run lib:dist npm run ui:dist來(lái)構(gòu)建本地代碼到node_modules下對(duì)應(yīng)包的dist,來(lái)維持本地開(kāi)發(fā)
5.npm run web:serve來(lái)測(cè)試修改或者開(kāi)發(fā)的代碼(公用組件),組件必須為受控支持v-model雙向綁定
6.vue.config.js 是一個(gè)可選的配置文件,如果項(xiàng)目的 (和 package.json 同級(jí)的) 根目錄中存在這個(gè)文件,那么它會(huì)被 @vue/cli-service 自動(dòng)加載。也可以使用 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 是否在保存的時(shí)候檢查
lintOnSave: true,
//放置生成的靜態(tài)資源 (js、css、img、fonts) 的 (相對(duì)于 outputDir 的) 目錄。
assetsDir: "static",
//以多頁(yè)模式構(gòu)建應(yīng)用程序。
pages: pageConfig.pages,
//是否使用包含運(yùn)行時(shí)編譯器的 Vue 構(gòu)建版本
runtimeCompiler: true,
//是否為 Babel 或 TypeScript 使用 thread-loader。該選項(xiàng)在系統(tǒng)的 CPU 有多于一個(gè)內(nèi)核時(shí)自動(dòng)啟用,僅作用于生產(chǎn)構(gòu)建,在適當(dāng)?shù)臅r(shí)候開(kāi)啟幾個(gè)子進(jìn)程去并發(fā)的執(zhí)行壓縮
parallel: require("os").cpus().length > 1,
//生產(chǎn)環(huán)境是否生成 sourceMap 文件,一般情況不建議打開(kāi)
productionSourceMap: false,
// webpack配置
//對(duì)內(nèi)部的 webpack 配置進(jìn)行更細(xì)粒度的修改 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") }) 這種模版加載方式
// 注意:寫(xiě)include和exclude要在use和loader之前寫(xiě)
config.module
.rule("html")
.test(/\.html$/)
.exclude.add(/public/)
.end()
.use("raw-loader")
.loader("raw-loader");
// 只輸出src下ts文件錯(cuò)誤
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);
},
//調(diào)整 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,
// 開(kāi)啟 CSS source maps,一般不建議開(kāi)啟
sourceMap: false,
// css預(yù)設(shè)器配置項(xiàng)
loaderOptions: {
sass: {
//設(shè)置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 相關(guān)配置 https://webpack.js.org/configuration/dev-server/
devServer: {
headers: {
"Access-Control-Allow-Origin": "*"
},
host: "0.0.0.0",
port: 8100, // 端口號(hào)
https: false, // https:{type:Boolean}
open: true, //配置自動(dòng)啟動(dòng)瀏覽器 http://172.16.1.12:7071/rest/mcdPhoneBar/
hot: true // 熱更新
// proxy: 'http://localhost:8000' // 配置跨域處理,只有一個(gè)代理
},
// 第三方插件配置 https://www.npmjs.com/package/vue-cli-plugin-style-resources-loader
pluginOptions: require("./dll.config")
};
2. 接下來(lái)開(kāi)始項(xiàng)目結(jié)構(gòu)解析


component的實(shí)際導(dǎo)出就是來(lái)自vue-class-component的vue類組件裝飾器,并且默認(rèn)將我們要實(shí)現(xiàn)的頁(yè)面組件進(jìn)行了鉤子掛載,在類里實(shí)現(xiàn)對(duì)應(yīng)的方法
(應(yīng)該是個(gè)迭代器方法)即可, 如:
@Component
class MyComp extends Vue {
// class 組件現(xiàn)在可以處理 beforeRouteEnter 鉤子和
// beforeRouteLeave 鉤子作為 Vue Router 鉤子
beforeRouteEnter (to, from, next) {
console.log('beforeRouteEnter')
next() // 需要調(diào)用這個(gè)來(lái)確認(rèn)導(dǎo)航
}
beforeRouteLeave (to, from, next) {
console.log('beforeRouteLeave')
next() // 需要調(diào)用這個(gè)來(lái)確認(rèn)導(dǎo)航
}
}
來(lái)看一下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 綁定的屬性名
這個(gè)屬性裝飾器將service的flagwind.Activator.createInstance封裝實(shí)例進(jìn)行了在ObjectFactory的上的map靜態(tài)屬性掛載,并且也能通過(guò)組件的屬性名來(lái)調(diào)用這個(gè)實(shí)例
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);
}
}
所以,這個(gè)ObjectFactory的實(shí)例可以通過(guò)原型鏈來(lái)獲取所有組件注冊(cè)的Service類,暫時(shí)不知道有啥用,還待研究。。。
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的形式來(lái)引用子組件