mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-08-07 21:19:45 +08:00
feat(cli): switch to postmessage (#8500)
This commit is contained in:
parent
68c86bd637
commit
b22cbceed0
@ -2,28 +2,69 @@
|
||||
* 同步父窗口和 iframe 的 vue-router 状态
|
||||
*/
|
||||
|
||||
import { iframeReady, isMobile } from '.';
|
||||
let queue = [];
|
||||
let isIframeReady = false;
|
||||
|
||||
window.syncPath = function() {
|
||||
const router = window.vueRouter;
|
||||
const isInIframe = window !== window.top;
|
||||
const currentDir = router.history.current.path;
|
||||
function iframeReady(callback) {
|
||||
if (isIframeReady) {
|
||||
callback();
|
||||
} else {
|
||||
queue.push(callback);
|
||||
}
|
||||
}
|
||||
|
||||
if (isInIframe) {
|
||||
window.top.replacePath(currentDir);
|
||||
} else if (!isMobile) {
|
||||
const iframe = document.querySelector('iframe');
|
||||
if (iframe) {
|
||||
iframeReady(iframe, () => {
|
||||
iframe.contentWindow.replacePath(currentDir);
|
||||
});
|
||||
if (window.top === window) {
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data.type === 'iframeReady') {
|
||||
isIframeReady = true;
|
||||
queue.forEach((callback) => callback());
|
||||
queue = [];
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
} else {
|
||||
window.top.postMessage({ type: 'iframeReady' }, '*');
|
||||
}
|
||||
|
||||
window.replacePath = function(path = '') {
|
||||
// should preserve hash for anchor
|
||||
if (window.vueRouter.currentRoute.path !== path) {
|
||||
window.vueRouter.replace(path).catch(() => {});
|
||||
function getCurrentDir() {
|
||||
const router = window.vueRouter;
|
||||
return router.history.current.path;
|
||||
}
|
||||
|
||||
export function syncPathToParent() {
|
||||
window.top.postMessage(
|
||||
{
|
||||
type: 'replacePath',
|
||||
value: getCurrentDir(),
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
|
||||
export function syncPathToChild() {
|
||||
const iframe = document.querySelector('iframe');
|
||||
if (iframe) {
|
||||
iframeReady(() => {
|
||||
iframe.contentWindow.postMessage(
|
||||
{
|
||||
type: 'replacePath',
|
||||
value: getCurrentDir(),
|
||||
},
|
||||
'*'
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function listenToSyncPath(router) {
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data?.type !== 'replacePath') {
|
||||
return;
|
||||
}
|
||||
|
||||
const path = event.data?.value || '';
|
||||
// should preserve hash for anchor
|
||||
if (router.currentRoute.path !== path) {
|
||||
router.replace(path).catch(() => {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,22 +1,3 @@
|
||||
function iframeReady(iframe, callback) {
|
||||
const doc = iframe.contentDocument || iframe.contentWindow.document;
|
||||
const interval = () => {
|
||||
if (iframe.contentWindow.replacePath) {
|
||||
callback();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
interval();
|
||||
}, 50);
|
||||
}
|
||||
};
|
||||
|
||||
if (doc.readyState === 'complete') {
|
||||
interval();
|
||||
} else {
|
||||
iframe.onload = interval;
|
||||
}
|
||||
}
|
||||
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
const isMobile = /ios|iphone|ipod|ipad|android/.test(ua);
|
||||
|
||||
@ -27,4 +8,4 @@ export function decamelize(str, sep = '-') {
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
export { isMobile, iframeReady };
|
||||
export { isMobile };
|
||||
|
@ -3,7 +3,7 @@ import VueRouter from 'vue-router';
|
||||
import { isMobile, decamelize } from '../common';
|
||||
import { config, documents } from 'site-desktop-shared';
|
||||
import { getLang, setDefaultLang } from '../common/locales';
|
||||
import '../common/iframe-router';
|
||||
import { listenToSyncPath, syncPathToChild } from '../common/iframe-router';
|
||||
|
||||
if (isMobile) {
|
||||
location.replace('mobile.html' + location.hash);
|
||||
@ -48,7 +48,7 @@ function getRoutes() {
|
||||
if (locales) {
|
||||
routes.push({
|
||||
path: '*',
|
||||
redirect: route => `/${getLangFromRoute(route)}/`,
|
||||
redirect: (route) => `/${getLangFromRoute(route)}/`,
|
||||
});
|
||||
} else {
|
||||
routes.push({
|
||||
@ -66,7 +66,7 @@ function getRoutes() {
|
||||
});
|
||||
}
|
||||
|
||||
names.forEach(name => {
|
||||
names.forEach((name) => {
|
||||
const { component, lang } = parseName(name);
|
||||
|
||||
if (component === 'home') {
|
||||
@ -113,7 +113,9 @@ export const router = new VueRouter({
|
||||
});
|
||||
|
||||
router.afterEach(() => {
|
||||
Vue.nextTick(() => window.syncPath());
|
||||
Vue.nextTick(syncPathToChild);
|
||||
});
|
||||
|
||||
listenToSyncPath(router);
|
||||
|
||||
window.vueRouter = router;
|
||||
|
@ -4,7 +4,7 @@ import DemoHome from './components/DemoHome';
|
||||
import { decamelize } from '../common';
|
||||
import { demos, config } from 'site-mobile-shared';
|
||||
import { getLang, setDefaultLang } from '../common/locales';
|
||||
import '../common/iframe-router';
|
||||
import { listenToSyncPath, syncPathToParent } from '../common/iframe-router';
|
||||
|
||||
const { locales, defaultLang } = config.site;
|
||||
|
||||
@ -29,10 +29,10 @@ function getRoutes() {
|
||||
if (langs.length) {
|
||||
routes.push({
|
||||
path: '*',
|
||||
redirect: route => `/${getLangFromRoute(route)}/`,
|
||||
redirect: (route) => `/${getLangFromRoute(route)}/`,
|
||||
});
|
||||
|
||||
langs.forEach(lang => {
|
||||
langs.forEach((lang) => {
|
||||
routes.push({
|
||||
path: `/${lang}`,
|
||||
component: DemoHome,
|
||||
@ -51,11 +51,11 @@ function getRoutes() {
|
||||
});
|
||||
}
|
||||
|
||||
names.forEach(name => {
|
||||
names.forEach((name) => {
|
||||
const component = decamelize(name);
|
||||
|
||||
if (langs.length) {
|
||||
langs.forEach(lang => {
|
||||
langs.forEach((lang) => {
|
||||
routes.push({
|
||||
name: `${lang}/${component}`,
|
||||
path: `/${lang}/${component}`,
|
||||
@ -91,8 +91,10 @@ export const router = new VueRouter({
|
||||
|
||||
router.afterEach(() => {
|
||||
if (!router.currentRoute.redirectedFrom) {
|
||||
Vue.nextTick(window.syncPath);
|
||||
syncPathToParent();
|
||||
}
|
||||
});
|
||||
|
||||
listenToSyncPath(router);
|
||||
|
||||
window.vueRouter = router;
|
||||
|
Loading…
x
Reference in New Issue
Block a user