Shero.

生活百般滋味,你要笑着面对😊


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

HTML、CSS基础概念总结

发表于 2019-05-04 | 分类于 CSS

HTML

HTML语义化
  • HTML 语义化就是使用正确的标签,内容的结构化(内容语义化),选择合适的标签(代码语义化)
  • 定义麻烦,可以直接举例,如:
    • 段落就写 p 标签,标题就写 h1~h6 标签,
    • 文章就写article标签,视频就写video标签,section就写文档中的一个区域(或节),article比section更具有独立性、完整性。可通过该段内容脱离了所在的语境,是否完整、独立来判断等等。
  • 也可以阐述一下历史
    • 咱们的后台开发人员常使用table布局,美工人员常使用div+css布局,前端的优势当然就是会使用正确的标签进行页面开发啦
语义话的好处
  • 可简单解释为:便于开发者阅读和写出更优雅的代码的同时让浏览器的爬虫和机器很好地解析
  1. 在没有CSS的情况下,页面也能呈现出很好地内容结构、代码结构—–为了裸奔时好看
  2. 有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重
  3. 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以有意义的方式来渲染网页
  4. 有利于团队开发和维护
meta viewport是做什么呢?有什么用呢?
  • 先了解一下不设置meta viewport标签会导致什么后果呢
    • 移动设备上浏览器默认的宽度值为800px,980px,1024px等,总之是大于屏幕宽度的。这里的宽度所用的单位px都是指css中的px,它与实际屏幕物理像素的px不是一回事
  • meta标签的就是让当前viewport的宽度等于设备的宽度,同时不允许用户手动缩放

    • 因为每个移动设备浏览器中都有一个理想的宽度,可以用meta标签把viewport的宽度设为那个理想的宽度
      1
      <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
  • width: 设置layout viewport的宽度,为一个正整数,或字符串”width-device”

  • height: 设置layout viewport的高度,这个属性对我们并不重要,很少使用
  • initial-scale: 设置页面的初始缩放值,为一个数字,可以带小数
  • minimum-scale: 允许用户的最小缩放值,为一个数字,可以带小数
  • maximum-scale: 允许用户的最大缩放值,为一个数字,可以带小数
  • user-scalable 是否允许用户进行缩放,值为”no”或”yes”, no 代表不允许,yes代表允许

想深入了解的孩童可以看看:click here!

HTML 5 标签都有
  1. : 定义文档中的一个章节
  2. : 定义只包含导航链接的章节
  3. : 定义可以独立于内容其余部分的完整独立内容块
  4. : 定义和页面内容关联度较低的内容——如果被删除,剩下的内容仍然很合理
  5. : 定义页面或章节的头部。它经常包含 logo、页面标题和导航性的目录
  6. : 定义页面或章节的尾部。它经常包含版权信息、法律信息链接和反馈建议用的地址
  7. : 定义包含联系信息的一个章节
  8. : 定义文档中主要或重要的内容
    想了解更多:)
H5 理解
  • 简单理解:H5表示移动端页面,反正不是HTML5
  • H5更应该被理解为针对酷炫的移动端页面的一种解决方案,而这个解决方案里包含HTML5新增的标签(audio/video),canvas技术,拖拽的特性,本地存储,websocket通信,也会用到基本的盒模型,定位等一些前端基本知识,所以,H5更应该理解为一个技术合集,前端的技术广度/深度
  • H5移动端各种产品的简称吧

css

两种盒模型分别说一下
  • css盒模型的包括(margin + padding + content)
  • 标准模型(content) + IE模型(content+padding+border)
  • 两者的区别:计算宽度和高度的不同
css如何设置这两种模型
  • (标准)box-sizing: content-box
  • (IE)box-sizing: border-box
js如何设置获取盒模型的宽和高
  1. dom.style.width/height(获取的是内联)
  2. dom.currentStyle.width/height(获取页面渲染之后的,只支持IE)
  3. window.getComputedStyle(dom).width/height(firefox google)
  4. dom.getBoundingClientRect().width/height(计算元素的绝对位置,获取的是viewport左上角的位置)
    平时开发更多使用border-box,因为更好用
CSS 选择器优先级
  • 普通的权重比较,不是完全正确

    • (外部样式)External style sheet <(内部样式)Internal style sheet <(内联样式)Inline style
    1. 内联样式表的权值最高 1000
    2. ID 选择器的权值为 100
    3. Class 类选择器的权值为 10
    4. HTML 标签选择器的权值为 1
    • 详细参考
  • 越具体优先级越高

  • 优先级写在后面的覆盖写在前面的
  • !important 优先级最高,但是要少用
清除浮动
  1. 父级div定义伪类:after 强烈推荐

    1
    2
    3
    4
    5
    6
    7
    8
    .clearfix:after {
    content: '';
    display: block; /* 或者table */
    clear: both;
    }
    .clearfix{
    zoom: 1; /* IE 兼容 */
    }
  2. 在结尾处添加空div标签clear: both

  3. 父级div定义height
  4. 父级div定义overflow: hidden
  5. 父级div定义overflow: auto
