h5长按 touch事件
多个域名如何配置axios
1. ES6 Part
const
const 声明的对象改变其属性值,是可以的,因为内存地址没变。
如果要使其对象的属性不能改变,使用 Object.defineProperty 设置不可写,也可使用Object.freeze()进行冻结。
如果冻结嵌套对象可以自定义递归冻结函数。
function myFreeze(obj) {
Object.freeze(obj)
Object.keys(obj).forEach((key) => {
if (typeof obj[key] === 'object' && typeof obj[key] != null) {
myFreeze(obj[key])
}
})
}
解构
使用场景
- 函数传参
function sum([a,b,c]){
return a+b+c
}
a([1,2,3])
- 函数返回值
function sum(){
return {
a:1,
b:2
}
}
let {a,b}=sum()
- JSON
- Ajax请求
axios.get().then(({data})=>{
console.log(data)
})
//等价于
axios.get().then((res)=>{
console.log(res.data)
})
class
class实际上是函数,一个语法糖
class People { }
console.log(typeof People)//function
2. Native JS Part
this
- 默认绑定
浏览器环境指向Window,node环境指向globle
let obj1 = {
print() {
setTimeout(function () {
//this === window
console.log(this)
}, 250)
}
}
let obj2 = {
print() {
setTimeout(() => {
//this 指向print
console.log(this)
}, 250)
}
}
- 隐式绑定
如果函数调用时,前面存在调用它的对象,那么this就会隐式绑定到这个对象上(如:obj.fn() )
如果函数调用前存在多个对象,this指向距离调用自己最近的对象(但不要与原型链概念混淆)
在特定情况下会存在隐式绑定丢失的问题,最常见的就是作为参数传递以及变量赋值。
// 函数参数
let name = 'window';
let obj = {
name: 'obj',
fn: function () {
console.log(this.name);
}
};
function fn1(param) {
param();
};
fn1(obj.fn);//window
闭包
自由变量的查找是在函数定义的地方向上级作用域查找,不是在执行的地方。
- 函数作为返回值
function print() {
let a = 11
return function () {
console.log(a)
}
}
let a = 22
let fn = print()
fn()//11
- 函数作为参数
function print(fn) {
let a = 2
fn()
}
let a = 1
function fn() {
console.log(a)
}
print(fn) //1
-
闭包隐藏数据,只提供API
function createCache() {
const data = {}
return {
set: function (key, val) {
data[key] = val
},
get: function (key) {
return data[key]
}
}
}
let c = createCache()
c.set('a', 1)
console.log(c.get('a'))
typeof 运算符
- 能判断值类型
let a;//undefined
const str = 'abc'//string
const n = 100 //number
const b = true //boolean
const s = Symbol('s') //symbol
- 引用类型。能判断函数,能识别引用类型(但不能再继续识别)
typeof null //object
typeof {} //object
typeof [] //object
typeof function(){} //function
typeof Array //function
深拷贝
function deepClone(obj = {}) {
if (typeof obj !== 'object' || obj == null) {
return obj;
}
let result;
obj instanceof Array ? result = [] : result = {}
for (const key in obj) {
// 保证key不是原型上的属性
// hasOwnProperty不会遍历原型上的属性
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
return result;
}
== 运算符
obj.a == null
//相当于
obj.a === null || obj.a === undefined
除了 == null 之外,其余用 === 进行比较判断
// 以下是falsely变量,除此之外都是truely变量
!!0 === false
!!NaN === false
!!'' === false
!!null === false
!!undefined === false
!!false === false
Array.prototype.filter()
filter()函数大部分需要return,同时注意箭头函数简写
// 功能正常
arrList = arrList.filter((item) => item.id !== id)
arrList = arrList.filter((item) => { return item.id !== id })
//不加return功能会错误
arrList = arrList.filter((item) => {item.id !== id })
arrList = arrList.filter(function (item) {item.id !== id })
Map()
// 为数组对象每一个加一个属性
// map返回一个新数组,不会更改原数组
let newArr=this.arr.map((item)=>{
return {
...item,newAttri:newValue
}
})
Cookie
function getCookie(key){
var arr1=document.cookie.split("; ");
//由于cookie是通过一个分号+空格的形式串联起来的,所以这里需要先按分号空格截断,变成
//[name=Jack,pwd=123456,age=22]数组类型;
for(var i=0;i<arr1.length;i++){
var arr2=arr1[i].split("=");//通过=截断,把name=Jack截断成[name,Jack]数组;
if(arr2[0]==key){
return decodeURI(arr2[1]);
}
}
}
onbeforeunload
关闭页面、刷新页面均会执行
// 判断是刷新网页还是关闭网页
let beginTime = 0;//开始时间
let differTime = 0;//时间差
console.log('我来了')
window.addEventListener('unload', () => {
differTime = new Date().getTime() - beginTime;
if(differTime <= 5){
console.log('进来了1')
storage.remove(LOGIN_CODE);
}else{
console.log('进来了2')
}
});
window.addEventListener('beforeunload', () => {
console.log('进来了3')
beginTime = new Date().getTime();
});
扁平化数组转换为树形结构
function toTree(data) {
let _data = JSON.parse(JSON.stringify(data));
return _data.filter((p, pi) => {
const _arr = _data.filter(c => p.id === c.pid);
_arr.length && (p.children = _arr);
return p.pid === 0;
});
}
事件委托
例子:ul下有多个li,每个li点击事件,同时li可以新增,如何设计点击事件函数
<ul @click="show">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
show(e){
console.log(e.target)
},
</script>
3. CSS Part
- word-break (div中英文无法自动换行)
word-break:break-all
- 神秘的line-height
- 选择器
相邻兄弟选择器 (+
)
兄弟选择符 (~),位置无须紧邻,只须同层级
-
fixed定位在底部问题
// 如果全局样式有最大宽750px 那可能只写bottom:0 width: 100% 时,会在屏幕大于750px时,
// fixed_tabbar宽度最大只有750px
// 所以最好写上left 两个位置的定位才准确
.fixed_tabbar{
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
overflow属性
- overflow:auto; 内容会被修剪,超出设置的宽高后会出现滚动条。
- overflow:scroll; 内容会被修剪,不管内容是否超出,都会出现滚动条的位置
- overflow:visible; 这个是默认值,内容不会被修剪,会出现在元素框外面。
- overflow:hidden; 内容被修剪,多余的内容被隐藏
- overflow:inherit; 从父元素那里继承overflow的值。
美化ant UI sidebar 滚动条
/* style='overflowY: auto' */
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar{
width: 7px;
height: 7px;
background-color: #F5F5F5;
}
/*定义滚动条轨道 内阴影+圆角*/
::-webkit-scrollbar-track {
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
border-radius: 10px;
background-color: #F5F5F5;
}
/*定义滑块 内阴影+圆角*/
::-webkit-scrollbar-thumb{
border-radius: 10px;
box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
background-color: #c8c8c8;
}
- rem单位border-radius:50%在安卓手机中画圆变形
宽高度可以使用px,要不rem出现奇数可能也会导致不圆
使用svg
使用图片
使用transform scale。先把width,height的值放大一倍,然后用transform scale(.5)缩小一倍,接着用transform-origin调整下圆的位置
#calendar_wrap .calendar_days .date_item .date .spot {
position: absolute;
bottom: 4rpx;
left: 50%;
display:inline-block;
width:16rpx;
height:16rpx;
background-color:#0d7ee1;
border-radius:50%;
transform:scale(.5) translateX(-50%);
transform-origin:0% center;
}
4. BOM
window.location.search
5. Vue
- vue cli 2跨域
将axios的baseURL注释,请求才会经过proxyTable里面的target
怎么在样式中使用组件中接收的参数?
<template>
<div class="box" :style="styleVar">
</div>
</template>
<script>
export default {
props: {
height: {
type: Number,
default: 54,
},
},
computed: {
styleVar() {
return {
'--box-height': this.height + 'px'
}
}
},
}
</script>
<style scoped>
.box {
height: var(--box-height);
}
</style>
自定义组件绑定点击事件@click 要使用native来修饰
<my-component @click.native="test"></my-component>
6. 兼容ios
-
input等输入框在iPhone上边框有阴影
input{
outline: none;
-webkit-appearance: none; /*去除系统默认的样式*/
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); /* 点击高亮的颜色*/
}
- 移动端input框 在手机页面中无法输入文字的问题
-moz-user-select: none;
-webkit-user-select: none;
-
position:fixed定位的元素会随着页面的滑动而抖动
7.数组操作
问题:数组的深拷贝
方法:JSON.parse(JSON.stringify(array))、展开运算符[...]、Array.from()、Array.prototype.concat()
问题:数组的并集、交集和差集
方法:Set
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// (a 相对于 b 的)差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
问题:数组去重
方法:Set、reduce、filter
// 方法一:Set(ES6)
function unique(arr) {
return Array.from(new Set(arr))
}
// 或者
var unique = arr => [...new Set(arr)]
var arr = [1, 2, 2, 3]
unique(arr); // [1, 2, 3]
// 方法二:reduce
function unique (arr) {
return arr.sort().reduce((acc, cur) => {
if (acc.length === 0 || acc[acc.length - 1] !== cur) {
acc.push(cur);
}
return acc
}, [])}
;
var arr = [1, 2, 2, 3]
unique(arr); // [1, 2, 3]
// 方法三:filter
function unique(arr) {
return arr.filter( (element, index, array) => {
return array.indexOf(element) === index
})
}
var arr = [1, 2, 2, 3]
unique(arr); // [1, 2, 3]
问题:数组扁平化
方法:flat、reduce、栈
- Array.prototype.flat()
-
该方法返回一个新的数组,对原数据没有影响
-
不传参数时,默认扁平化一层;传入一个整数时,这个整数代码想要扁平化的层数
-
传入
<=0
的整数将不进行扁平化,返回原数组 -
Infinity
关键字作为参数时,无论是多少层嵌套,都会转为一维数组 -
如果原数组有空位,会跳过空位
const test = ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]]
// flat不传参数时,默认扁平化一层
test.flat()
// ["a", "b", "c", "d", ["e", ["f"]], "g"]
// flat传入一个整数参数,整数即扁平化的层数
test.flat(2)
// ["a", "b", "c", "d", "e", ["f"], "g"]
// Infinity 关键字作为参数时,无论多少层嵌套,都会转为一维数组
test.flat(Infinity)
// ["a", "b", "c", "d", "e", "f", "g"]
// 传入 <=0 的整数将返回原数组,不扁平化
test.flat(0)
test.flat(-1)
// ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]]
// 如果原数组有空位,flat()方法会跳过空位。
["a", "b", "c", "d",,].flat()
// ["a", "b", "c", "d"]
- reduce
function flattenDeep(arr) {
return Array.isArray(arr)
? arr.reduce( (acc, cur) => [...acc, ...flattenDeep(cur)] , [])
: [arr]
}
// 测试
var test = ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]]
flattenDeep(test)
// ["a", "b", "c", "d", "e", "f", "g"]
- 栈
function flattenDeep(arr) {
const result = []
// 将数组元素拷贝至栈,直接赋值会改变原数组
const stack = [...arr]
// 如果栈不为空,则循环遍历
while (stack.length !== 0) {
const val = stack.pop()
if (Array.isArray(val)) {
// 如果是数组再次入栈,并且展开了一层
stack.push(...val)
} else {
// 如果不是数组,就用头插法插入到结果数组中
result.unshift(val)
}
}
return result
}
// 测试
var test = ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]]
flattenDeep(animals)
// ["a", "b", "c", "d", "e", "f", "g"]
问题:字符串去重
方法:Set
[...new Set('ababbc')].join('')
// "abc"
问题:转换为数组
方法:Array.from、展开符[...]
Array.from()可以转换伪数组对象(拥有一个 length
属性和若干索引属性的任意对象),与可迭代对象(可以获取对象中的元素,如 Map和 Set 等)
使用展开符[...]
问题:将数组某个元素移动到最后
方法:arr.push(arr.splice(i, 1)[0])
arr.push(...arr.splice(arr.findIndex(i => i === key), 1));
const moveToLast = (arr) => {
let y = 0;//定义y用于控制循环结束
for (let i = 0; y < arr.length; y++) {
if (arr[i] === 0) arr.push(arr.splice(i, 1)[0]);//循环到是0的位置就删除该元素0并且在arr末尾push进这个元素0,由于splice删除了该位置元素,所以i不用+1,下次循环仍然检查i位置的元素
else i++;//循环到不是0的位置就继续往后循环
}
return arr;//返回操作后的原数组
};
arr.push(...arr.splice(arr.findIndex(i => i === key), 1));
8.对象操作
问题:遍历对象
方法:for in、Object.keys、Object.getOwnPropertyNames(obj)
问题:合并对象
方法:Object.assign(target, orgin)
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };
const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
9.未分类 Part
上传图片
// ant UI <a-upload>直接提供了上传form格式
// 注意按需要配置name action accept headers data 属性
// 而vant UI插件不提供,可以使用new FormData(),自行添加form格式数据
let data = new FormData();
data.append("img",file.file); //图片
axios.post("/api/material/uploadMaterial", data,{
headers: {'Content-Type': 'multipart/form-data'}
}).then(res => {
console.log(res.data);
}).catch(err=>{
console.log("失败");
})
下载图片
使用URL.createObjectURL(blob)创建出一个本地url
function funcDownload (content, filename) {
// 创建隐藏的可下载链接
var eleLink = document.createElement('a');
eleLink.download = filename;
eleLink.style.display = 'none';
// 字符内容转变成blob地址
var blob = new Blob([content]);
eleLink.href = URL.createObjectURL(blob);
// 触发点击
document.body.appendChild(eleLink);
eleLink.click();
// 然后移除
document.body.removeChild(eleLink);
}
NPM
- 查看当前地址:
npm config get registry
- 设置当前地址(设置为淘宝镜像)
npm config set registry http://registry.npm.taobao.org/
- 设置当前地址(设置为默认地址)
npm config set registry https://registry.npmjs.org/
- 每次执行命令前加入–registry指定仓库路径
npm --registry https://registry.npm.taobao.org install
简单手写JQuery
class JQuery {
constructor(selector) {
let results = document.querySelectorAll(selector)
for (let i = 0; i < results.length; i++) {
this[i] = results[i]
}
this.length = results.length
this.selector = selector
}
get(index) {
return this[index]
}
each(fn) {
for (let i = 0; i < this.length; i++) {
fn(this[i])
}
}
}
// 扩展插件
JQuery.prototype.dialog = function (info) {
alert(info)
}
class MyJQuert extends JQuery {
constructor(selector) {
super(selector)
}
// 扩展方法
add() { }
}
前端基础体系