接上篇博客,如今增長一個新需求:h5頁面B區顯示富文本HTML片斷。html
要求git
有一段PC端顯示的富文本HTML片斷,在手機H5頁面B區上加載顯示github
保持PC端的樣式縮放適應手機屏幕瀏覽器
若是HTML富文本有圖片服務器
提示框架
看到需求時,第一想到的是隻是顯示一段富文本內容,爲何要用iframe,直接顯示不就好了。 iframe仍是有挺多缺點的:ide
這麼多缺點爲何還要用呢(關鍵是我對iframe的使用不太熟悉,手動微笑。。。)
高人指點,由於想用iframe隔離全局樣式對富文本樣式的影響,emmmm,確實頗有道理。函數
好比你在全局樣式裏寫了一個樣式:工具
p {
font-size: 18px;
}
複製代碼
那麼富文本的內容也會受到這個全局樣式的影響,全部p裏面的字體大小都會是18px。這可不是咱們想獲得的。post
其實看到這,確定會想到,只要在全局樣式裏注意一下,不要寫一些可能會影響全局的樣式就好了,好比不寫標籤的樣式。這對於一個新項目可能較爲容易去實現,若是一個項目已經很是龐大或通過多人的修改,把不規範的樣式所有改掉好像有點不太現實。
好了,暫時沒有想到其餘好的辦法,只能選擇iframe。
由於返回的數據是一段html片斷,因此選擇iframe的srcdoc屬性(規定在<iframe>中顯示的頁面的 HTML 內容),咱們能夠在獲取到數據以後對數據進行一些處理(圖片懶加載,後面會講到),而後再字符串拼接成一段完整的HTML。
html中設置meta標籤,容許用戶縮放:
<meta name="viewport" content="width=device-width, initial-scale=1">
複製代碼
設置全局樣式
<style>
body {height: ${clientHeight}px;}
img {max-width: ${clientWidth}px;}
</style>
複製代碼
clientHeight是屏幕高度,clientWidth是屏幕寬度。
設置body的高度是由於這篇博客需求是接着上篇博客的需求來的(須要實現阻尼效果),在iframe裏,我禁用了scroll,具體思路可參考上篇博客。
設置img最大寬度是爲了實現圖片自適應,不會由於太大而超出屏幕。
直接上代碼:
修改字符串內容:
const newHtml = result.content.replace(/<img.*?\/>/g, match => {
return match.replace('src', 'src="./images/iframe/loading.gif" data-src');
});
複製代碼
懶加載函數:
const clientHeight = $(window).height();
let continueLoading = true;
const imgTags = document.getElementsByTagName('img');
const lazyload = () => {
let num = 0;
for (let img of imgTags) {
const { top } = img.getBoundingClientRect();
if (/loading.gif/.test(img.src)) {
top < clientHeight && (img.src = img.dataset.src);
} else {
num++;
}
}
num === imgTags.length && (continueLoading = false);
};
$('.main').on('touchmove', e => {
continueLoading && lazyload();
});
複製代碼
我這裏是先用正則進行替換,先顯示loading,並用data-src記住圖片地址。而後再touchmove事件中檢測並進行懶加載:
getBoundingClientRect()用來檢測圖片是否在可視區域內。
continueLoading是一個標誌,當全部圖片都加載完成後,就再也不觸發lazyload函數。
這個很是簡單了,用一個絕對定位的div去顯示圖片就能夠了,div背景色設置成白色(或者是其餘你喜歡的顏色),display: none,當點擊iframe中的圖片時,設置div裏img標籤src的值,並顯示div。再次點擊彈層的圖片,隱藏彈層。
$('.main img').on('click', e => {
$('.img-modal .img-detail').attr('src', e.target.src);
$('.img-modal').show();
});
$('.img-modal').on('click', () => {
$('.img-modal').hide();
});
複製代碼
由於在ifame所在的B區也要實現阻尼效果。其餘部分的思路和A區的阻尼效果實現思路相同,只不過當用戶到達頁面頂部並下拉到臨界值時,使用postmessage通知父頁面顯示A區,隱藏B區。
iframe中:
$('.main').on('touchend', e => {
//其餘邏輯
...
if (last_distance >= RANGE_TOP) {
//切換到上一個頁面
window.parent.postMessage('prev', '*');
...
}
});
複製代碼
父頁面中:
window.addEventListener('message', rs => {
if (rs.data === 'prev') {
$('.pageB').hide();
$('.pageA').show();
...
}
});
複製代碼
代碼實現的較爲粗糙,還有不少能夠優化提升的地方。
具體代碼見個人github,並詳細介紹了項目的使用方法。 由於懶,我沒有把此次的代碼單獨放到一個repo,就和上次的放在一塊兒,實在慚愧。。。