1.在移动端h5中,经常会遇到下图这种情况的弹窗,弹窗背景后面的内容不允许滚动
2.只需要在背景节点身上加上@touchmove.prevent
即可(vue中),此时处于该节点及其子节点等将无法实现页面滚动
如果弹窗内的内容不滚动,只有点击时,该方式适用; 内容滚动时是不适用的
**当弹窗内需要滚动时,就需要使用下面这种方式了
3.弹出弹窗时,禁止滚动,并停留在当前位置
const disableScroll = (ref) => {
var scrollTopVal = document.documentElement.scrollTop || document.body.scrollTop;
// 禁止滑动
const selectdom = ref || 'app';
this.$refs[selectdom].style.position = "fixed";
this.$refs[selectdom].style.top = "-" + scrollTopVal + 'px';
this.$refs[selectdom].style.width = '100%';
this.$refs[selectdom].style.overflow = "hidden";
}
4.关闭弹窗时,打开页面滚动功能,恢复在停留位置
const enableScroll = (ref) => {
/** *取消滑动限制***/
const selectdom = ref || 'app';
var scrollVal = Math.abs(parseFloat(this.$refs[selectdom].style.top));
this.$refs[selectdom].style.position = "";
this.$refs[selectdom].style.overflow = "";
this.$refs[selectdom].style.top = "";
if (document.body) {
document.body.scrollTop = scrollVal;
}
if (document.documentElement) {
document.documentElement.scrollTop = scrollVal;
}
}
像iphonex、iphone12、iphone13等等,这些全面屏手机存在一个安全区,一般需要进行适配
/* 适配 iPhone XS Max / iPhone XR */
@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3),
(device-width: 414px) and (device-height: 896px),
(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3),
(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) {
#app {
padding-top: env(safe-area-inset-top); // 顶部安全区
// env(safe-area-inset-bottom) 底部安全区
}
}
1.单行
width: 100px;
white-space: nowarp;
overflow: hidden;
text-overflow: ellipsis;
2.多行
width: 200px;
/* height: 100px; 如果设置了高度,且高度超过文本显示行数,在第三行会正常出现省略号,但是三行之后的仍然正常显示*/
background-color: pink;
/* 设置高度是行高的倍数,防止文本露出一半 */
line-height: 20px;
/* 旧版弹性盒 */
display: -webkit-box;
/* 弹性盒子元素垂直排列 */
-webkit-box-orient: vertical;
/* 控制要显示的行数 */
-webkit-line-clamp: 3;
overflow: hidden;
@click.stop 或者点击事件中 事件参数e.preventDefault()阻止默认事件
在移动端社交通讯类app中,通常会出现类似通讯录的ui功能,如下图
实现方案一:
在app中经常会通过特定条件触发弹窗与动画,但是当资源较大时,无法立刻加载出,会出现图片断层或者动画卡顿,用户体验度会不太好,在显示之前预先加载后,使用时可以避免这些情况
方案一
// 存放本地图片路径的数组
const imgSrcArr = [
'./images/egg.png',
'./images/put-grey.png',
'./images/activityRuleBg.png',
'./images/myPrize.png',
..., // 可以存放本地图片路径或者网络图片地址
];
// 存放生成的img对象
const imgWrap = [];
/**
* 预加载图片资源
* @param {array} arr 存放本地图片路径的数组(预加载)
*/
preloadImg(arr: string[]) {
for(let i =0; i< arr.length ;i++) {
this.imgWrap[i] = new Image();
this.imgWrap[i].src = arr[i];
}
}
preloadImg(imgSrcArr);
<div class="box">
<ul>
<li>li>
ul>
div>
<style lang="less">
.box {
width: 100%;
height: 80px;
overflow-x: scroll;
ul {
display: flex;
height: 80px;
width: max-content; // 设置宽度为内容的最大宽度
flex-wrap: nowrap;
overflow: hidden; // 超出的隐藏 上面父级我们写了overflow-x: scroll; 会让他滚动
}
}
style>
const nowTime = () => {
let xmlHttp = new XMLHttpRequest();
if( !xmlHttp ){
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttp.open("HEAD", location.href, false);
xmlHttp.send();
const severtime = new Date(xmlHttp.getResponseHeader("Date"));
return severtime.getTime();
};
// 获取指定日期时间戳
new Date('2023-2-9 12:00:00');
具体参考:
传送门
编码 | 解码 |
---|---|
encodeURIComponent | decodeURIComponent |
encodeURI | decodeURI |
escape | unescape |
interface Type {
"a": HTMLAnchorElement;
"abbr": HTMLElement;
"address": HTMLElement;
"applet": HTMLAppletElement;
"area": HTMLAreaElement;
"article": HTMLElement;
"aside": HTMLElement;
"audio": HTMLAudioElement;
"b": HTMLElement;
"base": HTMLBaseElement;
"bdi": HTMLElement;
"bdo": HTMLElement;
"blockquote": HTMLQuoteElement;
"body": HTMLBodyElement;
"br": HTMLBRElement;
"button": HTMLButtonElement;
"canvas": HTMLCanvasElement;
"caption": HTMLTableCaptionElement;
"cite": HTMLElement;
"code": HTMLElement;
"col": HTMLTableColElement;
"colgroup": HTMLTableColElement;
"data": HTMLDataElement;
"datalist": HTMLDataListElement;
"dd": HTMLElement;
"del": HTMLModElement;
"details": HTMLDetailsElement;
"dfn": HTMLElement;
"dialog": HTMLDialogElement;
"dir": HTMLDirectoryElement;
"div": HTMLDivElement;
"dl": HTMLDListElement;
"dt": HTMLElement;
"em": HTMLElement;
"embed": HTMLEmbedElement;
"fieldset": HTMLFieldSetElement;
"figcaption": HTMLElement;
"figure": HTMLElement;
"font": HTMLFontElement;
"footer": HTMLElement;
"form": HTMLFormElement;
"frame": HTMLFrameElement;
"frameset": HTMLFrameSetElement;
"h1": HTMLHeadingElement;
"h2": HTMLHeadingElement;
"h3": HTMLHeadingElement;
"h4": HTMLHeadingElement;
"h5": HTMLHeadingElement;
"h6": HTMLHeadingElement;
"head": HTMLHeadElement;
"header": HTMLElement;
"hgroup": HTMLElement;
"hr": HTMLHRElement;
"html": HTMLHtmlElement;
"i": HTMLElement;
"iframe": HTMLIFrameElement;
"img": HTMLImageElement;
"input": HTMLInputElement;
"ins": HTMLModElement;
"kbd": HTMLElement;
"label": HTMLLabelElement;
"legend": HTMLLegendElement;
"li": HTMLLIElement;
"link": HTMLLinkElement;
"main": HTMLElement;
"map": HTMLMapElement;
"mark": HTMLElement;
"marquee": HTMLMarqueeElement;
"menu": HTMLMenuElement;
"meta": HTMLMetaElement;
"meter": HTMLMeterElement;
"nav": HTMLElement;
"noscript": HTMLElement;
"object": HTMLObjectElement;
"ol": HTMLOListElement;
"optgroup": HTMLOptGroupElement;
"option": HTMLOptionElement;
"output": HTMLOutputElement;
"p": HTMLParagraphElement;
"param": HTMLParamElement;
"picture": HTMLPictureElement;
"pre": HTMLPreElement;
"progress": HTMLProgressElement;
"q": HTMLQuoteElement;
"rp": HTMLElement;
"rt": HTMLElement;
"ruby": HTMLElement;
"s": HTMLElement;
"samp": HTMLElement;
"script": HTMLScriptElement;
"section": HTMLElement;
"select": HTMLSelectElement;
"slot": HTMLSlotElement;
"small": HTMLElement;
"source": HTMLSourceElement;
"span": HTMLSpanElement;
"strong": HTMLElement;
"style": HTMLStyleElement;
"sub": HTMLElement;
"summary": HTMLElement;
"sup": HTMLElement;
"table": HTMLTableElement;
"tbody": HTMLTableSectionElement;
"td": HTMLTableDataCellElement;
"template": HTMLTemplateElement;
"textarea": HTMLTextAreaElement;
"tfoot": HTMLTableSectionElement;
"th": HTMLTableHeaderCellElement;
"thead": HTMLTableSectionElement;
"time": HTMLTimeElement;
"title": HTMLTitleElement;
"tr": HTMLTableRowElement;
"track": HTMLTrackElement;
"u": HTMLElement;
"ul": HTMLUListElement;
"var": HTMLElement;
"video": HTMLVideoElement;
"wbr": HTMLElement;
}
日期格式:
1、(Y-M-D) => 年 - 月 - 日
2、(h-m-s) => 时 - 分 - 秒
/**
* 时间戳转日期格式
* @param {number} timestamp 时间
* @param {string} format 日期格式(Y-M-D) => 年-月-日 (h-m-s) => 时-分-秒
*/
formatDate(timestamp: number, format: string) {
let dateStr = format;
const time = new Date(timestamp * 1000);
const newArr = [];
const formatArr = ['Y', 'M', 'D', 'h', 'm', 's'];
newArr.push(`${time.getFullYear()}`.padStart(2, '0'));
newArr.push(`${(time.getMonth() + 1)}`.padStart(2, '0'));
newArr.push(`${(time.getDate())}`.padStart(2, '0'));
newArr.push(`${(time.getHours())}`.padStart(2, '0'));
newArr.push(`${(time.getMinutes())}`.padStart(2, '0'));
newArr.push(`${(time.getSeconds())}`.padStart(2, '0'));
newArr.forEach((item, index) => {
dateStr = dateStr.replace(formatArr[index], item);
});
return dateStr;
}
一般用于做一些模块曝光判断
const exposuredObserver = new IntersectionObserver((entries) => {
const [itemEntry] = entries;
if (itemEntry.isIntersecting) {
if (!this.isExposured) {
this.$emit('bannerAdExposured');
this.exposuredObserver?.disconnect();
}
}
}, {
threshold: 0,
});
this.exposuredObserver.observe(this.$refs.bannerAd);
安装:npm i html2canvas
// 获取需要截取的dom节点
const posterImg = document.getElementById('share-poster') || null;
// 节点信息
const posInfo = posterImg?.getBoundingClientRect() || null;
// 生成canvas画布
const canvas = await html2canvas(posterImg, {
allowTaint: true, // 是否允许画布污染
useCORS: true, // 是否允许图片跨域
width: posInfo.width, // 切图宽度
height: posInfo.height, // 切图高度
scale: window.devicePixelRatio, // 物理像素比
dpi: 300,
});
canvas.getContext('2d');
// base64
const addr = canvas.toDataURL('image/jpeg', 1.0);
const base64 = addr.replace(/^data:image\/jpeg;base64,/, 'data:image/jpg;base64,');
传送门
返回值:返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合, 即:是与该元素相关的CSS 边框集合
属性值:
属性 | 描述 |
---|---|
top | 元素上边距离页面上边的距离 |
left | 元素右边距离页面左边的距离 |
right | 元素右边距离页面左边的距离 |
bottom | 元素下边距离页面上边的距离 |
width | 元素宽度 |
height | 元素高度 |