本文将介绍如何通过RxJS+TS实现模块间的松耦合。所谓松耦合是指模块间不能存在显示的引用关系。公司项目中经常看到junior程序员写出如下的代码:
var moduleA = {
foo: function() {
moduleB.doSomeThing();
moduleC.doSomeThing();
}
dummy: function() {}
}
var moduleB = {
doSomeThing: function() {}
doAnotherThing: function() {
moduleA.dummy();
}
}
var moduleC = {
doSomeThing: function() {}
}
显然这种代码极其糟糕,模块间互相引用,一旦修改就会漏洞百出。 那么作为tech manager,我提出了几种修改建议。 首先,建立demo环境
npm init -y
npm install rxjs ts-loader typescript webpack webpack-dev-server --save
npm install webpack-cli --save-dev
tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"noImplicitAny": true,
"module": "es6",
"moduleResolution": "node",
"sourceMap": true,
"target": "es6",
"experimentalDecorators": true,
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
}
}
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.ts',
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
public/index.html
<html>
<head>
<title>Demo</title>
</head>
<body>
<style>
#app {
width: 100%;
height: 400px;
display: flex;
}
#toolDiv {
width: 100%;
height: 50px;
background-color:cornsilk;
}
#leftDiv {
width: 50%;
height: 100%;
background-color:chocolate;
}
#rightDiv {
width: 50%;
height: 100%;
background-color: burlywood;
}
</style>
<div id="toolDiv">
<input type="button" id="btnCount" value="+1" />
<input type="button" id="btnMinus" value="-1" />
</div>
<div id="app" style="width:100%; height: 400px;">
<div id="leftDiv">
<p id="leftCount">0</p>
</div>
<div id="rightDiv">
<p id="rightCount">0</p>
</div>
<div id="middleDiv">
<p id="middleCount">0</p>
</div>
</div>
</body>
<script src="/bundle.js"></script>
</html>
src/index.ts //方案一
namespace Index {
type addClickEvent = () => void;
class ToolBar {
private btnAdd: HTMLElement;
private addCB: addClickEvent
constructor(_addCallBack: addClickEvent) {
this.btnAdd = document.getElementById("btnCount");
this.btnAdd.onclick = this.AddClickHandler.bind(this);
this.addCB = _addCallBack;
}
private AddClickHandler() {
this.addCB && this.addCB();
}
}
class Left {
public handleAdd() {
const counter = document.getElementById('leftCount');
counter.innerText = (parseInt(counter.innerText)+1).toString();
}
}
class Right {
public handleAdd() {
const counter = document.getElementById('rightCount');
counter.innerText = (parseInt(counter.innerText)+1).toString();
}
}
class App {
private toolBar: ToolBar;
private leftCom: Left;
private rightCom: Right;
constructor() {
this.leftCom = new Left();
this.rightCom = new Right();
this.toolBar = new ToolBar(this.onAddClick.bind(this));
}
private onAddClick() {
this.leftCom.handleAdd();
this.rightCom.handleAdd();
}
}
const app = new App();
}