Skip to main content

实现页面实时预览

前言

业务方会有一边编辑平台数据,一边实时预览页面效果的需求。此时,需要业务页面配合做一些代码修改,接收平台传输的消息并作出相关处理。 目前仅在详情页(/p/detail)支持该功能。

1. 添加手机模拟器

step1. 修改配置表 - 自定义操作 - 添加“手机模拟器” - 链接处填写预览的页面地址(支持{}插值)

自定义操作

2. 预览页面为前端渲染页面

当在详情页修改数据时,右侧会以iframe的形式展示预览页面。

此时,平台管理台会向iframe发送如下消息

// 此处为平台管理台的实现代码,仅方便用户接入理解原理
// 找到iframe元素,并向iframe的域发送消息
const iframeUrl = '手机模拟器填写的url地址'
const el = this.$el.querySelector("._previewFrame iframe");
if (el.contentWindow) {
el.contentWindow.postMessage(data, 'iframeUrl地址的origin');
}

其中,data为以下格式:

{
type: "live-preview",
// payload 放的是这条配置数据的值
payload: {
// ...
},

meta: {
appid: 'xxxx', // 平台表项目ID
schemaid: 'xxx', // 平台表ID
dataid: 'xxx' // 编辑数据的主键ID
},
}

接着,业务在预览页面中接收消息

if(window === top) return;

window.addEventListener("message", function (event) {
// 严谨来说,此处需要对 event.origin 进行校验
// event.data 就是 上面的 data 数据,业务可以接收后自行操作页面
// event.data.type => 'live-preview'
// event.data.payload => 平台数据
// event.data.meta => 平台表信息
}, false);

3. 预览页面为SSR页面

原理:直出页面需要支持 get 和 post 都能输出正确的html。平台表数据变更时,会重新发起POST请求iframe,POST的body仍然保持上面提到的data格式。

自定义操作 - 手机模拟器,需要设置为POST请求。

直出模式

因为刷新了iframe,所以可能有保留滚动条高度等需求。业务可以向平台管理台发送需要存储在内存中的变量(比如testParam),每次请求iframe时,会在url中以_变量名(比如_testParam)带上。

业务代码demo

if (window !== top) {
let timer = null;
$(window).scroll((event) => {
clearTimeout(timer);
timer = setTimeout(() => {
// 每次滚动,让平台管理台记录某个变量
// scrollTop之类的变量名自行定义则可
parent.postMessage({
type: 'live-preview',
payload: {
scrollTop: document.documentElement.scrollTop || document.body.srcollTop || 0,
},
}, '*');
}, 100);
});

// 下次进页面,可以从url上找到 _变量名,进行对应操作
if (~location.search.indexOf('_scrollTop')) {
const kvs = (location.search || '?').slice(0).split('&');
const query = {};
kvs.forEach((kv) => {
const arr = kv.split('=');
if (arr.length === 2) {
query[arr[0]] = arr[1];
}
});
window.scrollTo(0, query._scrollTop ? +query._scrollTop : 0);
}
}