flex布局左边一栏 右边两栏

margin-left: auto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 <style>
.box {
display: flex;
border: 1px solid red;
justify-content: space-between;
padding: 10px 0;
}
.box div {
width: 300px;
height: 100px;
border: 1px solid #ff9400;
}
.box div:nth-child(2) {
margin-left: auto;
}
</style>
<div class="box">
<div>1</div>
<div>2</div>
<div>3</div>
</div>

window下git bash 命令行实用技巧

发表于 2019-05-04 | 分类于 tool

命令窗口,使用快捷键快速跳转

  1. 新建一个文件目录,mkdir ~/repos
  2. 切换目录 cd ~/repos
  3. 克隆 git clone https://github.com/rupa/z.git
  4. 新建bashrc文件,如果已经存在这个文件,可忽略这步,touch ~/.bashrc
  5. 打开bashrc文件,start ~/.bashrc
  6. 在文件里写入

    1
    2
    . ~/repos/z/z.sh
    alias j='z'
  7. 重启 Git Bash

  8. 验证你的配置,使用 j XXX 就可以快速到达之前去过的目录了
  9. 使用 j 可以查看所有去过的目录,使用z也可以调整目录,调整目录名都可以不用写文件名全称,如:d/document 使用快速调整 z doc 或 j doc
    注意,~/repos/z/z.sh 不能删除,删除了就不能用了

js常使用的函数总结

发表于 2019-05-03 | 分类于 JS

js常使用的工具函数

