临近2021新年,公司想做个类似于支付宝年终报告的活动,通过在微信朋友圈分享、好友分享进行年终报告分享和拉新,整个项目中也遇到了一些问题,H5开发经验少,所以想把这次的经验总结下来.
一、移动端适配问题
前提:此次活动使用的是有赞开源的基于 vue 的 Mobile 组件库,由于此次项目已经升级到了vue3.0,所以Vant也使用了V3版本.
在现有项目中使用 Vant 时,可以通过 npm 或 yarn 进行安装
Vue 2 项目,安装 Vant 2:
npm i vant -S
Vue 3 项目,安装 Vant 3:
npm i vant@next -S
引入组件 —>采用自动按需引入组件 (推荐)
babel-plugin-import 是一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式。
安装插件
npm i babel-plugin-import -D
// 对于使用 babel7 的用户,可以在 babel.config.js 中配置
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
plugins: [['import', {
libraryName: 'vant',
libraryDirectory: 'es',
// style: true,
style: (name) = >`$ {
name
}
/style/less`,
},
'vant', ], ],
};
// 接着在main.js中直接引入 Vant 组件,插件会自动将代码转化为以上方式中的按需引入形式
import { Button } from 'vant’;
const app = createApp(App);
// vant 挂载
const vantArr = [
NavBar, Tabbar, TabbarItem, Button, Toast, Step, Steps, Form, Picker, Field, Popup, ShareSheet, Swipe, SwipeItem, Overlay, Dialog, Loading, Checkbox];
vantArr.filter((e) => app.use(e));
app.use(Lazyload, {
lazyComponent: true,
});
app.mount('#app');
如何结合autoprefixer、postcss-pxtorem做移动端适配?
npm install autoprefixer postcss-pxtorem --save-dev
// postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem
// autoprefixer --浏览器前缀处理
配置:vue.config.js文件
const autoprefixer = require('autoprefixer')
const pxtorem = require('postcss-pxtorem')
module.exports = {
css: {
loaderOptions: {
postcss: {
plugins: [
autoprefixer(),
pxtorem({
// 设计稿 375->37.5
// 设计稿:750->75,Vant 是基于 375
rootValue: 75,
propList: ['\*'],
// 该项仅在使用 Circle 组件时需要
// 原因参见 https://github.com/youzan/vant/issues/1948
selectorBlackList: ['van-‘] // 排除vant框架相关组件
})
]
}
}
}
}
经过以上配置,小屏手机下字体依然过大,导致字体和图片有重叠或遮挡,如何处理?
新建rem.js,在main.js中引入
((doc, win) => {
// 用原生方法获取用户设置的浏览器的字体大小(兼容ie)
let userWebsetFont;
if (doc.documentElement.currentStyle) {
userWebsetFont = doc.documentElement.currentStyle.fontSize;
} else {
userWebsetFont = getComputedStyle(doc.documentElement, false).fontSize;
}
// 取整后与默认16px的比例系数
const xs = parseFloat(userWebsetFont) / 16;
// 设置rem的js设置的字体大小
let viewJssetFont; let resultFont;
const docEl = doc.documentElement;
const resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
const { clientWidth, clientHeight } = docEl;
const recalc = () => {
if (!clientWidth) return;
if (!doc.addEventListener) return;
if (clientWidth >= 750) {
docEl.style.fontSize = '75px';
} else if (clientHeight <= 480) {
docEl.style.fontSize = '28px';
} else if (clientHeight < 625) {
docEl.style.fontSize = '34px';
} else {
// 设置rem的js设置的字体大小
viewJssetFont = 75 \* (clientWidth / 750);
// 最终的字体大小为rem字体/系数
resultFont = viewJssetFont / xs;
// 设置根字体大小
docEl.style.fontSize = `${resultFont}px`;
}
};
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
import './utils/rem';
这里有网友总结的比较全的适配案:https://www.cnblogs.com/axl23...
二、接口报错netWork Error
解决方式:下载Charles抓包工具,连接手机进行请求抓包,如上图,最终找到原因是因为http和https混用导致的跨域问题,app端webview使用的协议与H5不一致,用老版本的app测试依然出现这个报错也是因为老版本的协议不一致,最终用户只能升级最新版才能避免这个问题,或者服务器需要做配置.
三、H5唤起app方法
// 去生成我的报告
const onCreateMyReport = () => {
// 判断是不是微信浏览器
const ua = navigator.userAgent;
const isWeixin = ua.indexOf('MicroMessenger') !== -1;
const isAndroid = ua\.indexOf\('Android'\) \> \-1 \|\| ua\.indexOf\('Adr'\) \> \-1; // android终端
const isiOS = !!ua.match(/(i[^;]+;( U;)? CPU.+Mac OS X/); // ios终端
if (isWeixin && isAndroid) {
// 安卓端微信,跳转到空白页面唤起app
window.location.href = 'https://www.51trust.com/mobile/html/ywxAwake.html';
} else {
// iOS终 端直接页面跳转,ios的schema链接和下载链接是一致的
window.location.href = 'https://www.51trust.com/download/';
}
};
在am项目新建一个awakenApp.html,部署后是https://www.51trust.com/mobil...
// 唤醒app
function loadURL() {
const androidrl = 'yiwangxin://51trust/main';
const downLoadUrl = 'https://www.51trust.com/download/';
let iFrame;
const u = navigator.userAgent;
const isWeixin = u.indexOf('MicroMessenger') !== -1;
const isAndroid = u\.indexOf\('Android'\) \> \-1 \|\| u\.indexOf\('Adr'\) \> \-1; // android终端
console.log('isAndroid--', isAndroid);
if (isAndroid) {
// 安卓终端使用iframe
iFrame = document.createElement('iframe');
iFrame.setAttribute('src', androidrl);
iFrame.setAttribute('style', 'display:none;');
iFrame.setAttribute('height', '0px');
iFrame.setAttribute('width', '0px');
iFrame.setAttribute('frameborder', '0');
document.body.appendChild(iFrame);
// 发起请求后这个 iFrame 就没用了,所以把它从 dom 上移除掉
setTimeout(() => {
iFrame.parentNode.removeChild(iFrame);
iFrame = null;
}, 100);
if(!isWeixin){
window.location = downLoadUrl;
}
} else {
window.location = downLoadUrl;
}
}
四、canvas生成图片,使用html2canvas遇到的坑
html2canvas ——> HTML代码转换成Canvas,进而生成可保存分享的图片
npm install --save html2canvas
在使用的页面引入
import html2canvas from 'html2canvas’
<div :ref="setImageDown" id="imageDown" class="shareImg-box”>XXXX</div>
const setCanvas = () => new Promise((resolve) => {
const canvasDom = imageDown.value;
html2canvas(canvasDom, {
backgroundColor: 'transparent',
width: canvasDom.offsetWidth, // 设置canvas尺寸与所截图尺寸相同,防止白边
height: canvasDom.offsetHeight, // 防止白边
useCORS: true,
logging: true,
}).then((canvas) => {
const url = canvas.toDataURL('image/png', 2.0);
resolve(url);
}).catch((err) => { console.log(err); });
});
出现的问题:
1、html2canvas在IOS端生成图片不显示?
找到的原因: html2canvas插件在^1.0.0-rc.4版本以上有兼容问题,使用^1.0.0-rc.4版本正常
也有可能是因为图片素材出现了跨域,如果是因为素材跨域,可以通过配置
2、生成的图片模糊?
导出的图片看起来没有原图那么清晰,这其实是因为使用了背景图片的原因。解决方法也很简单,就是直接使用<img>标签就好了,可以通过定位的方式进行样式处理.
3、PNG图片不透明问题?
如果使用PNG图片作为背景图,最后生成的图片却并不透明,可能会出现白边或白色角,这是因为生成canvas背景颜色默认为白色的缘故.解决方案就是增加一个背景颜色配置:
backgroundColor: "transparent"
五、当input输入内容超过input可视框,再次聚焦时,如何把光标定位自动定位到文本最后?
<input id="feedBack-input" class="feedBack-input" v-model="feedbackval" placeholder="请输入" @click="End">
const End = () => { // input获取光标显示在最后
nextTick(() => {
const { length } = state.feedbackval;
const elInput = document.getElementById('feedBack-input');
elInput.focus();
elInput.selectionStart = length;
elInput.selectionEnd = length;
});
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。