一次前端活动页面制作的总结(杂谈)

记录总结供以后查询使用。
作者:cuifancastle
文章链接:https://blog.csdn.net/cuifancastle/article/details/107731155

img图裂如何处理

这里介绍两种方法:
方法一 text-indent & opacity

img {
   border: 0;
   vertical-align: bottom;
   text-indent: -10000px;
}
img[src=""],img:not([src]){
   opacity:0;
}

方法二 使用背景图,不会出现图裂, background: url();

图片懒加载

浏览器原生支持

<img src="a.png" loading="lazy">

兼容旧浏览器思路:
监听scroll事件,获取图片距离顶部高度(offsetTop 或 getBoundingClientRect),即将进入时视窗时,进行加载,设置图片真实src。

一种“单页应用”首屏优化方案尝试

  • 首屏用到的图,写在css之前,与css并行加载
<head>
	<script>new Image().src="a.md5.png";</script>
	<link href=js.md5.js rel=preload as=script>
	<link href=css.md5.css rel=stylesheet>
</head>
  • dom渲染首屏,vue加载后渲染
<body>
	<div id="app">
		<p>浏览器加载完css后,渲染body,在加载js之前,可以看到些静态资源。</p>
		<p>js加载完后,会重新渲染这部分。</p>
	</div>
</body>

在做这点之前,想过静态布局,放在最底层,动态渲染放在上层,可能比较麻烦。如:

<body>
	<div id="static">静态布局,作为背景层。 z-index=-1</div>
	<div id="app"></div>
</body>

如何实现 跑马灯(轮播文字,控制滚动动画时间和间隔时间)

DOM:

<div :class="{'animate-up': animateUp}">
	<p  v-for="(item, index) in list" :key="index">{{item}}</p>
</div>
.animate-up {
   	/*动画间隔*/
     transition: all 0.5s ease-in-out; 
      /* 配合list 首个移动到末尾实现循环*/
     transform: translateY(-20px); 
   }
scrollAnimate() {
	this.isAnimate = true
	setTimeout(() => {
		this.list.push(this.msgList[0])
		this.list.shift()
		this.isAnimate = false
	}, 500) // 动画间隔
}
setInterval(this.scrollAnimate, 1500); // 间隔+动画总时间

如何实现回到顶部按钮首屏不显示,非首屏显示,淡入淡出动画

判断是否为首屏

backTopShowHide() {
this.isShowBackTop =document.body.getBoundingClientRect().y < -150
}

监听滚动

// throttle为节流函数
window.addEventListener('scroll', throttle(this.backTopShowHide, 300, 800));
/**
	* 节流函数
	* @param fun 要执行的函数
	* @param delay 延迟
	* @param time 在time时间内必须执行一次
	* @returns {Function}
	* @example window.addEventListener('scroll', throttle(lazyload, 500, 1000));
	*/
export function throttle(fun, delay, time) {
	let timeout,
		startTime = new Date();
	return function () {
		let context = this,
			args = arguments,
			curTime = new Date();
		clearTimeout(timeout);
		// 如果达到了规定的触发时间间隔,触发 handler
		if (curTime - startTime >= time) {
			fun.apply(context, args);
			startTime = curTime;
			// 没达到触发间隔,重新设定定时器
		} else {
			timeout = setTimeout(function () {
				fun.apply(context, args);
			}, delay);
		}
	};
}

css使用opacity和transition很方便。

p {
	transition: 0.5s;
	opacity: 1;
}

transition很好用,一般鼠标hover效果不那么突兀,变色,变位置等。

button {
	color: black;
	transition: 0.5s;
}
button:hover {
	color: #fff;
}

如何实现平滑滚动到固定位置

原生浏览器支持

window.scrollTo({
   	top: 100,
   	behavior: 'smooth'
})

滚动到哪个id的dom,有时该dom定位,位置需要微调下,封装下工具函数

/**
   * 滚动
   * @param domId
   * @param num -3 100 微调 单位px
   */
export const scrollTo = (domId, num = 0) => {
   let top = 0
   if (domId) {
   	const dom = document.getElementById(domId)
   	if (!dom) return
   	top = dom.offsetTop + num
   }
   window.scrollTo({
   	top,
   	behavior: 'smooth'
   })
}

复制功能函数

  • clipboard.js库
  • 原生方法:document.execCommand()

这种工具函数方式比较简单。

/**
* 复制字符串到剪贴板
* @param value
*/
export function clip (value) {
	const input = document.createElement('input');
	input.setAttribute('readonly', 'readonly');
	input.setAttribute('value', value);
	document.body.appendChild(input);
	input.select();
	const isOk = document.execCommand('copy');
	document.body.removeChild(input);
	return isOk
}