序列号格式化输出
1
2
3
4
5
6
7
8
9
10
/**
* @param {index} 索引
* @des: 序列号格式化输出
* @return: 格式化的字符串
*/
queueSerial (index) {
let strZero = ['00', '0', ''];
let curIndex = index + 1;
return strZero[curIndex.toString().length - 1] + curIndex;
}
查找数组中是否存在某个属性值,存在就返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* @param {ist, attr, value} 数组,属性,属性值
* @des: 查找数组中是否存在某个属性值,存在就返回
* @return: Object
*/
function findOneByKey (list, attr, value) {
let obj = {};
let isExsit = false;
for (let i = 0, len = list.length; i < len; i++) {
if (list[i][attr] === value) {
for (const _attr in list[i]) {
obj[_attr] = list[i][_attr];
}
isExsit = true;
break;
}
}
return {isExsit, obj};
}
var list = [
{ name: 'aa', age: 12 },
{ name: 'bb', age: 17 },
{ name: 'aa', age: 18 }
];
jQuery如何扩展自定义方法
1
2
3
4
5
6
7
8
9
10
11
12
(jQuery.fn.myMethod=function () {
alert('myMethod');
})
// 或者:
(function ($) {
$.fn.extend({
myMethod : function () {
alert('myMethod');
}
})
})(jQuery)
$("#div").myMethod();
冒泡排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @param {arr} 排序数组
* @des: 实现冒泡排序
* @return: new arr
*/
function bubbling(arr) {
var temp = 0; // 临时变量
for(let i = 0; i < arr.length; i++) {
for(let j = 0; j < arr.length - i; j++) {
if(arr[j] > arr[j + 1]) {
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
判断一个字符串中出现次数最多的字符,统计这个次数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let str = 'asdfssaaasasasasaa';
function findStrMax(str) {
let resultObj = {};
for (let i = 0; i < str.length; i++) {
if (!resultObj[str.charAt(i)]) {
resultObj[str.charAt(i)] = 1;
} else {
resultObj[str.charAt(i)]++;
};
};
let strNum = ''; // 统计出现字符串最多的
let totalNum = 0; // 统计字符串总的出现了多少次
for(let i in resultObj) {
if (resultObj[i] > totalNum) {
totalNum = resultObj[i];
strNum = i;
};
};
console.log('出现次数最多的是:' + strNum + '出现' + totalNum +'次');
}
findStrMax(str);
去掉一个数组的重复元素
  • 计数排序变形
  • 使用 Set
  • 使用 WeakMap
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 方法1
    let arr = [2, 3, 4, 4, 5, 2, 3, 6];
    function getNewArr(arr) {
    let newArr = [];
    for (let i = 0; i < arr.length; i++) {
    if (newArr.indexOf(arr[i]) < 0) {
    newArr.push(arr[i]);
    };
    };
    console.log('新的数组' + newArr);
    }
    getNewArr(arr);
    // 方法2
    let newArr = arr.filter(function(ele, index, self) {
    return self.indexOf(ele) === index;
    });
去除字符串前后的空格
1
2
3
4
5
6
7
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
}
//或者
function trim(string) {
return string.replace(/^\s+|\s+$/g, '');
}
判断一个数字是不是整数
1
2
3
function isInt(num) {
return num % 1 === 0;
}
获取浏览器的地址参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function getUrlParams(url) {
// var _href = window.location.href;
let _href = 'http://www.runoob.com/jquery/misc-trim.html?channelid=12333&name=xiaoming&age=23';
let _tmpArr = _href.split('?');
let _paramArr = _tmpArr[1].split('&');
let resultObj = {};
let _arg = [];
for (let i = 0; i < _paramArr.length; i++) {
_arg = _paramArr[i].split('=');
resultObj[_arg[0]] = _arg[1];
};
console.log(resultObj);
return resultObj;
}
getUrlParams();
JS递归算法1+ 2+3…..100的和
1
2
3
4
5
6
7
function num(n) {
if(n === 1) {
return 1;
}
return num(n - 1) + n;
}
num(100);
找出一组数据中的奇数和偶数,偶数乘以2,并从小到大排列,奇数从大到小排列,最后合并数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var arr = [4, 3, 8, 6, 2, 9, 1];
function findOddEven(arr) {
let [oddArr, evenArr] = [[], []]; // oddArr奇数 evenArr偶数
for(let i = 0, len = arr.length; i < len; i++) {
if(arr[i] % 2 === 0) {
evenArr.push(arr[i] * 2);
} else {
oddArr.push(arr[i]);
}
}
oddArr.sort(function(a, b) {
return b - a; // 从大到小
});
evenArr.sort(function(a, b) {
return a - b; // 从小到大
});
console.log('奇数'+ oddArr);
console.log('偶数'+ evenArr);
return oddArr.concat(evenArr);
}
findOddEven(arr);
根据json对象的某一属性对其进行排序

https://www.cnblogs.com/ygtq-island/p/6512728.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
var json = {
'A': {
'id': 1,
'name': 'a'
},
'E': {
'id': 5,
'name': 'e'
},
'C': {
'id': 3,
'name': 'c'
},
'F': {
'id': 6,
'name': 'f'
},
'B': {
'id': 2,
'name': 'b'
},
'D': {
'id': 4,
'name': 'd'
}
};
var obj = {name: 'lisa', age: 8, ace: 5, nbme: 'lisi'}; // 要排序的对象
/**
* [objKeySort description] 排序的函数
* @Author pyf
* @DateTime 2019-03-19T15:44:58+0800
* @param {[Object]} obj [需要排序的json对象]
* @return {[Object]} [排序后的对象]
*/
function objKeySort(obj) {
// Object内置类的keys方法获取要排序对象的属性名,利用Array原型上的sort方法对获取的属性名进行排序,newKeyArr是一个数组
var newKeyArr = Object.keys(obj).sort();
var newObj = {}; // 存放排好序的键值对
for(let i = 0, len = newKeyArr.length; i < len; i++) {
newObj[newKeyArr[i]] = obj[newKeyArr[i]]; // 向新数组中按照排好的顺序依次增加键值对
}
return newObj; // 返回排好序的新对象
}
console.log(objKeySort(json));
js返回两个数组的差异值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 普通算法
function diff(arr1, arr2) {
var newArr = [];
var arr3 = [];
for (var i=0;i<arr1.length;i++) {
if(arr2.indexOf(arr1[i]) === -1)
arr3.push(arr1[i]);
}
var arr4 = [];
for (var j=0;j<arr2.length;j++) {
if(arr1.indexOf(arr2[j]) === -1)
arr4.push(arr2[j]);
}
newArr = arr3.concat(arr4);
return newArr;
}

// 优雅
function diff(arr1, arr2) {
console.log(arr1.concat(arr2));
return arr1.concat(arr2).filter(item => {
return !arr1.includes(item)||!arr2.includes(item)
});
}

// 方式三
function diff(arr1, arr2) {
return arr1.concat(arr2).filter(item => !arr1.includes(item)||!arr2.includes(item));
}
diff([1, 2, 3, 5], [0, 2, 3, 4, 5]);
某年某月的1号为星期几
1
2
var weekDay = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
weekDay[new Date(2019, 3, 1).getDay()];
数据的排序 123454321 23456765432
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 方法1 
//01234543210
//先展示前面的 01234
//n:开始的数字 m:结束的数字
function num1(n, m) {
for(var i = n; i < m; i++) {
//再展示后面的 543210
console.log(i);
if (i === m-1) {
num2(n, m)
}
}
}
function num2(n, m) {
for(var i = m; i >= n; i--) {
console.log(i)
}
}
num1(2, 5) //2345432
// 方法2
function num(n, m) {
console.log(n);
if (n < m) {
num(n + 1, m);
console.log(n);
}
}
num(2, 5) //2345432
首字母大写
1
2
3
4
5
6
7
8
9
/** 
* 首字母大写
* @param str 字符串
* @example heheHaha
* @return {string} HeheHaha
*/
function capitalizeFirstLetter (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
深拷贝
  • 递归
  • 判断类型
  • 检查环(也叫循环引用)
  • 需要忽略原型
    理解深浅拷贝,需了解
  1. 基本类型–名值存储在栈内存中,例如let a=1
    栈内存
  2. 引用数据类型–名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值
    堆内存
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function deepCopy(obj) {
    // 判断是否是简单数据类型,
    if (typeof obj == 'object') {
    //复杂数据类型
    var result = obj.constructor == Array ? [] : {};
    for(let i in obj) {
    result[i] = typeof obj[i] == 'object' ? deepCopy(obj[i]) : obj[i];
    }
    } else {
    //简单数据类型 直接 == 赋值
    var result = obj;
    }
    return result;
    }
将类数组转化为数组
1
2
3
4
function trigger() {
var args = Array.prototype.slice.call(arguments);
// ...
}
使用 Array的 slice 进行数组复制( 浅复制)
1
2
3
4
5
6
7
8
var items = [1, 2, 3];
// bad
var itemsCopy = [];
for (var i = 0; i < items.length; i++) {
itemsCopy[i] = items[i];
}
// good slice返回的是一个新数组,和直接赋值区别
var itemsCopy = items.slice();
使用 for-in 循环时需要避免对象从原型链上继承来的属性也被遍历出来,因此保险的做法是对 key 是否是对象自身的属性进行验证
1
2
3
4
5
6
// good
for (const key in foo) {
if (Object.prototype.hasOwnProperty.call(foo, key)) {
doSomething(key);
}
}
if(a === 1 || a === 2 || a === 3){}推荐写法
1
2
3
4
5
6
7
8
9
10
11
12
13
[1, 2, 3].indexOf() || /^(1|2|3)$/.test()
// 第一种方式
if(a === 1 || a === 2 || a === 3) {
// doThing
}
// 第二种方式,在数组判断是否存在此元素,不存在返回-1
if([1, 2, 3].indexOf(a) > -1) {
// doThing
}
// 第三种方式1,2,3之间不能有空格
if (/^(1| 2|3)$/.test(a)) {
// doThing
}
三位数字分离与合并的相互转化
1
2
3
4
5
6
7
8
9
10
11
12
function numSplit(val) {
if (val) {
return val.toString().replace(/(\d)(?=(\d{3})+($|\.))/g, '$1,');
}
}
console.log(numSplit(1003030)); // 1,003,030

// 1,333,112 ==> 1333112
function numMery (v) {
return parseFloat(v.toString().replace(/,/g, ''));
}
console.log(numMery('1,333,112'));
抽离出相同类型的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// es6
let _data = [
{typeCnt: '独家特色', content: '24小时落货装卸分拨'},
{typeCnt: '独家特色', content: '专属服务经理对接'},
{typeCnt: "独家特色", content: "千元以下理赔24H赔付"},
{typeCnt: "覆盖范围", content: "宁夏全境覆盖"},
{typeCnt: "覆盖范围", content: "网络覆盖宁夏全境、乌海、巴彦淖尔和阿拉善盟,无盲区"},
{typeCnt: "覆盖范围", content: "全省地级市自提点全覆盖"},
{typeCnt: "定时必达", content: "省内地市中转次日达"},
{typeCnt: "定时必达", content: "市配当日达"},
{typeCnt: "超低价格", content: "银川三环以内配送40元/票起"},
{typeCnt: "超低价格", content: "中转价格透明不议价"}
];
// ES6新的数据类型set
// set 集合,和数组很类似
// 特点 数据有唯一性,可以用来去除重复数据
let typeCntGroup = new Set();
let result = [];
_data.forEach(item => {
typeCntGroup.add(item.typeCnt);
});
// ES6为Array增加了from函数用来将其他对象转换成数组。
// 当然,其他对象也是有要求,也不是所有的,可以将两种对象转换成数组。
// 1.部署了Iterator接口的对象,比如:Set,Map,Array。
// 2.类数组对象,什么叫类数组对象,就是一个对象必须有length属性,没有length,转出来的就是空数组。
typeCntGroup = Array.from(typeCntGroup);
for (let i = 0; i < typeCntGroup.length; i++) {
let _obj = {
typeCnt: '',
content: []
};
_obj.typeCnt = typeCntGroup[i];
for (let j = 0; j < _data.length; j++) {
if (_data[j].typeCnt === typeCntGroup[i]) {
_obj.content.push(_data[i].content);
}
}
result.push(_obj);
}
console.log(result);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let _typeArr = []; // 枢纽展示类型
for (let i = 0; i < _data.length; i++) {
// 将枢纽类型先存储下来
if (_typeArr && _typeArr.indexOf(_data[i].typeCnt) < 0) {
_typeArr.push(_data[i].typeCnt);
}
}
let _newArr = []; // 每个枢纽类型对应的content保存
for (let i = 0; i < _typeArr.length; i++) {
let obj = {
typeCnt: '',
content: []
};
obj.typeCnt = _typeArr[i];
for (let j = 0; j < _data.length; j++) {
if (_typeArr[i] === _data[j].typeCnt) {
obj.content.push(_data[j].content);
}
}
_newArr.push(obj);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// es5的处理
let _typeArr = []; // 枢纽展示类型
for (let i = 0; i < _data.length; i++) {
// 将枢纽类型先存储下来
if (_typeArr && _typeArr.indexOf(_data[i].typeCnt) < 0) {
_typeArr.push(_data[i].typeCnt);
}
}
let _newArr = []; // 每个枢纽类型对应的content保存
for (let i = 0; i < _typeArr.length; i++) {
let obj = {
typeCnt: '',
content: []
};
obj.typeCnt = _typeArr[i];
for (let j = 0; j < _data.length; j++) {
if (_typeArr[i] === _data[j].typeCnt) {
obj.content.push(_data[j].content);
}
}
_newArr.push(obj);
}
函数防抖和函数节流
  1. 节流(一段时间执行一次之后,就不执行第二次)
    注意 认为节流函数不是立刻执行的,而是在冷却时间末尾执行的(相当于施法有吟唱时间),那样说也是对的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function throttle(fn, delay) {
    let canUse = true;
    return function() {
    if (canUse) {
    fn.apply(this, arguments);
    canUse = false;
    setTimeout(() => {
    canUse = true;
    }, delay)
    }
    }
    }
    const throttled = throttle(() => console.log('hi'));
    throttled();
    throttled();
  2. 防抖(一段时间会等,然后带着一起做了)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function debounce(fn, delay) {
    let timerId = null;
    return function() {
    const context = this;
    if (timerId) {
    window.clearTimeout(timerId);
    }
    timerId = setTimeout(() => {
    fn.apply(context, arguments);
    timerId = null;
    }, delay)
    }
    }
    const debounced = debounce( () => console.log('hi'))
    debounced()
    debounced()
手写AJAX
1
2
3
4
5
6
7
8
9
10
11
12
var request = new XMLHttpRequest();
request.open('GET', '/a/b/c?name=ff', true);
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
console.log(request.responseText);
}};
request.send();
// 简单一些可以如下
var request = new XMLHttpRequest();
request.open('GET', '/a/b/c?name=ff', true);
request.onload = () => console.log(request.responseText);
request.send();
事件委托
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 简单版本
ul.addEventListener('click', function(e) {
if (e.target.tagName.toLowerCase() === 'li') {
fn() // 执行某个函数
}
})
// bug 在于,如果用户点击的是 li 里面的 span,就没法触发 fn,这显然不对
// 优化版本 思路是点击 span 后,递归遍历 span 的祖先元素看其中有没有 ul 里面的 li
function delegate(element, eventType, selector, fn) {
element.addEventListener(eventType, e => {
let el = e.target;
while (!el.matches(selector)) {
if (element === el) {
el = null;
break;
}
el = el.parentNode;
}
el && fn.call(el, e, el);
})
return element;
}
用 mouse 事件写一个可拖曳的 div

快速看到效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var dragFlag = false;
var position = null;
drag.addEventListener('mousedown', function(e) {
dragFlag = true;
position = [e.clientX, e.clientY];
})

// mousemove 与 mouseup 不能监听在元素上 快速拖到会有问题
document.addEventListener('mousemove', function(e) {
if (dragFlag) {
return;
}
const x = e.clientX;
const y = e.clientY;
const deltaX = x - position[0];
const deltaY = y - position[1];
// parseInt('')空转为 NaN
// drag.style.left初始值为'0px'
const left = parseInt(drag.style.left || 0, 10);
const top = parseInt(drag.style.top || 0, 10);
drag.style.left = left + deltaX + 'px';
drag.style.top = top + deltaY + 'px';
position= [x, y];
})

document.addEventListener('mouseup', function() {
dragFlag = false;
})

filter方法
  • 不会对空数组进行检测,会跳过那些空元素
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let arr = [0, 3, 5];
    arr[10] = 10;
    arr.filter((val) => {
    return val === undefined;
    });
    // 初始化
    let array = [0, 3, 5, undefined, undefined, null, 123];
    array[10] = 10;
    array.filter((val) => {
    return val === undefined;
    });
join()
  • javascript 在定义数组的时候允许最后一个元素后跟一个,(分号)
    1
    2
    let str = [,,,].join(); // ,,
    let str = [,,1,].join('.').length;
普通函数与箭头函数的区别
  • this指向的问题,会捕获其所在上下文的this值,作为自己的this值
  • 箭头函数不绑定arguments,取而代之用reset参数解决

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 箭头函数
    let foo = (...args) => {
    return args[0];
    }
    console.log(foo(1));
    // 普通函数
    fun() {
    console.log(argument[0]);
    }
    console.log(fun(1, 34));
  • 箭头函数不能用作构造器,和new一起用就会抛出错误

  • 箭头函数没有原型属性
    1
    2
    var foo = () => {};
    console.log(foo.prototype) // undefined
js常见的自认为正确的问题
1
2
3
4
5
6
7
var array = [];
for(var i = 0; i <3; i++) {
array.push(() => i);
console.log(array);
}
var newArray = array.map(el => el());
console.log(newArray); // [3, 3, 3]
  • 解决问题为什么不是0,1,2
  • var声明变量,三个箭头函数体中的每个i,都指向相同的绑定,所以它们在循环结束时返回相同的值3
  • 解决方法1,把var改为let(let 声明一个具有块级作用域的变量,每个循环迭代创建一个新的绑定)
  • 解决方式2,使用闭包
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var array = [];
    for(var i = 0; i <3; i++) {
    array[i] = (function(x) {
    return function() {
    return x;
    }
    })(i);
    }
    var newArray = array.map(el => el());
    console.log(newArray); // [3, 3, 3]
找出字符串中第一次只出现一次的字母
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
String.prototype.firstAppear = function () {
let obj = {},
len = this.length;
for (let i = 0; i < len; i++) {
if (obj[this[i]]) {
obj[this[i]]++;
} else {
obj[this[i]] = 1;
}
}
for (let prop in obj) {
if (obj[prop] == 1) {
return prop;
}
}
}
let str = 'abcdahfksdb';
console.log('result', str.firstAppear());
获得滚动条的滚动距离
1
2
3
4
5
6
7
8
9
10
11
12
13
function getScrollOffset() {
if (window.pageXOffset) {
return {
x: window.pageXOffset,
y: window.pageYOffset
}
} else {
return {
x: document.body.scrollLeft + document.documentElement.scrollLeft,
y: document.body.scrollTop + document.documentElement.scrollTop
}
}
}
获得视口的尺寸
  • To Learn More…
    1
    2
    3
    4
    ```

    ##### 简短函数调用
    * 三元操作符来实现多个函数调用

// Longhand
function test1() {
console.log(‘test1’);
};
function test2() {
console.log(‘test2’);
};
var test3 = 1;
if (test3 == 1) {
test1();
} else {
test2();
}
// Shorthand
(test3 === 1? test1:test2)();

1
2
3

##### switch 简化
* 将条件保存在键值对象中,并根据条件来调用它们

// Longhand
switch (data) {
case 1:
test1();
break;
case 2:
test2();
break;
case 3:
test();
break;
// And so on…
}
// Shorthand
var data = {
1: test1,
2: test2,
3: test
};
data[something] && datasomething;

1
2

##### 延展操作符简化

//longhand
// joining arrays using concat
const data = [1, 2, 3];
const test = [4 ,5 , 6].concat(data);
//shorthand
// joining arrays
const data = [1, 2, 3];
const test = [4 ,5 , 6, …data];
console.log(test); // [ 4, 5, 6, 1, 2, 3]

1
* 延展操作符进行克隆

//longhand
// cloning arrays
const test1 = [1, 2, 3];
const test2 = test1.slice()
//shorthand
// cloning arrays
const test1 = [1, 2, 3];
const test2 = […test1];

1
2

* 如何将浮点数点左边的数每三位添加一个逗号,如 12000000.11 转化为『12,000,000.11』?

// 方法一
function format(number) {
return number && number.replace(/(?!^)(?=(\d{3})+.)/g, “,”);
}
// 方法二
function format1(number) {
return Intl.NumberFormat().format(number)
}
// 方法三
function format2(number) {
return number.toLocaleString(‘en’)
}

1
2

##### 求和,最小值和最大值

const array = [5,4,7,8,9,2];
array.reduce((a, b) => a + b); // 输出: 35
array.reduce((a, b) => a > b ? a : b); // 输出: 9
array.reduce((a, b) => a < b ? a : b); // 输出: 2

1
2
3

##### 排序字符串,数字或对象等数组
* 内置的方法sort()和reverse()来排序字符串

const stringArr = [“Joe”, “Kapil”, “Steve”, “Musk”]
stringArr.sort();
// 输出 [“Joe”, “Kapil”, “Musk”, “Steve”]

stringArr.reverse();
// 输出 [“Steve”, “Musk”, “Kapil”, “Joe”]

1
* 数字数组排序

const array = [40, 100, 1, 5, 25, 10];
array.sort((a,b) => a-b);
// 输出 [1, 5, 10, 25, 40, 100]

array.sort((a,b) => b-a);
// 输出 [100, 40, 25, 10, 5, 1]

1
* 对象数组排序

const objectArr = [
{ first_name: ‘Lazslo’, last_name: ‘Jamf’ },
{ first_name: ‘Pig’, last_name: ‘Bodine’ },
{ first_name: ‘Pirate’, last_name: ‘Prentice’ }
];
objectArr.sort((a, b) => a.last_name.localeCompare(b.last_name));
// 输出
(3) [{…}, {…}, {…}]
0: {first_name: “Pig”, last_name: “Bodine”}
1: {first_name: “Lazslo”, last_name: “Jamf”}
2: {first_name: “Pirate”, last_name: “Prentice”}
length: 3

1
2

##### 从数组中过滤到虚值 (0, undefined, null, false, "", '')

const array = [3, 0, 6, 7, ‘’, false];
array.filter(Boolean);
// 输出 [3, 6, 7]
`

BFC

发表于 2019-05-02 | 分类于 CSS

BFC

  • 详细概念 MDN
  • BFC全称为Block Formatting Context,即块级格式化上下文,就是一个独立的渲染区域
  • 可以简单理解为: BFC为某个元素的一个CSS属性,只不过这个属性不能被开发者显式的修改,拥有这个属性的元素对内部元素和外部元素会表现出一些特性,这就是BFC。

BFC特点:

  • BFC这个元素垂直方向的边距会发生重叠
  • BFC的区域不会与浮动元素的box重叠
  • BFC在页面上是一个独立的元素,内外元素不会互相影响
  • BFC计算高度的时候,浮动元素也会计算

如何创建BFC

  • float: 值不为none
  • overflow: 值为hidden或atuo给父元素
  • position:值不为static或relative
  • display:值为table(table、table-cell、table-caption等)相关的属性

BFC应用场景

  • 了解BFC主要知道它的应用场景就可以了
    1.防止垂直margin重叠:
    • 父子元素的边界重叠解决方案:在父元素上加上overflow:hidden;使其成为BFC
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
       <style>
      .parent {
      background: #E7A1C5;
      overflow: hidden;
      }
      .parent .child {
      background: #C8CDF5;
      height: 100px;
      margin-top: 10px;
      }
      </style>
      <section class="parent">
      <article class="child"></article>
      </section>
  1. 兄弟元素的边界重叠,在第二个子元素创建一个BFC上下文

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <style>
    #margin {
    background: #E7A1C5;
    overflow: hidden;
    width: 300px;
    }
    #margin p {
    background: #C8CDF5;
    margin: 20px auto 30px;
    }
    </style>
    <section id="margin">
    <p>1</p>
    <div style="overflow:hidden;">
    <p>2</p>
    </div>
    <p>3</p>
    </section>
  2. 自适应两栏布局

  • BFC不会与float元素发生重叠
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <section id="layout">
    <style>
    #layout {
    background: red;
    }
    #layout .left {
    float: left;
    width: 100px;
    height: 100px;
    background: pink;
    }
    #layout .right {
    height: 110px;
    background: #ccc;
    overflow: auto;
    }
    </style>
    <div class="left"></div>
    <div class="right"></div>
    </section>
  1. BFC清除内部浮动
  • 父元素#float的高度为0,解决方案为为父元素#float创建BFC,这样浮动子元素的高度也会参与到父元素的高度计算
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     <section id="float">
    <style>
    #float {
    overflow: auto;
    background: red;
    }
    #float .child {
    float: left;
    font-size: 30px;
    }
    </style>
    <div class="child">我是浮动元素</div>
    </section>

