qlfy-postmate 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -11
- package/lib/index.mjs +151 -75
- package/lib/index.mjs.gz +0 -0
- package/lib/index.umd.js +1 -1
- package/lib/postMeta/ChildPostmate.d.ts +20 -1
- package/lib/postMeta/ParentPostmate.d.ts +59 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,8 @@ import { ChildPostmate } from 'qlfy-postmate'
|
|
|
14
14
|
|
|
15
15
|
#### 3、使用
|
|
16
16
|
|
|
17
|
-
```
|
|
17
|
+
```js
|
|
18
|
+
// 基本使用
|
|
18
19
|
const childrenComm = new ChildPostmate({
|
|
19
20
|
error: (err: any) => {
|
|
20
21
|
console.log('-----------------链接失败-----------------', err)
|
|
@@ -26,6 +27,22 @@ const childrenComm = new ChildPostmate({
|
|
|
26
27
|
console.log('-----------------接收数据-----------------', dataInfo)
|
|
27
28
|
},
|
|
28
29
|
})
|
|
30
|
+
|
|
31
|
+
// 带路由功能的使用(推荐)
|
|
32
|
+
import { useRouter } from 'vue-router'
|
|
33
|
+
|
|
34
|
+
const router = useRouter()
|
|
35
|
+
const childrenComm = new ChildPostmate({
|
|
36
|
+
error: (err: any) => {
|
|
37
|
+
console.log('-----------------链接失败-----------------', err)
|
|
38
|
+
},
|
|
39
|
+
success: (success: any) => {
|
|
40
|
+
console.log('-----------------链接成功-----------------', success)
|
|
41
|
+
},
|
|
42
|
+
receive: (dataInfo: any) => {
|
|
43
|
+
console.log('-----------------接收数据-----------------', dataInfo)
|
|
44
|
+
},
|
|
45
|
+
}, router) // 传入router实例,支持路由更新功能
|
|
29
46
|
```
|
|
30
47
|
|
|
31
48
|
#### 4、参数对象说明
|
|
@@ -38,9 +55,11 @@ const childrenComm = new ChildPostmate({
|
|
|
38
55
|
|
|
39
56
|
#### 5、方法
|
|
40
57
|
|
|
41
|
-
| 名称
|
|
42
|
-
|
|
|
43
|
-
| getData
|
|
58
|
+
| 名称 | 解释 | 使用 |
|
|
59
|
+
| ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
|
60
|
+
| getData | 链接成功后<br />可通过ChildPostmate实例对象,主动向父页面获取数据 | getData((dataInfo)=>void) |
|
|
61
|
+
| setRouter | 设置Vue Router实例和自定义路由更新回调函数<br />用于在实例创建后设置或更新路由实例 | setRouter(router, [routeUpdateCallback]) |
|
|
62
|
+
| sendOtherRequest | 向父页面发送自定义请求 | sendOtherRequest(params) |
|
|
44
63
|
|
|
45
64
|
#### 注意:
|
|
46
65
|
|
|
@@ -48,7 +67,16 @@ const childrenComm = new ChildPostmate({
|
|
|
48
67
|
|
|
49
68
|
2、getData方法,仅能在链接创建完成后再调用
|
|
50
69
|
|
|
51
|
-
3
|
|
70
|
+
3、路由更新功能需要传入Vue Router实例才能使用
|
|
71
|
+
|
|
72
|
+
4、路由更新功能会自动判断URL变化类型:
|
|
73
|
+
- 如果只有查询参数或哈希变化,只更新参数,不刷新页面
|
|
74
|
+
- 如果路径变化,会更新整个路由路径,但不会刷新页面
|
|
75
|
+
- 如果协议、主机或端口变化,会重新加载iframe
|
|
76
|
+
|
|
77
|
+
5、如果需要自定义路由更新逻辑,可以传入routeUpdateCallback回调函数
|
|
78
|
+
|
|
79
|
+
6、error、success函数仅作为链接状态的标注函数,不传递数据
|
|
52
80
|
|
|
53
81
|
|
|
54
82
|
|
|
@@ -102,6 +130,7 @@ App.vue
|
|
|
102
130
|
|
|
103
131
|
<script setup lang="ts">
|
|
104
132
|
import { ref } from 'vue'
|
|
133
|
+
import { useRouter } from 'vue-router'
|
|
105
134
|
import { useSystemStore } from '@/store/modules/system'
|
|
106
135
|
import { ChildPostmate } from 'qlfy-postmate'
|
|
107
136
|
|
|
@@ -117,6 +146,9 @@ initPostMate()
|
|
|
117
146
|
// 方法 -- 初始化postmate链接
|
|
118
147
|
function initPostMate() {
|
|
119
148
|
loading.value = true
|
|
149
|
+
// 获取router实例
|
|
150
|
+
const router = useRouter()
|
|
151
|
+
|
|
120
152
|
const childrenComm = new ChildPostmate({
|
|
121
153
|
error: (err: any) => {
|
|
122
154
|
console.log('-----------------链接失败-----------------')
|
|
@@ -147,7 +179,7 @@ function initPostMate() {
|
|
|
147
179
|
// 保存token
|
|
148
180
|
systemStore.setTooken(dataInfo.data.token)
|
|
149
181
|
},
|
|
150
|
-
})
|
|
182
|
+
}, router) // 传入router实例,支持路由更新功能
|
|
151
183
|
}
|
|
152
184
|
</script>
|
|
153
185
|
|
|
@@ -157,8 +189,7 @@ function initPostMate() {
|
|
|
157
189
|
|
|
158
190
|
### 样例二(main.js)【推荐】:
|
|
159
191
|
|
|
160
|
-
```
|
|
161
|
-
|
|
192
|
+
```js
|
|
162
193
|
import { createApp } from "vue";
|
|
163
194
|
import App from "./App.vue";
|
|
164
195
|
import { ChildPostmate } from 'qlfy-postmate'
|
|
@@ -178,7 +209,7 @@ let flag = true
|
|
|
178
209
|
// pinia模块
|
|
179
210
|
import useCounterStore from "@/store/index.js";
|
|
180
211
|
const $store = useCounterStore();
|
|
181
|
-
//
|
|
212
|
+
// 创建链接,传入router实例以支持路由更新功能
|
|
182
213
|
new ChildPostmate({
|
|
183
214
|
error: (err) => {
|
|
184
215
|
console.log('-----------------链接失败-----------------')
|
|
@@ -191,7 +222,7 @@ new ChildPostmate({
|
|
|
191
222
|
},
|
|
192
223
|
|
|
193
224
|
// 异步方法
|
|
194
|
-
receive:
|
|
225
|
+
receive: (dataInfo) => {
|
|
195
226
|
console.log('-----------------接收数据-----------------')
|
|
196
227
|
console.log(dataInfo)
|
|
197
228
|
if (dataInfo.status !== 200) return
|
|
@@ -209,10 +240,64 @@ new ChildPostmate({
|
|
|
209
240
|
}
|
|
210
241
|
flag = false
|
|
211
242
|
},
|
|
212
|
-
})
|
|
243
|
+
}, router) // 传入router实例,支持路由更新功能
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
### 父页面使用说明(ParentPostmate)
|
|
249
|
+
|
|
250
|
+
#### 1、导入
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
import { ParentPostmate } from 'qlfy-postmate'
|
|
213
254
|
```
|
|
214
255
|
|
|
256
|
+
#### 2、基本使用
|
|
257
|
+
|
|
258
|
+
```js
|
|
259
|
+
// 创建父页面通信实例
|
|
260
|
+
const parentComm = new ParentPostmate(
|
|
261
|
+
// 传递给子页面的数据
|
|
262
|
+
{
|
|
263
|
+
loginInfo: { /* 登录信息 */ },
|
|
264
|
+
token: 'token字符串',
|
|
265
|
+
isHideHeader: true
|
|
266
|
+
},
|
|
267
|
+
// iframe容器元素
|
|
268
|
+
document.getElementById('iframe-container'),
|
|
269
|
+
// 子页面URL
|
|
270
|
+
'http://example.com/child-page',
|
|
271
|
+
// 处理子页面其他请求的回调函数
|
|
272
|
+
(params) => {
|
|
273
|
+
console.log('收到子页面请求:', params)
|
|
274
|
+
}
|
|
275
|
+
)
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
#### 3、路由更新功能
|
|
279
|
+
|
|
280
|
+
当需要更新子页面URL时,只需调用`setIframeUrl`方法:
|
|
281
|
+
|
|
282
|
+
```js
|
|
283
|
+
// 更新子页面URL
|
|
284
|
+
parentComm.setIframeUrl('http://example.com/child-page/new-route?param=value')
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
系统会自动判断URL变化类型:
|
|
288
|
+
- 如果只有查询参数或哈希变化,只更新参数,不刷新页面
|
|
289
|
+
- 如果路径变化,会更新整个路由路径,但不会刷新页面
|
|
290
|
+
- 如果协议、主机或端口变化,会重新加载iframe
|
|
291
|
+
|
|
292
|
+
#### 4、方法说明
|
|
215
293
|
|
|
294
|
+
| 方法名 | 说明 | 参数 |
|
|
295
|
+
| ------ | ---- | ---- |
|
|
296
|
+
| setIframeUrl | 设置iframe的URL | (url: string) |
|
|
297
|
+
| setIframeEle | 设置iframe容器元素 | (element: HTMLElement \| (() => HTMLElement)) |
|
|
298
|
+
| sendData | 向子页面发送数据 | () |
|
|
299
|
+
| setLoadFunction | 设置iframe加载完成的回调函数 | (callback: () => void) |
|
|
300
|
+
| destroy | 销毁实例 | () |
|
|
216
301
|
|
|
217
302
|
### 集成调试
|
|
218
303
|
|
package/lib/index.mjs
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const h = "application/x-postmate-v1+json";
|
|
5
|
-
let y = 0;
|
|
6
|
-
const P = {
|
|
1
|
+
const c = "application/x-postmate-v1+json";
|
|
2
|
+
let m = 0;
|
|
3
|
+
const f = {
|
|
7
4
|
handshake: 1,
|
|
8
5
|
"handshake-reply": 1,
|
|
9
6
|
call: 1,
|
|
@@ -11,26 +8,26 @@ const P = {
|
|
|
11
8
|
reply: 1,
|
|
12
9
|
request: 1
|
|
13
10
|
};
|
|
14
|
-
function p(
|
|
15
|
-
return (typeof t != "string" ||
|
|
11
|
+
function p(n, t) {
|
|
12
|
+
return (typeof t != "string" || n.origin === t) && !!n.data && (typeof n.data != "object" || "postmate" in n.data) && n.data.type === c && !!f[n.data.postmate];
|
|
16
13
|
}
|
|
17
|
-
class
|
|
14
|
+
class g {
|
|
18
15
|
constructor(t) {
|
|
19
16
|
this.parent = t.parent, this.frame = t.frame, this.child = t.child, this.childOrigin = t.childOrigin, this.events = {}, this.listener = (e) => {
|
|
20
17
|
if (!p(e, this.childOrigin)) return;
|
|
21
|
-
const { value: s = {} } = e.data, { name: a, data:
|
|
22
|
-
e.data.postmate === "emit" && a in this.events && this.events[a].call(this,
|
|
18
|
+
const { value: s = {} } = e.data, { name: a, data: r } = s;
|
|
19
|
+
e.data.postmate === "emit" && a in this.events && this.events[a].call(this, r);
|
|
23
20
|
}, this.parent.addEventListener("message", this.listener, !1);
|
|
24
21
|
}
|
|
25
22
|
get(t) {
|
|
26
23
|
return new o.Promise((e) => {
|
|
27
|
-
const s = ++
|
|
28
|
-
|
|
24
|
+
const s = ++m, a = (r) => {
|
|
25
|
+
r.data.uid === s && r.data.postmate === "reply" && (this.parent.removeEventListener("message", a, !1), e(r.data.value));
|
|
29
26
|
};
|
|
30
27
|
this.parent.addEventListener("message", a, !1), this.child.postMessage(
|
|
31
28
|
{
|
|
32
29
|
postmate: "request",
|
|
33
|
-
type:
|
|
30
|
+
type: c,
|
|
34
31
|
property: t,
|
|
35
32
|
uid: s
|
|
36
33
|
},
|
|
@@ -42,7 +39,7 @@ class w {
|
|
|
42
39
|
this.child.postMessage(
|
|
43
40
|
{
|
|
44
41
|
postmate: "call",
|
|
45
|
-
type:
|
|
42
|
+
type: c,
|
|
46
43
|
property: t,
|
|
47
44
|
data: e
|
|
48
45
|
},
|
|
@@ -56,33 +53,33 @@ class w {
|
|
|
56
53
|
window.removeEventListener("message", this.listener, !1), this.frame.parentNode.removeChild(this.frame);
|
|
57
54
|
}
|
|
58
55
|
}
|
|
59
|
-
class
|
|
56
|
+
class P {
|
|
60
57
|
constructor(t) {
|
|
61
58
|
this.model = t.model, this.parent = t.parent, this.parentOrigin = t.parentOrigin, this.child = t.child, this.child.addEventListener("message", (e) => {
|
|
62
59
|
if (!p(e, this.parentOrigin)) return;
|
|
63
|
-
const { postmate: s, property: a, uid:
|
|
60
|
+
const { postmate: s, property: a, uid: r, data: h } = e.data, i = this.model[a];
|
|
64
61
|
if (s !== "call") {
|
|
65
|
-
const
|
|
66
|
-
o.Promise.resolve(
|
|
62
|
+
const l = typeof i == "function" ? i() : i;
|
|
63
|
+
o.Promise.resolve(l).then((d) => {
|
|
67
64
|
e.source.postMessage(
|
|
68
65
|
{
|
|
69
66
|
property: a,
|
|
70
67
|
postmate: "reply",
|
|
71
|
-
type:
|
|
72
|
-
uid:
|
|
73
|
-
value:
|
|
68
|
+
type: c,
|
|
69
|
+
uid: r,
|
|
70
|
+
value: d
|
|
74
71
|
},
|
|
75
72
|
e.origin
|
|
76
73
|
);
|
|
77
74
|
});
|
|
78
|
-
} else a in this.model && typeof
|
|
75
|
+
} else a in this.model && typeof i == "function" && i(h);
|
|
79
76
|
});
|
|
80
77
|
}
|
|
81
78
|
emit(t, e) {
|
|
82
79
|
this.parent.postMessage(
|
|
83
80
|
{
|
|
84
81
|
postmate: "emit",
|
|
85
|
-
type:
|
|
82
|
+
type: c,
|
|
86
83
|
value: { name: t, data: e }
|
|
87
84
|
},
|
|
88
85
|
this.parentOrigin
|
|
@@ -90,40 +87,40 @@ class E {
|
|
|
90
87
|
}
|
|
91
88
|
}
|
|
92
89
|
class o {
|
|
93
|
-
constructor({ container: t = document.body, model: e, url: s, name: a, classListArray:
|
|
94
|
-
return this.parent = window, this.frame = document.createElement("iframe"), this.frame.name = a || "", this.frame.classList.add(...
|
|
90
|
+
constructor({ container: t = document.body, model: e, url: s, name: a, classListArray: r = [] }) {
|
|
91
|
+
return this.parent = window, this.frame = document.createElement("iframe"), this.frame.name = a || "", this.frame.classList.add(...r), t.appendChild(this.frame), this.child = this.frame.contentWindow, this.model = e || {}, this.sendHandshake(s);
|
|
95
92
|
}
|
|
96
93
|
sendHandshake(t) {
|
|
97
94
|
const e = (() => {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
return
|
|
95
|
+
const r = document.createElement("a");
|
|
96
|
+
r.href = t;
|
|
97
|
+
const h = r.protocol.length > 4 ? r.protocol : window.location.protocol, i = r.host.length ? r.port === "80" || r.port === "443" ? r.hostname : r.host : window.location.host;
|
|
98
|
+
return r.origin || `${h}//${i}`;
|
|
102
99
|
})();
|
|
103
100
|
let s = 0, a;
|
|
104
|
-
return new o.Promise((
|
|
105
|
-
const
|
|
101
|
+
return new o.Promise((r, h) => {
|
|
102
|
+
const i = (u) => {
|
|
106
103
|
if (!p(u, e)) return !1;
|
|
107
|
-
u.data.postmate === "handshake-reply" ? (clearInterval(a), this.parent.removeEventListener("message",
|
|
104
|
+
u.data.postmate === "handshake-reply" ? (clearInterval(a), this.parent.removeEventListener("message", i, !1), this.childOrigin = u.origin, r(new g(this))) : h("Failed handshake");
|
|
108
105
|
};
|
|
109
|
-
this.parent.addEventListener("message",
|
|
110
|
-
const
|
|
106
|
+
this.parent.addEventListener("message", i, !1);
|
|
107
|
+
const l = () => {
|
|
111
108
|
s++, this.child.postMessage(
|
|
112
109
|
{
|
|
113
110
|
postmate: "handshake",
|
|
114
|
-
type:
|
|
111
|
+
type: c,
|
|
115
112
|
model: this.model
|
|
116
113
|
},
|
|
117
114
|
e
|
|
118
115
|
), s === 5 && clearInterval(a);
|
|
119
|
-
},
|
|
120
|
-
|
|
116
|
+
}, d = () => {
|
|
117
|
+
l(), a = setInterval(l, 500);
|
|
121
118
|
};
|
|
122
|
-
this.frame.onload =
|
|
119
|
+
this.frame.onload = d, this.frame.attachEvent && this.frame.attachEvent("onload", d), this.frame.src = t;
|
|
123
120
|
});
|
|
124
121
|
}
|
|
125
122
|
}
|
|
126
|
-
class
|
|
123
|
+
class y {
|
|
127
124
|
constructor(t) {
|
|
128
125
|
return this.child = window, this.model = t, this.parent = window.parent, this.sendHandshakeReply();
|
|
129
126
|
}
|
|
@@ -135,14 +132,14 @@ class I {
|
|
|
135
132
|
this.child.removeEventListener("message", this, !1), s.source.postMessage(
|
|
136
133
|
{
|
|
137
134
|
postmate: "handshake-reply",
|
|
138
|
-
type:
|
|
135
|
+
type: c
|
|
139
136
|
},
|
|
140
137
|
s.origin
|
|
141
138
|
), this.parentOrigin = s.origin;
|
|
142
139
|
const a = s.data.model;
|
|
143
|
-
a && Object.keys(a).forEach((
|
|
144
|
-
this.model[
|
|
145
|
-
}), t(new
|
|
140
|
+
a && Object.keys(a).forEach((r) => {
|
|
141
|
+
this.model[r] = a[r];
|
|
142
|
+
}), t(new P(this));
|
|
146
143
|
}
|
|
147
144
|
}, !1);
|
|
148
145
|
});
|
|
@@ -156,10 +153,10 @@ o.Promise = (() => {
|
|
|
156
153
|
return Promise;
|
|
157
154
|
}
|
|
158
155
|
})();
|
|
159
|
-
o.Model =
|
|
160
|
-
class
|
|
161
|
-
constructor(t) {
|
|
162
|
-
this.childPostmate = null, this.parentPostmate = null, this.isGetData = !1, this.getDataCllBack = null, window.top !== window.self ? this.init(t) : t.error({ status: 500, data: null, message: "未在一体化平台中运行" });
|
|
156
|
+
o.Model = y;
|
|
157
|
+
class w {
|
|
158
|
+
constructor(t, e, s) {
|
|
159
|
+
this.childPostmate = null, this.parentPostmate = null, this.isGetData = !1, this.getDataCllBack = null, this.router = null, this.routeUpdateCallback = null, this.router = e, this.routeUpdateCallback = s, window.top !== window.self ? this.init(t) : t.error({ status: 500, data: null, message: "未在一体化平台中运行" });
|
|
163
160
|
}
|
|
164
161
|
init(t) {
|
|
165
162
|
const e = this;
|
|
@@ -175,6 +172,19 @@ class k {
|
|
|
175
172
|
message: "success",
|
|
176
173
|
data: s
|
|
177
174
|
}), e.isGetData = !1;
|
|
175
|
+
},
|
|
176
|
+
// 处理路由更新
|
|
177
|
+
routeUpdate(s) {
|
|
178
|
+
try {
|
|
179
|
+
const a = JSON.parse(s);
|
|
180
|
+
if (e.routeUpdateCallback) {
|
|
181
|
+
e.routeUpdateCallback(a);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
e.router ? e.router.replace(a.fullPath) : console.warn("未提供router实例,无法进行路由更新");
|
|
185
|
+
} catch (a) {
|
|
186
|
+
console.error("路由更新失败:", a);
|
|
187
|
+
}
|
|
178
188
|
}
|
|
179
189
|
}).then((s) => {
|
|
180
190
|
e.parentPostmate = s, e.getData(), t.success({
|
|
@@ -200,25 +210,63 @@ class k {
|
|
|
200
210
|
}
|
|
201
211
|
t ? (this.isGetData = !0, this.getDataCllBack = t) : (this.isGetData = !1, this.getDataCllBack = null), this.parentPostmate.emit("requestBaseData");
|
|
202
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* 设置路由实例和路由更新回调
|
|
215
|
+
* @param router Vue Router实例
|
|
216
|
+
* @param routeUpdateCallback 自定义路由更新回调函数
|
|
217
|
+
*/
|
|
218
|
+
setRouter(t, e) {
|
|
219
|
+
this.router = t, e && (this.routeUpdateCallback = e);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* 向父页面发送其他请求
|
|
223
|
+
* @param params 请求参数
|
|
224
|
+
*/
|
|
225
|
+
sendOtherRequest(t) {
|
|
226
|
+
this.parentPostmate && this.parentPostmate.emit("otherRequest", t);
|
|
227
|
+
}
|
|
203
228
|
}
|
|
204
|
-
class
|
|
205
|
-
constructor(t, e
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
/** 通讯数据 */
|
|
209
|
-
l(this, "dataInfo", {
|
|
210
|
-
loginInfo: null,
|
|
229
|
+
class U {
|
|
230
|
+
constructor(t, e, s = "", a) {
|
|
231
|
+
this.postmateParent = null, this.dataInfo = {
|
|
232
|
+
loginInfo: {},
|
|
211
233
|
token: "",
|
|
212
234
|
isHideHeader: !0
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
235
|
+
}, this.iframeEle = null, this.currentUrl = "", this.currentIframe = null, this.loadFunction = null, this.handleOtherRequest = null, this.parsedCurrentUrl = null, this.dataInfo = t || this.dataInfo, this.iframeEle = e, this.setIframeUrl(s), a && (this.handleOtherRequest = a);
|
|
236
|
+
}
|
|
237
|
+
/** 解析URL */
|
|
238
|
+
parseUrl(t) {
|
|
239
|
+
const e = document.createElement("a");
|
|
240
|
+
e.href = t;
|
|
241
|
+
const s = e.protocol.length > 4 ? e.protocol : window.location.protocol, a = e.hostname, r = e.port || (s === "https:" ? "443" : s === "http:" ? "80" : ""), h = e.pathname.startsWith("/") ? e.pathname : `/${e.pathname}`, i = e.search, l = e.hash, d = e.origin || `${s}//${a}${r ? `:${r}` : ""}`, u = `${h}${i}${l}`;
|
|
242
|
+
return {
|
|
243
|
+
protocol: s,
|
|
244
|
+
host: a,
|
|
245
|
+
port: r,
|
|
246
|
+
pathname: h,
|
|
247
|
+
search: i,
|
|
248
|
+
hash: l,
|
|
249
|
+
origin: d,
|
|
250
|
+
fullPath: u
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/** 比较两个URL是否相同(协议、主机、端口) */
|
|
254
|
+
compareUrlBase(t, e) {
|
|
255
|
+
if (!t || !e) return !1;
|
|
256
|
+
const s = this.parseUrl(t), a = this.parseUrl(e);
|
|
257
|
+
return s.protocol === a.protocol && s.host === a.host && s.port === a.port;
|
|
258
|
+
}
|
|
259
|
+
/** 比较两个URL的路径是否相同(不包含查询参数和哈希) */
|
|
260
|
+
compareUrlPath(t, e) {
|
|
261
|
+
if (!t || !e) return !1;
|
|
262
|
+
const s = this.parseUrl(t), a = this.parseUrl(e);
|
|
263
|
+
return s.pathname === a.pathname;
|
|
264
|
+
}
|
|
265
|
+
/** 比较两个URL是否完全相同(包括查询参数和哈希) */
|
|
266
|
+
compareUrlFull(t, e) {
|
|
267
|
+
if (!t || !e) return !1;
|
|
268
|
+
const s = this.parseUrl(t), a = this.parseUrl(e);
|
|
269
|
+
return s.fullPath === a.fullPath;
|
|
222
270
|
}
|
|
223
271
|
/** 清除当前的 iframe 和 postmate 实例 */
|
|
224
272
|
clear() {
|
|
@@ -237,13 +285,17 @@ class v {
|
|
|
237
285
|
}
|
|
238
286
|
const s = new o({
|
|
239
287
|
container: e,
|
|
240
|
-
url: this.currentUrl
|
|
288
|
+
url: this.currentUrl,
|
|
289
|
+
name: "",
|
|
290
|
+
model: ""
|
|
241
291
|
});
|
|
242
|
-
this.currentIframe = e.querySelector("iframe"), this.currentIframe.addEventListener("load", () => {
|
|
243
|
-
this.loadFunction();
|
|
292
|
+
this.currentIframe = e.querySelector("iframe"), this.currentIframe.setAttribute("frameborder", "0"), this.currentIframe.setAttribute("allow", "fullscreen"), this.currentIframe.addEventListener("load", () => {
|
|
293
|
+
this.loadFunction && this.loadFunction();
|
|
244
294
|
}), s.then((a) => {
|
|
245
|
-
|
|
295
|
+
this.postmateParent = a, a.on("requestBaseData", () => {
|
|
246
296
|
this.sendData();
|
|
297
|
+
}), a.on("otherRequest", (r) => {
|
|
298
|
+
this.handleOtherRequest && this.handleOtherRequest(r);
|
|
247
299
|
}), typeof t == "function" && t();
|
|
248
300
|
}).catch((a) => {
|
|
249
301
|
console.error("Postmate 连接失败:", a);
|
|
@@ -253,13 +305,37 @@ class v {
|
|
|
253
305
|
setLoadFunction(t) {
|
|
254
306
|
this.loadFunction = t;
|
|
255
307
|
}
|
|
256
|
-
/** 设置 iframe Dom */
|
|
257
|
-
setIframeEle(t) {
|
|
258
|
-
this.iframeEle !== t && (this.iframeEle = t, this.iframeEle && this.currentUrl && this.init());
|
|
259
|
-
}
|
|
260
308
|
/** 设置 iframe url */
|
|
261
309
|
setIframeUrl(t) {
|
|
262
|
-
|
|
310
|
+
if (this.currentUrl === t) return;
|
|
311
|
+
if (!this.currentUrl) {
|
|
312
|
+
this.currentUrl = t, this.parsedCurrentUrl = this.parseUrl(t), this.iframeEle && this.init();
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const e = this.parseUrl(t);
|
|
316
|
+
if (this.postmateParent && this.compareUrlBase(this.currentUrl, t))
|
|
317
|
+
if (this.compareUrlPath(this.currentUrl, t)) {
|
|
318
|
+
if (this.compareUrlFull(this.currentUrl, t))
|
|
319
|
+
return;
|
|
320
|
+
this.currentUrl = t, this.parsedCurrentUrl = e, this.sendRouteUpdate(e);
|
|
321
|
+
return;
|
|
322
|
+
} else {
|
|
323
|
+
this.currentUrl = t, this.parsedCurrentUrl = e, this.sendRouteUpdate(e);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
this.currentUrl = t, this.parsedCurrentUrl = e, this.iframeEle && this.init();
|
|
327
|
+
}
|
|
328
|
+
/** 向子页面发送路由更新消息 */
|
|
329
|
+
sendRouteUpdate(t) {
|
|
330
|
+
this.postmateParent && this.postmateParent.call(
|
|
331
|
+
"routeUpdate",
|
|
332
|
+
JSON.stringify({
|
|
333
|
+
fullPath: t.fullPath,
|
|
334
|
+
pathname: t.pathname,
|
|
335
|
+
search: t.search,
|
|
336
|
+
hash: t.hash
|
|
337
|
+
})
|
|
338
|
+
);
|
|
263
339
|
}
|
|
264
340
|
/** 向子页面发送消息 */
|
|
265
341
|
sendData() {
|
|
@@ -271,6 +347,6 @@ class v {
|
|
|
271
347
|
}
|
|
272
348
|
}
|
|
273
349
|
export {
|
|
274
|
-
|
|
275
|
-
|
|
350
|
+
w as ChildPostmate,
|
|
351
|
+
U as ParentPostmate
|
|
276
352
|
};
|
package/lib/index.mjs.gz
ADDED
|
Binary file
|
package/lib/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(n
|
|
1
|
+
(function(c,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(c=typeof globalThis<"u"?globalThis:c||self,n(c["qlfy-postmate"]={}))})(this,function(c){"use strict";const n="application/x-postmate-v1+json";let f=0;const g={handshake:1,"handshake-reply":1,call:1,emit:1,reply:1,request:1};function m(o,t){return(typeof t!="string"||o.origin===t)&&!!o.data&&(typeof o.data!="object"||"postmate"in o.data)&&o.data.type===n&&!!g[o.data.postmate]}class P{constructor(t){this.parent=t.parent,this.frame=t.frame,this.child=t.child,this.childOrigin=t.childOrigin,this.events={},this.listener=e=>{if(!m(e,this.childOrigin))return;const{value:s={}}=e.data,{name:a,data:r}=s;e.data.postmate==="emit"&&a in this.events&&this.events[a].call(this,r)},this.parent.addEventListener("message",this.listener,!1)}get(t){return new h.Promise(e=>{const s=++f,a=r=>{r.data.uid===s&&r.data.postmate==="reply"&&(this.parent.removeEventListener("message",a,!1),e(r.data.value))};this.parent.addEventListener("message",a,!1),this.child.postMessage({postmate:"request",type:n,property:t,uid:s},this.childOrigin)})}call(t,e){this.child.postMessage({postmate:"call",type:n,property:t,data:e},this.childOrigin)}on(t,e){this.events[t]=e}destroy(){window.removeEventListener("message",this.listener,!1),this.frame.parentNode.removeChild(this.frame)}}class y{constructor(t){this.model=t.model,this.parent=t.parent,this.parentOrigin=t.parentOrigin,this.child=t.child,this.child.addEventListener("message",e=>{if(!m(e,this.parentOrigin))return;const{postmate:s,property:a,uid:r,data:l}=e.data,i=this.model[a];if(s!=="call"){const d=typeof i=="function"?i():i;h.Promise.resolve(d).then(u=>{e.source.postMessage({property:a,postmate:"reply",type:n,uid:r,value:u},e.origin)})}else a in this.model&&typeof i=="function"&&i(l)})}emit(t,e){this.parent.postMessage({postmate:"emit",type:n,value:{name:t,data:e}},this.parentOrigin)}}class h{constructor({container:t=document.body,model:e,url:s,name:a,classListArray:r=[]}){return this.parent=window,this.frame=document.createElement("iframe"),this.frame.name=a||"",this.frame.classList.add(...r),t.appendChild(this.frame),this.child=this.frame.contentWindow,this.model=e||{},this.sendHandshake(s)}sendHandshake(t){const e=(()=>{const r=document.createElement("a");r.href=t;const l=r.protocol.length>4?r.protocol:window.location.protocol,i=r.host.length?r.port==="80"||r.port==="443"?r.hostname:r.host:window.location.host;return r.origin||`${l}//${i}`})();let s=0,a;return new h.Promise((r,l)=>{const i=p=>{if(!m(p,e))return!1;p.data.postmate==="handshake-reply"?(clearInterval(a),this.parent.removeEventListener("message",i,!1),this.childOrigin=p.origin,r(new P(this))):l("Failed handshake")};this.parent.addEventListener("message",i,!1);const d=()=>{s++,this.child.postMessage({postmate:"handshake",type:n,model:this.model},e),s===5&&clearInterval(a)},u=()=>{d(),a=setInterval(d,500)};this.frame.onload=u,this.frame.attachEvent&&this.frame.attachEvent("onload",u),this.frame.src=t})}}class w{constructor(t){return this.child=window,this.model=t,this.parent=window.parent,this.sendHandshakeReply()}sendHandshakeReply(){return new h.Promise((t,e)=>{this.child.addEventListener("message",s=>{if(s.data.postmate){if(s.data.postmate!=="handshake")return e("Handshake Reply Failed");this.child.removeEventListener("message",this,!1),s.source.postMessage({postmate:"handshake-reply",type:n},s.origin),this.parentOrigin=s.origin;const a=s.data.model;a&&Object.keys(a).forEach(r=>{this.model[r]=a[r]}),t(new y(this))}},!1)})}}h.debug=!1,h.Promise=(()=>{try{return typeof window<"u"?window.Promise:Promise}catch{return Promise}})(),h.Model=w;class U{constructor(t,e,s){this.childPostmate=null,this.parentPostmate=null,this.isGetData=!1,this.getDataCllBack=null,this.router=null,this.routeUpdateCallback=null,this.router=e,this.routeUpdateCallback=s,window.top!==window.self?this.init(t):t.error({status:500,data:null,message:"未在一体化平台中运行"})}init(t){const e=this;this.childPostmate=new h.Model({baseData(s){s=JSON.parse(s),e.isGetData?e.getDataCllBack&&e.getDataCllBack({status:200,message:"success",data:s}):t.receive({status:200,message:"success",data:s}),e.isGetData=!1},routeUpdate(s){try{const a=JSON.parse(s);if(e.routeUpdateCallback){e.routeUpdateCallback(a);return}e.router?e.router.replace(a.fullPath):console.warn("未提供router实例,无法进行路由更新")}catch(a){console.error("路由更新失败:",a)}}}).then(s=>{e.parentPostmate=s,e.getData(),t.success({status:200,message:"success",data:{ChildPostmate:s}})}).catch(s=>{t.error({status:500,data:null,message:s})})}getData(t){if(!this.parentPostmate){t({status:500,message:"父页面未连接",data:null});return}t?(this.isGetData=!0,this.getDataCllBack=t):(this.isGetData=!1,this.getDataCllBack=null),this.parentPostmate.emit("requestBaseData")}setRouter(t,e){this.router=t,e&&(this.routeUpdateCallback=e)}sendOtherRequest(t){this.parentPostmate&&this.parentPostmate.emit("otherRequest",t)}}class E{constructor(t,e,s="",a){this.postmateParent=null,this.dataInfo={loginInfo:{},token:"",isHideHeader:!0},this.iframeEle=null,this.currentUrl="",this.currentIframe=null,this.loadFunction=null,this.handleOtherRequest=null,this.parsedCurrentUrl=null,this.dataInfo=t||this.dataInfo,this.iframeEle=e,this.setIframeUrl(s),a&&(this.handleOtherRequest=a)}parseUrl(t){const e=document.createElement("a");e.href=t;const s=e.protocol.length>4?e.protocol:window.location.protocol,a=e.hostname,r=e.port||(s==="https:"?"443":s==="http:"?"80":""),l=e.pathname.startsWith("/")?e.pathname:`/${e.pathname}`,i=e.search,d=e.hash,u=e.origin||`${s}//${a}${r?`:${r}`:""}`,p=`${l}${i}${d}`;return{protocol:s,host:a,port:r,pathname:l,search:i,hash:d,origin:u,fullPath:p}}compareUrlBase(t,e){if(!t||!e)return!1;const s=this.parseUrl(t),a=this.parseUrl(e);return s.protocol===a.protocol&&s.host===a.host&&s.port===a.port}compareUrlPath(t,e){if(!t||!e)return!1;const s=this.parseUrl(t),a=this.parseUrl(e);return s.pathname===a.pathname}compareUrlFull(t,e){if(!t||!e)return!1;const s=this.parseUrl(t),a=this.parseUrl(e);return s.fullPath===a.fullPath}clear(){this.postmateParent&&(this.postmateParent.destroy(),this.postmateParent=null),this.currentIframe&&this.currentIframe.parentNode&&this.currentIframe.parentNode.removeChild(this.currentIframe),this.currentIframe=null}async init(t=null){if(this.clear(),!this.iframeEle||!this.currentUrl){console.warn("iframeEle 和 currentUrl 是必需的");return}const e=typeof this.iframeEle=="function"?this.iframeEle():this.iframeEle;if(!e){console.warn("无法获取 iframe 容器");return}const s=new h({container:e,url:this.currentUrl,name:"",model:""});this.currentIframe=e.querySelector("iframe"),this.currentIframe.setAttribute("frameborder","0"),this.currentIframe.setAttribute("allow","fullscreen"),this.currentIframe.addEventListener("load",()=>{this.loadFunction&&this.loadFunction()}),s.then(a=>{this.postmateParent=a,a.on("requestBaseData",()=>{this.sendData()}),a.on("otherRequest",r=>{this.handleOtherRequest&&this.handleOtherRequest(r)}),typeof t=="function"&&t()}).catch(a=>{console.error("Postmate 连接失败:",a)})}setLoadFunction(t){this.loadFunction=t}setIframeUrl(t){if(this.currentUrl===t)return;if(!this.currentUrl){this.currentUrl=t,this.parsedCurrentUrl=this.parseUrl(t),this.iframeEle&&this.init();return}const e=this.parseUrl(t);if(this.postmateParent&&this.compareUrlBase(this.currentUrl,t))if(this.compareUrlPath(this.currentUrl,t)){if(this.compareUrlFull(this.currentUrl,t))return;this.currentUrl=t,this.parsedCurrentUrl=e,this.sendRouteUpdate(e);return}else{this.currentUrl=t,this.parsedCurrentUrl=e,this.sendRouteUpdate(e);return}this.currentUrl=t,this.parsedCurrentUrl=e,this.iframeEle&&this.init()}sendRouteUpdate(t){this.postmateParent&&this.postmateParent.call("routeUpdate",JSON.stringify({fullPath:t.fullPath,pathname:t.pathname,search:t.search,hash:t.hash}))}sendData(){this.postmateParent&&this.postmateParent.call("baseData",JSON.stringify(this.dataInfo))}destroy(){this.clear()}}c.ChildPostmate=U,c.ParentPostmate=E,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -3,13 +3,32 @@ interface EventObj {
|
|
|
3
3
|
success: (success: any) => void;
|
|
4
4
|
receive: (receive: any) => void;
|
|
5
5
|
}
|
|
6
|
+
interface RouteUpdateInfo {
|
|
7
|
+
fullPath: string;
|
|
8
|
+
pathname: string;
|
|
9
|
+
search: string;
|
|
10
|
+
hash: string;
|
|
11
|
+
}
|
|
6
12
|
export default class ChildPostmate {
|
|
7
13
|
childPostmate: any;
|
|
8
14
|
parentPostmate: any;
|
|
9
15
|
isGetData: boolean;
|
|
10
16
|
getDataCllBack: Function | null;
|
|
11
|
-
|
|
17
|
+
router: any;
|
|
18
|
+
routeUpdateCallback: ((routeInfo: RouteUpdateInfo) => void) | null;
|
|
19
|
+
constructor(eventObj: EventObj, router?: any, routeUpdateCallback?: (routeInfo: RouteUpdateInfo) => void);
|
|
12
20
|
init(eventObj: EventObj): void;
|
|
13
21
|
getData(callback?: any): void;
|
|
22
|
+
/**
|
|
23
|
+
* 设置路由实例和路由更新回调
|
|
24
|
+
* @param router Vue Router实例
|
|
25
|
+
* @param routeUpdateCallback 自定义路由更新回调函数
|
|
26
|
+
*/
|
|
27
|
+
setRouter(router: any, routeUpdateCallback?: (routeInfo: RouteUpdateInfo) => void): void;
|
|
28
|
+
/**
|
|
29
|
+
* 向父页面发送其他请求
|
|
30
|
+
* @param params 请求参数
|
|
31
|
+
*/
|
|
32
|
+
sendOtherRequest(params: any): void;
|
|
14
33
|
}
|
|
15
34
|
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
interface DataInfo {
|
|
2
|
+
loginInfo: {
|
|
3
|
+
[x: string]: any;
|
|
4
|
+
};
|
|
5
|
+
token: string;
|
|
6
|
+
isHideHeader: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface ParsedUrl {
|
|
9
|
+
protocol: string;
|
|
10
|
+
host: string;
|
|
11
|
+
port: string;
|
|
12
|
+
pathname: string;
|
|
13
|
+
search: string;
|
|
14
|
+
hash: string;
|
|
15
|
+
origin: string;
|
|
16
|
+
fullPath: string;
|
|
17
|
+
}
|
|
18
|
+
export default class ParentPostmate {
|
|
19
|
+
/** 连接到的子 postmate 实例 */
|
|
20
|
+
postmateParent: any;
|
|
21
|
+
/** 通讯数据 */
|
|
22
|
+
dataInfo: DataInfo;
|
|
23
|
+
/** iframe Dom 容器 */
|
|
24
|
+
iframeEle: any;
|
|
25
|
+
/** 当前 iframe url */
|
|
26
|
+
currentUrl: string;
|
|
27
|
+
/** 存储当前的 iframe 元素 */
|
|
28
|
+
currentIframe: any;
|
|
29
|
+
/** iframe 加载完成执行函数 */
|
|
30
|
+
loadFunction: (() => void) | null;
|
|
31
|
+
/** 处理子类的其他请求方法 */
|
|
32
|
+
handleOtherRequest: ((params: any) => void) | null;
|
|
33
|
+
/** 当前URL解析结果 */
|
|
34
|
+
parsedCurrentUrl: ParsedUrl | null;
|
|
35
|
+
constructor(dataInfo: DataInfo, iframeEle: HTMLElement | (() => HTMLElement), iframeUrl?: string, handleOtherRequest?: (params: any) => void);
|
|
36
|
+
/** 解析URL */
|
|
37
|
+
parseUrl(url: string): ParsedUrl;
|
|
38
|
+
/** 比较两个URL是否相同(协议、主机、端口) */
|
|
39
|
+
compareUrlBase(url1: string, url2: string): boolean;
|
|
40
|
+
/** 比较两个URL的路径是否相同(不包含查询参数和哈希) */
|
|
41
|
+
compareUrlPath(url1: string, url2: string): boolean;
|
|
42
|
+
/** 比较两个URL是否完全相同(包括查询参数和哈希) */
|
|
43
|
+
compareUrlFull(url1: string, url2: string): boolean;
|
|
44
|
+
/** 清除当前的 iframe 和 postmate 实例 */
|
|
45
|
+
clear(): void;
|
|
46
|
+
/** 初始化 */
|
|
47
|
+
init(callback?: any): Promise<void>;
|
|
48
|
+
/** 设置load执行事件 */
|
|
49
|
+
setLoadFunction(loadFunction: any): void;
|
|
50
|
+
/** 设置 iframe url */
|
|
51
|
+
setIframeUrl(iframeUrl: string): void;
|
|
52
|
+
/** 向子页面发送路由更新消息 */
|
|
53
|
+
sendRouteUpdate(parsedUrl: ParsedUrl): void;
|
|
54
|
+
/** 向子页面发送消息 */
|
|
55
|
+
sendData(): void;
|
|
56
|
+
/** 销毁实例 */
|
|
57
|
+
destroy(): void;
|
|
58
|
+
}
|
|
59
|
+
export {};
|