背景
运营人员通常会在公众号发布一些文章,同样的文章内容也需要发布到app站内,但是如果直接使用微信链接会出现几个问题。
- 图片链接问题,图片用的是微信的,有可能会把图片给删除。
- 微信链接会携带微信app专属内容,比如二维码、关注等。
目标
研发人员在运营后台的的页面上开发一个功能,通过抓取微信链接的主要内容,将图片链接变成app站内的,删除微信app专属内容。
调研
通过调研发现,微信公众号的文章链接的主要内容全部写在一个id为js_content
div里面,微信app的专属内容则是写在其他div元素,而且它的css样式也是内联的形式存在。
也就是说:研发同学只需要拿到id为js_content的div所有元素内容,以及将里面的图片资源转换成app站内资源即可!
。
如何获取制定id的div元素内容与图片?
通过服务端的接口,我们可以获取到微信链接的html字符串内容。那么方便获取我们想要的元素。 使用DOMParser
它支持将htmlStr转换成dom元素。
通过wangEditor实现链接内容的二次更改
当我们转换完毕之后,除了需要显示链接内容,还要支持二次修改。更关键的是,研发同学可以通过wangEditor在浏览器开发者模式下直接修改代码。
页面展示优化
为了h5能够快速展示文章内容,将图片的src以data-src存储,待contenload事件后再下载图片。
实现方案
graph TD
a[ 输入url ]-.通过接口获取htmlStr.->c[ ]
c[ htmlStr ] -.使用DomParser将htmlStr转换成HTMLDom元素.-> d[ ]
d[ HTMLDom ] -.调用其方法getElementById获取id为js_conten的DivEle.-> e[ ]
e[ DivEle ] -.调用其方法querySelectorAll获取所有的图片元素imgEles.-> f[ ]
f[ 遍历imgEles ] -.1 获取data-src并上传图片.-> g[ ]
f[ 遍历imgEles ] -.2 将回传的url赋值到data-src上.-> g[ ]
f[ 遍历imgEles ] -.3 将src赋值成默认值base64方便优化.-> g[ ]
g[ imgEles ] -.将HTMLDom转换成html上传.-> h[ ]
h[ 创建outHtmlStr ] -.编写outHtmlStr,编写函数方法来懒加载图片.-> i[ ]
i[ 组合h5_content ] -.将DivEle转成str注入到outHtmlStr形成h5_content.-> j[ 上传 ]
遇到的问题
图片上传问题
转化后元素不显示
查看源码后发现微信网页给js_conntent元素设置了style='visibility: hidden'
;
字符串scrpit问题
在组合htmlStr中,vue编译层不支持写<scrpts></scripts>
,需要通过添加子节点的形式导入。
let Dom = new DOMParser().parseFromString(outHtmlStr, "text/html");
let htmlEle = Dom.getElementsByTagName("html")[0];
let scriptEle = Dom.createElement("script");
scriptEle.innerHtml = 'console.log(1)'
htmlEle.appendChild(scriptEle);
console.log(htmlEle.outerHTML);
图片回显异常问题
如果只是单单转化图片的src,在实际浏览过程中会发现图片的尺寸有的过大问题。这是因为微信h5有js代码处理了图片的显示问题,而我们并没有js代码处理。
处理方法:给组合的html添加一个函数方法,遍历所有的图片,将当前屏幕的可视宽度innerWidth与图片绑定的data-w的值进行比较,
如果innerWidth > data-w,则将图片的style设置为width:data-w,
如果innerWidth <= data-w,则将图片的style设置为width:100%,
(function () {
var imgs = document.getElementsByTagName('img')
function lazyLoad(imgs) {
var h = window.innerHeight;
var w = window.innerWidth;
var s = document.documentElement.scrollTop || document.body.scrollTop;
for (let i = 0; i < imgs.length; i++) {
// 如果图片距离顶部的距离 小于 滚动区域与可视区域之和时,加载图片
if ((h + s) > imgs[i].offsetTop) {
// 替换真实图片
if (!imgs[i].src) {
let imgW = imgs[i].getAttribute('data-w')
const style = imgW > w ? 'width:100%' : 'width:'+imgW+'px'
imgs[i].setAttribute('style',style);
imgs[i].src = imgs[i].getAttribute('data-src')
}
}
}
}
lazyLoad(imgs);
// 监听页面滚动
window.onscroll = function () {
lazyLoad(imgs)
}
})()