类与继承

发表于 2019-04-30 | 分类于 JS

如何实现继承及继承的几种方式

借助构造函数实现继承
1
2
3
4
5
6
7
8
9
function Parent() {
this.name = 'parent1';
}
Parent.prototype.say = function(){};
function Child() {
Parent.call(this);
this.type = 'child';
}
console.log(new Child); // 无参数,()可以省略
  • 原理:子类通过call方法改变函数运行上下文
  • 不足:把Parent1的this指向Child1,不能继承父类的原型上的方法
借助构造函数实现继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Parent2() {
this.name = 'parent2';
this.play = [1, 2, 3];
}
function Child2() {
this.type = 'child2';
}
Child2.prototype = new Parent2();
console.log(new Child2().__proto__);
console.log(new Child2().__proto__ === Child2.prototype); // true
console.log(new Child2().__proto__.name); // parent2
var s1 = new Child2();
var s2 = new Child2();
console.log(s1.play, s2.play);
s1.play.push(4);
console.log(s1.play, s2.play);
console.log(s1.__proto__ === s2.__proto__); // true
  • 原理:子类通过prototype属性指向父类的实例
  • 不足:修改s1,s2同时也改变,事实应该是隔离的,原型链中的原型对象是公用的
组合方式继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Parent3() {
this.name = 'parent3';
this.play = [1, 2, 3];
}
function Child3() {
Parent3.call(this);
this.type = 'child3';
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play);
console.log(s3.constructor);
  • 不足:父类构造函数执行了两次