如何实现单行省略,多行省略号

这个太常用了,定宽,定高,溢出省略,设置title(鼠标hover上去有个tips),一套操作下来解决大多数问题

/* 单行省略号 */
.ellipsis {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

多行省略有点麻烦,

  • line-clamp,浏览器原生支持,不是规范,chrome支持。
  • css处理 ,利用:after伪类…挡在结尾的,需要处理可能挡住半个文字,或没溢出却显示…了的情况。
  • js处理,计算文字长度(多数字体中英文宽度不一样)

可选择性开启的禁止右键菜单

主要是contextmenu事件处理

  • 全部禁用
window.oncontextmenu=function(e){
    //取消默认的浏览器自带右键 很重要!!
    e.preventDefault();
}
  • 自定义右键菜单内容
    思路,先取消默认右键,再找到鼠标位置,插入自定义右键菜单(html),参考js设置或禁用鼠标右键菜单
  • 全部禁用,选择性开启
    这样图片,文字很奇怪的右键就被禁用掉了,需要单独开启的(比如,可复制的文字)也可单独开启了。
window.addEventListener('contextmenu', function (event) {
	if (!event.target.getAttribute('allowcontextmenu')) {
		event.preventDefault();
	}
})
<p allowcontextmenu="true">http://fuzhiwoba.com</p>
<img src="https://sdd.com/a.png"></img>

禁止选中,拖拽

user-drag:auto | element | none

 body {
     -webkit-user-drag: none;
    -webkit-user-select: none;
}

计算字节长度,汉子2字节英文1字节

/**
   * 字符串长度,字节数
   * @param str
   * @returns {number}
   */
export function strlen(str) {
   let len = 0;
   for (let i = 0; i < str.length; i++) {
   	let c = str.charCodeAt(i);
   	//单字节加1
   	if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
   		len++;
   	}
   	else {
   		len += 2;
   	}
   }
   return len;
}

jsonp实现

function generateJsonpCallback() {
	return `jsonpcallback_${Date.now()}_${Math.floor(Math.random() * 100000)}`;
}

function removeScript(id) {
	document.body.removeChild(document.getElementById(id));
}

function removeFunc(name) {
	delete global[name];
}

export function jsonp(url, options = {timeout: 10000, cb: 'cb'}, query = {}) {
	const timeout = options.timeout || 10000;
	const cbName = options.cb || 'cb'
	const querystring = Object.keys(query).reduce((total, key) => {
		return `${total }&${key}=${query[key]}`
	}, '')
	let timeId;
	return new Promise((resolve, reject) => {
		const funcName = generateJsonpCallback();
		global[funcName] = (res) => {
			resolve(res);
			timeId = setTimeout(() => {
				removeScript(funcName);
				removeFunc(funcName);
			}, timeout)
		};
		const script = document.createElement('script');
		script.src = `${url}?${cbName}=${funcName}${querystring}`;
		script.id = funcName;
		script.type = 'text/javascript';
		document.body.appendChild(script);
		script.onerror = () => {
			reject(new Error(`fetch ${url} failed`));
			removeScript(funcName);
			removeFunc(funcName);
			if (timeId) clearTimeout(timeId);
		}
	})
}

关于jsonp安全问题

后端要严格限制referer
参考jsonp介绍及其安全风险
预防CSRF(Cross Site Request Forgery, 跨站请求伪造攻击)
过滤callback函数名以及JSON数据输出,预防xss(Cross Site Scripting)

滚动条样式

PC端默认的滚动条样式很丑,可通过scrollbar相关css进行配置。
参考css scrollbar样式设置

/* 滚动条 */
.scrollbar--default::-webkit-scrollbar {
    width: 6px;
}

.scrollbar--default::-webkit-scrollbar-thumb {
    height: 0px;
    border-radius: 4px;
    background: rgba(119, 119, 119, 0.5);
}
.scrollbar--light::-webkit-scrollbar {
}
<div class="scrollbar--light">溢出的文本</div>

打点实现

export function dd(url) {
	let i = new Image()
	i.onload = i.onerror = i.onabort = () => {
		i.onload = i.onerror = i.onabort = null
		i = null
	}
	i.src = url
}
export function tt(query, BASE_URL) {
	const queryStr = Object.keys(query).reduce((total, key) => {
		return `${total}&${key}=${query[key]}`
	}, '')
	const url = `${BASE_URL}?t=${+new Date()}${queryStr}`
	dd(url)
}
  • 图片打点,使用gift打点
  • 减少请求,不影响业务,合并打点与延迟打点。
  • 防止图片请求被终止(垃圾回收),使用变量
  • 防止相同url图片请求不会发起-url随机值

在实际开发中,注意兼容性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值