javascript - 使用 ES6 模块时,在 2 个网页之间共享非常相似的代码
问题描述
解释
我有 2 个使用不同入口点的应用程序/网页,我们分别调用它们app1
和app2
,它们分别使用entry1.js
和entry2.js
。在这两个应用程序中,我都使用了非常通用的模块,它们存储在一个shared
文件夹中。
我在我的项目中使用 OpenLayers,其概念是我有一个“第 1 页”和一个“第 2 页”,它们有很多共同点(地图、相同的特征样式、一些图层、相同的数据存储逻辑),但也很多不同的东西(一些层次,商店的内容,我使用商店做事的方式)。
我目前使用的文件结构如下所示:
entry1.js
entry2.js
app1/
map.js
[...]
app2/
map.js
[...]
shared/
pointsLayer.js
store.js
styles.js
[...]
在此示例中,pointsLayer
应用程序之间使用完全相同的逻辑,但我获取点样式的方式不同。
entry1.js
import './app1/map';
import { togglePoint } from './shared/pointsLayer';
// pointsLayer is used here to bind the togglePoint function to the DOM event
$('.point-checkbox').change(function() {
let $this = $(this);
let eid = $this.data('eid');
togglePoint(eid, $this.is(':checked'));
});
entry2.js
import './app2/map';
import { togglePoint } from './shared/pointsLayer';
// pointsLayer is used here to bind the togglePoint function to the DOM event
$('.another-point-checkbox').change(function() {
// Bind the function to another DOM element than app1
// [...]
togglePoint(eid, $this.is(':checked'));
});
app1/map.js
和app2/map.js
// The files looks the same because I only extracted what's relevant for you
import { Map, View } from 'ol';
import pointLayer, { updatePoint } from '../shared/pointsLayer';
const map = new Map({
layers: [pointLayer],
target: 'map',
view: new View([/*...*/])
});
map.addEventListener /* ... */
// Here, on a specific map event, I call updatePoint(eid, position)
shared/store.js
// Here I initialise some data that come from the Global Scope
// This module allows me to share data between ES modules
export default {
a: window.a,
b: window.b
};
// In app1, a will be set, b will be undefined
// In app2, a will be undefined, b will be set
// a and b contain information used to set the color of a Feature Style
// That's part of the problem I'm trying to resolve
shared/styles.js
import { Circle, Fill, Stroke, Style, Text } from 'ol/style';
import Store from './store';
function getElementColor(eid) {
// Here
// I need to access Store.a[eid].color when it's app1
// Or access Store.b[eid].color when it's app2
}
function getPointStyle(eid) {
return new Style({
image: new Circle({
fill: new Fill({
color: getElementColor(eid)
}),
radius: 6,
stroke: new Stroke({
color: '#000',
width: 2
})
})
});
}
export { getPointStyle };
shared/pointsLayer.js
import { Feature } from 'ol';
import { Point } from 'ol/geom';
import { Vector as VectorSource } from 'ol/source';
import { Vector as VectorLayer } from 'ol/layer';
import Styles from './styles';
const points = {};
const source = new VectorSource();
const layer = new VectorLayer({
source: source,
style: new Style(null)
});
export function updatePoint(eid, position) {
// Do stuff to update a point using the provided eid and position
// I call the getPointStyle function from 'shared/styles.js' here
// [...]
points[eid].setStyle(Styles.getPointStyle(eid));
// [...]
}
export function togglePoint(eid, visible) {
// Do stuff to toggle a point visible or not
// Also uses Styles.getPointStyle(eid) to set the corresponding style
}
export default layer;
问题
我的问题是shared/pointsLayer
文件中的所有内容都可以在两个应用程序中使用,但是该模块依赖于另一个模块,该模块在其中做不同的事情并将app1
a应用于a (请参阅 中的函数)。app2
color
Style
Point
getElementColor
shared/styles.js
我想我可以让getElementColor
函数做类似的事情,if (Store.a === undefined) { // I am in app2 } [...]
但我很确定这不是处理这个问题的好方法。
我想到了另外两个想法,但我也不满意。
理念一
- 设置 Store.app = "app1" 在
app1/map.js
- 设置 Store.app = "app2" 在
app2/map.js
getElementColor
在函数中检查 Store.app 的值
map.js
import { Map, View } from 'ol';
import pointLayer, { updatePoint } from '../shared/pointsLayer';
// HERE
import Store from '../shared/store';
Store.app = "app1"; // Or "app2"
const map = new Map({
layers: [pointLayer],
target: 'map',
view: new View([/*...*/])
});
map.addEventListener /* ... */
// Here, on a specific map event, I call updatePoint(eid, position)
shared/styles.js
// [...]
function getElementColor(eid) {
if (Store.app == 'app1') {
// Access Store.a[eid].color
} else {
// Access Store.b[eid].color
}
}
// [...]
想法 2
pointsLayer
添加一个函数来设置模块内部的“样式函数”- 不再依赖
shared/styles.js
内部pointsLayer
模块 - 使用中的功能
map.js
shared/pointsLayer.js
import { Feature } from 'ol';
import { Point } from 'ol/geom';
import { Vector as VectorSource } from 'ol/source';
import { Vector as VectorLayer } from 'ol/layer';
const points = {};
const source = new VectorSource();
const layer = new VectorLayer({
source: source,
style: new Style(null)
});
// HERE
let getPointColor = () => {};
export function setGetPointColor(fct) {
getPointColor = fct;
}
function getPointStyle(eid) {
return new Style({
image: new Circle({
fill: new Fill({
color: getPointColor(eid)
}),
radius: 6,
stroke: new Stroke({
color: '#000',
width: 2
})
})
});
}
//
export function updatePoint(eid, position) {
// [...]
points[eid].setStyle(getPointStyle(eid));
// [...]
}
export function togglePoint(eid, visible) {
// Also uses getPointStyle(eid) to set the corresponding style
}
export default layer;
app1/map.js
和app2/map.js
import { Map, View } from 'ol';
import pointLayer, { updatePoint, setGetPointColor } from '../shared/pointsLayer';
// HERE
setGetPointColor(function(eid) {
let element = Store.a[eid]; // Or Store.b[eid]
if (!element) {
// Log, error, whatever...
return '#000';
}
return element.color;
});
const map = new Map({
layers: [pointLayer],
target: 'map',
view: new View([/*...*/])
});
map.addEventListener /* ... */
// Here, on a specific map event, I call updatePoint(eid, position)
这些解决方案/想法对我来说都不合适,我是使用 ES6 的新手,我想也许我错过了一些重要的 ES 模块概念?
您的帮助将不胜感激。
解决方案
推荐阅读
- c++ - 当我指定 T 必须基于 C++ 中的某个类时,如何调用泛型变量的方法?
- wordpress - woocommerce结帐页面不断加载
- django - 如何在使用 django 按下 html 按钮时将布尔值保存到数据库中
- anova - welch-anova 之后的事后检验
- c# - 工厂服务和注入.net core 3.1
- php - Laravel 两次重定向到同一条路线
- hibernate - 如何使用 HibernateTemplate 和 spring mvc 检查数据库数据中的电子邮件和密码以检查正确的电子邮件和密码
- c# - 如何从 iOS AppDelegate.cs 中的方法访问共享项目数据对象?
- java - 你能帮我while-if-break后面的所有短语有什么问题吗?
- php - 如何在elementor SELECT2控件中显示帖子名称和帖子链接