组合方式继承优化1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Parent4() {
this.name = 'parent4';
this.play = [1, 2, 3];
}
function Child4() {
Parent4.call(this);
this.type = 'child4';
}
Child4.prototype = Parent4.prototype;
var s5 = new Child4();
var s6 = new Child4();
console.log(s5, s6);
console.log(s5 instanceof Child4, s5 instanceof Parent4);
console.log(s5.constructor);
组合方式继承优化2
1
2
3
4
5
6
7
8
9
10
11
12
13
function Parent5() {
this.name = 'parent5';
this.play = [1, 2, 3];
}
function Child5() {
Parent5.call(this);
this.type = 'child5';
}
Child5.prototype = Object.create(Parent5.prototype); // 创建中间对象__proto__)
Child5.prototype.constructor = Child5;
var s7 = new Child5();
console.log(s7 instanceof Child5, s7 instanceof Parent5);
console.log(s7.constructor);

页面布局-三栏布局实现方案

发表于 2019-04-29 | 分类于 CSS

假设高度已知,请写出三栏布局,左右栏宽度各300px,中间自适应

以下五种实现方案

1
2
3
4
5
6
7
8
9
10
11
12
13
// 公共的css样式`
<style>
html * {
padding: 0;
margin: 0;
}
.layout {
margin-top: 30px;
}
.layout article div {
min-height: 100px;
}
</style>
float实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<section class="layout float">
<style>
.layout.float .left {
float: left;
width: 300px;
background: #ff0000;
}
.layout.float .right {
float: right;
width: 300px;
background: #ff9400;
}
.layout.float .center {
background: #c40;
}
</style>
<article class="left-right-center">
<div class="left"></div>
<div class="right"></div>
<div class="center">
<h1>浮动解决方案</h1>
1.这是三栏布局中间buf部分
1.这是三栏布局中间buf部分
</div>
</article>
</section>
position实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 <section class="layout absolute">
<style>
.layout.absolute .left-center-right > div {
position: absolute;
}
.layout.absolute .left {
left: 0;
width: 300px;
background: #ff0000;
}
.layout.absolute .center{
left: 300px;
right: 300px;
background: #ff9400;
}
.layout.absolute .right {
right: 0;
width: 300px;
background: #c40;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>绝对定位解决方案</h1>
1.这是三栏布局中间buf部分
1.这是三栏布局中间buf部分
</div>
<div class="right"></div>
</article>
</section>
flex实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 <section class="layout flexbox">
<style>
.layout.flexbox {
margin-top: 140px;
}
.layout.flexbox .left-center-right {
display: flex;
}
.layout.flexbox .left {
width: 300px;
background: #ff0000;
}
.layout.flexbox .center{
flex: 1;
background: #ff9400;
}
.layout.flexbox .right {
width: 300px;
background: #c40;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>flexbox解决方案</h1>
1.这是三栏布局中间buf部分
1.这是三栏布局中间buf部分
</div>
<div class="right"></div>
</article>
</section>
table实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 <section class="layout table">
<style>
.layout.table .left-center-right {
width: 100%;
display: table;
height: 100px;
}
.layout.table .left-center-right > div {
display: table-cell;
}
.layout.table .left {
width: 300px;
background: #ff0000;
}
.layout.table .center{
background: #ff9400;
}
.layout.table .right {
width: 300px;
background: #c40;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>table表格解决方案</h1>
1.这是三栏布局中间buf部分
1.这是三栏布局中间buf部分
</div>
<div class="right"></div>
</article>
</section>
grid实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<section class="layout grid">
<style>
.layout.grid .left-center-right {
width: 100%;
display: grid;
grid-template-rows: 100px;
grid-template-columns: 300px auto 300px;
}
.layout.grid .left {
background: #ff0000;
}
.layout.grid .center{
background: #ff9400;
}
.layout.grid .right {
background: #c40;
}
</style>
<article class="left-center-right">
<div class="left"></div>
<div class="center">
<h1>grid网格解决方案</h1>
1.这是三栏布局中间buf部分
1.这是三栏布局中间buf部分
</div>
<div class="right"></div>
</article>
</section>

五种方案比较

  • float:清除浮动,脱离文档流,处理不好,带来很多问题,本身的局限性,兼容性比较好
  • position:快捷,不容易出现问题,布局已经脱离文档流,下面的子元素也要脱离文档流,导致可使用性、有效性差
  • flex:解决上面float、position的不足,兼容性不好,主要应用移动端
  • table:table-cell,很多场景中适用,兼容性好
  • grid:网格布局,新技术,可做很多复杂事情
  • flex与table-cell两种看应用场景使用

如果已知高度去掉,中间的高度变化,左右同时变化,那个方案不实用

  • 推荐flex与table
  • float 需要创建bfc

大家也可以扩展延伸

三栏布局
  • 左右宽度固定,中间自适应
  • 上下高度固定,中间自适应
两栏布局
  • 左宽度固定,右自适应
  • 右宽度固定,左自适应
  • 上高度固定,下自适应
  • 下高度固定,上自适应

Hello World

发表于 2019-04-29 | 分类于 blog

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

1…67
yongfeng.peng

yongfeng.peng

(女英

67 日志
13 分类
11 标签
© 2022 yongfeng.peng