- 显示省略号
- 点击显示二级下拉菜单及遮罩层
- toast弹窗
- 布局相关
- 样式重置
- 通用媒体查询
- 全屏背景、内容垂直居中、强制出现垂直滚动条、CSS固定页脚
- @font-face模板
- 基于文件类型的链接样式
- px2rem
function new2(fn) { // 将fn当成构造函数
if (!(fn instanceof Function)) throw Error('not a function!')
let obj = Object.create(fn.prototype); // 继承构造器函数原型
let args = [...arguments].slice(1); // 获取剩余参数
let res = fn.apply(obj, args); // 改变fn内的this指向,使得obj生成一些私有属性
return res instanceof Object ? res : obj; // 判断res,如果为object,则直接返回,效果和new操作符一样
}
// 具体思路是使用对象方法的调用方式,this绑定将直接绑定到对象上
// 模拟apply只是内部传参的类型不同
Function.prototype.call2 = function(obj = window) {
obj.fn = this; // this为函数。为obj添加方法,这样使用对象方法调用法this的取值就是obj了,相当于将this值绑定在了obj
let args = [...arguments].slice(1); // 剩余参数
let res = obj.fn(...args); // 保留函数返回值
delete obj.fn; // 调用后删除
return res;
}
// bind并非立即调用,会返回一个绑定this后的函数
// 如果对返回函数使用new操作符,那么this将重新绑定在new返回的对象上
Function.prototype.bind2 = function(obj) {
let thisFn = this; // 获取调用函数
let args = [...arguments].slice(1); // 剩余参数
let FnBound = function() {
// 关键一步,判断是否使用new操作符
// 函数柯里化,将先传入的参数与后传入的参数拼接
return thisFn.apply(this instanceof FnBound ? this : obj, [...args, ...arguments]);
}
// 遵从bind,将返回函数的原型绑定为调用函数的原型,使用Object.create创建的实例作为中转站
FnBound.prototype = Object.create(thisFN.prototype);
return FnBound;
}
function jsonp(url, params = {}, cb) {
// 随机的回调函数名字,避免缓存问题
let cbName = `jsonp_${(Math.random()*Math.random())}`;
window[cbName] = function(data) {
cb(data)
document.body.removeChild(scriptEle)
}
let queryStr = ''; // 查询参数
for (let key in params) {
queryStr += `${key}=${params[key]}&`;
}
url += `?${queryStr}callback=${cbName}`;
let scriptEle = document.createElement('script');
scriptEle.src = url;
document.body.appendChild(scriptEle)
}
// 有序数组中查找相应value的key
function binarySearch_1(arr, value) {
let low = 0,
high = arr.length - 1;
while (low <= high) {
let mid = parseInt((low + high) / 2);
if (value === arr[mid]) {
return mid;
} else if (value < arr[mid]) { // 折半
high = mid + 1;
} else if (value > arr[mid]) { // 折半
low = mid - 1;
} else {
return -1;
}
}
}
function binarySearch_2(arr, value, high, low = 0) {
let high = high || arr.length - 1,
mid = parseInt((low + high) / 2);
if (value === arr[mid]) {
return mid;
} else if (value < arr[mid]) { // 折半
high = mid + 1;
} else if (value > arr[mid]) { // 折半
low = mid - 1
} else {
return -1;
}
}
// checkType ('hjkhjhT','lower')'需要验证的字符串','匹配的格式'
// email:验证邮箱
// phone:验证手机号
// tel:验证座机号
// number:验证数字
// english:验证英文字母
// chinese:验证中文字
// lower:验证小写
// upper:验证大写
function checkType (str, type) {
switch (type) {
case 'email':
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
case 'phone':
return /^1[3|4|5|7|8][0-9]{9}$/.test(str);
case 'tel':
return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
case 'number':
return /^[0-9]$/.test(str);
case 'english':
return /^[a-zA-Z]+$/.test(str);
case 'chinese':
return /^[\u4E00-\u9FA5]+$/.test(str);
case 'lower':
return /^[a-z]+$/.test(str);
case 'upper':
return /^[A-Z]+$/.test(str);
default :
return true;
}
}
function IsPC() {
let userAgentInfo = navigator.userAgent;
let Agents = ["Android", "iPhone","SymbianOS", "Windows Phone","iPad", "iPod"];
let flag = true;
for (let i = 0; i < Agents.length; i++) {
if (userAgentInfo.indexOf(Agents[i]) > 0) {
flag = false;
break;
}
}
return flag;
}
// 或者
if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) { //移动端
// do something...
}
利用对象属性无法重复的特性:
function distinct(arr1, arr2) {
arr1 = [...arr1, ...arr2];
const res = [], obj = {};
for(let val of arr1) {
if(!obj[val]) {
res.push(val);
res[val] = true;
}
}
return res;
}
/* 单行文本显示... */
p {
text-overflow: ellipsis;
white-space: wrap;
overflow: hidden;
}
/* 多行文本显示... */
P {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
通过JS改变相应的class
ul {
position: absolute;
/* 相对于顶部导航栏的位移 */
top: 52px;
left: 0;
right: 0;
z-index: 1000;
background-color: #fff;
transform: translateY(calc(-100%));
}
ul.show {
transform: translateY(0);
}
.mask {
position: fixed;
/* 占满屏幕 */
top: 52px;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .6);
z-index: 999;
display: none;
}
.mask.show {
display: block;
}
可以通过JS在弹出mask后禁止触摸滑动,mask消失后恢复滑动
document.addEventListener('touchmove', (e) =>{ e.preventDefault() }, { passive: false })
包裹一个外层元素,使用JS切换显示与否
.mask_2 {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100vh;
background-color: rgba(0, 0, 0, .6);
z-index: 100000;
}
.toast {
position: fixed;
/* 居中 */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 100001;
background-color: #fff;
padding-top: 20px;
border-radius: 10px;
text-align: center;
width: 76%;
}
<div class="icon">
<a class="call">
<img src="../../../images/dh@2x.png" alt="电话icon">
</a>
<a class="call">
<img src="../../../images/dw@2x.png" alt="定位icon">
</a>
</div>
.icon {
float: right;
display: flex;
flex-flow: column nowrap;
justify-content: space-between;
align-items: center;
position: absolute;
/* 实现两个icon在两边 */
top: 0;
bottom: 0;
right: 15px;
}
.icon a:nth-child(1) {
margin-top: 15px;
}
.icon a:nth-child(2) {
margin-bottom: 15px;
}
.icon a {
display: inline-block;
border: 1px solid rgba(0, 0, 0, .3);
padding: 15px;
text-align: center;
border-radius: 50%;
position: relative;
}
.icon a img {
width: 40%;
display: inline-block;
position: absolute;
/* 居中 */
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; outline: none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;
}
html { height: 101%; -webkit-text-size-adjust: 100%; -webkit-overflow-scrolling : touch;} /* IOS Safari在横屏的时候会放大字体,第二个属性让滑动更流畅 */
body { font-size: 62.5%; line-height: 1; font-family: Arial, Tahoma, sans-serif; }
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; }
ol, ul { list-style: none; }
blockquote, q { quotes: none; }
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
strong { font-weight: bold; }
table { border-collapse: collapse; border-spacing: 0; }
img { border: 0; max-width: 100%; }
p { font-size: 1.2em; line-height: 1.0em; color: #333; }
textarea{ resize: none; }
input:focus, textarea:focus, select:focus{ outline: none; }
input::-webkit-inner-spin-button{ -webkit-appearance: none; } /* 去掉number输入框右边点击上下的小三角 */
select{ -webkit-appearance: none; } /* 去掉select的默认样式 */
/* Smartphones (portrait and landscape) ----------- */
@media only screen
and (min-device-width : 320px) and (max-device-width : 480px) {
/* Styles */
}
/* Smartphones (landscape) ----------- */
@media only screen and (min-width : 321px) {
/* Styles */
}
/* Smartphones (portrait) ----------- */
@media only screen and (max-width : 320px) {
/* Styles */
}
/* iPads (portrait and landscape) ----------- */
@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) {
/* Styles */
}
/* iPads (landscape) ----------- */
@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : landscape) {
/* Styles */
}
/* iPads (portrait) ----------- */
@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait) {
/* Styles */
}
/* Desktops and laptops ----------- */
@media only screen and (min-width : 1224px) {
/* Styles */
}
/* Large screens ----------- */
@media only screen and (min-width : 1824px) {
/* Styles */
}
/* iPhone 4 ----------- */
@media only screen and (-webkit-min-device-pixel-ratio:1.5), only screen and (min-device-pixel-ratio:1.5) {
/* Styles */
}
/* 全屏背景 */
html {
background: url('images/bg.jpg') no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
/* 内容垂直居中 */
.container {
min-height: 6.5em;
display: table-cell;
vertical-align: middle;
}
/* 强制出现垂直滚动条 */
html { height: 101% }
/* CSS固定页脚 */
#footer {
position: fixed;
left: 0px;
bottom: 0px;
height: 30px;
width: 100%;
background: #444;
}
@font-face {
font-family: 'MyWebFont';
src: url('webfont.eot'); /* IE9 Compat Modes */
src: url('webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('webfont.woff') format('woff'), /* Modern Browsers */
url('webfont.ttf') format('truetype'), /* Safari, Android, iOS */
url('webfont.svg#svgFontName') format('svg'); /* Legacy iOS */
}
body {
font-family: 'MyWebFont', Arial, sans-serif;
}
/* external links */
a[href^="http://"] {
padding-right: 13px;
background: url('external.gif') no-repeat center right;
}
/* emails */
a[href^="mailto:"] {
padding-right: 20px;
background: url('email.png') no-repeat center right;
}
/* pdfs */
a[href$=".pdf"] {
padding-right: 18px;
background: url('acrobat.png') no-repeat center right;
}
// 转换px为rem函数,不传值默认参数为30
@function px2rem($px: 30) {
@return ($px / 100) + rem;
}