
http://www.shteyan.com/News3/3487.html
http://www.shteyan.com/News3/3490.html
距離上面發(fā)布的文章,在發(fā)布文章和編輯文章時(shí)添加預(yù)覽HTML的功能之后,我突然又想在列表上直接預(yù)覽文章。
第一步:
apps/admin/model/content/ContentModel.php
獲取文章列表的地方添加:
'a.content',
其他幾處也相應(yīng)添加,要不然后臺(tái)列表處無(wú)法獲取到數(shù)據(jù)。
第二步:在后臺(tái)模板文件中添加代碼,最終形成如下。
{if($value->status)}
{if(!$value->outlink)}
<input type="hidden" name="urls[[value->id]]" value="{php}echo $link{/php}">
<a href="{php}echo $link{/php}" class="layui-btn layui-btn-xs layui-btn-primary" target="_blank">查看</a>
{else}
<a href="[value->outlink]" class="layui-btn layui-btn-xs layui-btn-primary" target="_blank">查看</a>
{/if}
<!-- 添加的代碼 -->
<input type="hidden" name="content[[value->id]]" value="[value->content]">
<a href="javascript:;" class="layui-btn layui-btn-xs btn-preview" data-id="[value->id]">列表預(yù)覽</a>
<script>
layui.use(['layer', 'jquery'], function () {
var $ = layui.jquery;
var layer = layui.layer;
// 只綁定一次點(diǎn)擊事件
$(document).off('click', '.btn-preview').on('click', '.btn-preview', function () {
var id = $(this).data('id');
var $input = $("input[name='content[" + id + "]']");
if (!$input.length) {
layer.alert("未找到 ID=" + id + " 的內(nèi)容!");
return;
}
var rawHtml = $input.val();
var previewHtml = `<iframe id="previewFrame" style="width:100%;height:100%;border:none;"></iframe>`;
layer.open({
type: 1,
title: '文章內(nèi)容預(yù)覽',
area: ['90%', '90%'],
content: previewHtml,
success: function (layero, index) {
var iframe = document.getElementById('previewFrame');
var doc = iframe.contentDocument || iframe.contentWindow.document;
var fullHtml = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
此處可引入你前端的CSS樣式,以便預(yù)覽的時(shí)候顯示的是你前端的效果,而不是加載后端的樣式。
<style>
body { padding: 20px; font-family: "微軟雅黑", sans-serif; }
</style>
</head>
<body>
${rawHtml}
</body>
</html>
`;
doc.open();
doc.write(fullHtml);
doc.close();
}
});
});
});
</script>
<!-- 添加的代碼 -->
{else}
<a href="javascript:;" class="layui-btn layui-btn-xs layui-btn-disabled">查看</a>
{/if}最后我們來(lái)看效果:


使用上面的方法 呢,可能我們會(huì)擔(dān)心一個(gè)問(wèn)題,就是在一個(gè)列表中,用
<input type="hidden" name="content[[value->id]]" value="[value->content]">
去獲取的數(shù)據(jù)會(huì)不會(huì)太大了。假如列表是15篇文章,那就相當(dāng)于有15篇文章的內(nèi)容在這個(gè)頁(yè)面中。會(huì)造成這個(gè)列表數(shù)據(jù)龐大,會(huì)不會(huì)卡頓呢?
1. 頁(yè)面卡頓可能性
每篇文章內(nèi)容完整HTML都寫(xiě)在了隱藏input的value屬性里,瀏覽器會(huì)把這些內(nèi)容都加載、解析。
如果內(nèi)容很長(zhǎng),尤其有大量HTML、圖片、樣式等,頁(yè)面源碼會(huì)變得很大,初始加載時(shí)瀏覽器解析負(fù)擔(dān)會(huì)增大,加載時(shí)間變長(zhǎng)。
隱藏字段的value存放大量HTML其實(shí)并不太合適,可能導(dǎo)致:
頁(yè)面體積變大,加載慢
瀏覽器渲染緩慢
內(nèi)存占用增加
如果還有JS對(duì)這些字段做操作,性能壓力更大
2. 用戶體驗(yàn)
首屏加載時(shí)間變長(zhǎng),影響用戶體驗(yàn)。
如果用戶只點(diǎn)擊少數(shù)幾篇文章預(yù)覽,卻加載了所有文章內(nèi)容,浪費(fèi)資源。
改進(jìn)方案 方案A:按需加載內(nèi)容
頁(yè)面隱藏域只保存文章的 ID、標(biāo)題等輕量信息,不保存完整內(nèi)容。
點(diǎn)擊“預(yù)覽”按鈕時(shí),通過(guò) Ajax 請(qǐng)求后臺(tái)接口,傳文章ID,服務(wù)器返回該文章完整內(nèi)容(HTML)。
前端收到內(nèi)容后,再打開(kāi)彈窗展示。
這樣初始頁(yè)面只加載少量數(shù)據(jù),提升首屏性能,點(diǎn)擊時(shí)才加載詳細(xì)內(nèi)容。
所以我們第一步在后臺(tái)打開(kāi)API接口。

第二步修改代碼。
<!-- 添加的代碼 -->
<input type="hidden" name="content[[value->id]]" >
<a href="javascript:;" class="layui-btn layui-btn-xs btn-preview" data-id="[value->id]">預(yù)覽</a>
<script>
layui.use(['layer', 'jquery'], function () {
var $ = layui.jquery;
var layer = layui.layer;
$(document).off('click.preview').on('click.preview', '.btn-preview', function () {
var id = $(this).data('id');
if (!id) {
layer.alert("未獲取到文章ID!");
return;
}
var url = '/api.php/content/' + id;
var loading = layer.load(2);
$.ajax({
type: 'GET', // 改為GET請(qǐng)求
url: url,
dataType: 'json',
data: {
appid: "{pboot:appid}",
timestamp: "{pboot:timestamp}",
signature: "{pboot:signature}"
},
success: function (res) {
layer.close(loading);
if (!res || !res.data || !res.data.content) {
layer.alert("未獲取到文章內(nèi)容!");
return;
}
var rawHtml = res.data.content;
var iframeHtml = '<iframe id="previewFrame" style="width:100%;height:100%;border:none;"></iframe>';
layer.open({
type: 1,
title: '文章預(yù)覽',
area: ['90%', '90%'],
content: iframeHtml,
success: function () {
var iframe = document.getElementById('previewFrame');
var doc = iframe.contentDocument || iframe.contentWindow.document;
var fullHtml = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/template/peoplesj/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="/template/peoplesj/css/style.css">
<style>body { padding: 20px; font-family: "微軟雅黑", sans-serif; }</style>
</head>
<body>
${rawHtml}
</body>
</html>
`;
doc.open();
doc.write(fullHtml);
doc.close();
}
});
},
error: function (xhr, status, error) {
layer.close(loading);
console.error("請(qǐng)求失?。?quot;, error);
layer.alert("請(qǐng)求失敗:" + error);
}
});
});
});
</script>按道理,這樣我們連MODE都不用修改了。未作測(cè)試,諸君可自行測(cè)試一下。
但是有一個(gè)問(wèn)題,我在本地測(cè)試的時(shí)候,獲取不到API,只有放在服務(wù)器上才可以。
有關(guān)我們服務(wù)的更多信息,請(qǐng)聯(lián)系項(xiàng)目經(jīng)理
15899750475 楊先生