2017年8月
1,ES6 Map和Set
Map
ES6中新增的数据类型,类似PHP中的键值对形式结构
var m = new Map([['a',1],['b',2],['c',3]]);
m.get('a'); //1
m.set('d',4); //新增
Set
ES6中新增了Set数据结构,类似于数组,但是它的成员都是唯一的,其构造函数可以接受一个数组作为参数
let array = Array.from(newSet([1,1,1,2,3,2,4]));
//Array.from函数可以实现set-->Array的转化
console.log(array);// => [1, 2, 3, 4]
2,MVVM
angular,js
脏检查模式:在angular中当触发某些执行条件时(如change,input等),执行一个检测轮询,来遍历所有数据,对比更改的地方,然后执行变化,响应到DOM
因为此方法不科学,有很多多余的遍历,故称为脏检查
vue.js
数据劫持:在ES5中定义了一个名为"属性描述符的对象",可以通过Object.getPropertyDescriptor()来查询,getPropertyDescriptor接收一个对象,和对象上的某个属性两个参数,查询该属性的四个描述符状态,如:
Object.getPropertyDescriptor({x:1},x);
//返回该属性的值,可写性,可枚举性和可配置性
{
value:1,
writable:true,
enumeable:true,
configurable:true
}
而需要设置,修改这些特性时,使用Object.defineProperty。在vue vm中通过Object.defineProperty()对需要监听的每个对象属性设置getter和setter,每当对象属性的数据发生变更时,触发setter的函数(劫持),在setter中通知所有的订阅者,watcher监听到变化之后更新视图
函数节流
「函数节流让一个函数只有在你不断触发后停下来歇会才开始执行,中间你操作得太快它直接无视你。」
为了节制某些函数的执行频率,在触发时设置setTimeout,如果短时间内再次触发,清除上一个定时器,设置新的定时器。
function throttle(method, context) {
clearTimeout(methor.tId);
method.tId = setTimeout(function(){
method.call(context);
}, 100);
}
//接收一个函数和一个上下文(函数执行上下文为非必选参数),将定时器设为该函数的一个属性,100ms内再次调用这个函数将清除并重新设置定时器
//调用
window.onresize = function(){
throttle(myFunc);
}
//摘自js高程
2017年9月
1,获取浏览器窗口大小
//PC
var pageWidth = document.documentElement.clientWidth || document.body.clientWidth;
pageHeight = document.documentElement.clientHeight || document.body.clientHeight;
//移动设备中,除了以上方法window.innerWidth || window.innerHeight都保存着可见视口信息
2,常见的POST数据提交方式
application/x-www-form-urlencoded:浏览器的原生表单提交,若不设置参数格式,默认就为application/x-www-form-urlencoded,后端可以方便读取
multipart/form-data:常用于文件上传,于表单和请求头中设置
application/json:这种方案,可以方便的提交复杂的结构化数据,特别适合 RESTful 的接口。各大抓包工具如 Chrome 自带的开发者工具、Firebug、Fiddler,都会以树形结构展示 JSON 数据,非常友好。
3,前端安全XSS和CRSF
XSS,跨站脚本攻击,全称cross-site scripting,使用js脚本注入的方式攻击网站。
防范:
1,过滤转义输入输出,若输入输出中带有<script>等标签,将不会被执行。
2,通信cookie使用httponly属性,防止被读写.
CRSF,跨站请求伪造,伪造请求发送到服务器
防范:
1,防止登录的session长时间储存在客户端中,设置reprice
2,检测请求域名
3,关键请求使用验证码
4,CSS中的box-sizing
box-sizing用于设置盒模型的模式
其中属性
context-box:(默认值)标准盒模型,border和padding不计入元素width中,一个块的总宽度等于margin+padding+border+width
border-box:IE怪异盒模型,border和padding计入width中,一个块的总宽度等于margin+width
padding-box:padding计算入width内
5,H5语义化标签
标签写得语义化有助于SEO,搜索引擎易检索查到。
充分利用各种HTML标签完成他们本职的工作。
6,创建对象方式
1,对象字面量 var obj = {a:1}
2,构造函数创建对象 var obj = new Function()
3,对象原生方法创建 var obj = Object.create({})
7,New一个新对象时发生了什么?
var obj = new Function()
1,创建了一个新对象 obj
2,将this上下文指向这个新对象 this-->obj,此时的这个对象已经是继承于构造函数.prototype
3,执行构造函数中的代码
4,返回一个新对象 return obj 共四步
8,性能优化
1,雪碧图,减少http请求
2,减少dom操作(事件代理等)
3,压缩js,css
4,CDN静态资源托管
5,DNS预加载(在头部添加meta标签,预先请求域名外的域名文件)
9,今日杂项
1,表单reset之后不是清空表表单,而是重置到每个input都为默认的value值
2,Jq中设置dom属性为$("#id").attr('src',path);
而在JS中为dom.setattribute('value',value);
3,原生表单提交阻止页面自动跳转,设置一个隐藏的iframe,然后将表单的target指向该iframe,返回信息显示在iframe中而页面不会跳转。原始发送表单submit()。
4,刷新页面location.reload。
10,ES6深拷贝
var arr = [1,2,3]
var copy = Object.assign([],arr) //此处的第一个参数也能换成{}对象形式,返回的copy即为键值对对象
copy.push(4)
console.log(arr) //[1, 2, 3]
console.log(copy) //[1,2,3,4] 对copy的操作并未对arr产生影响
11,事件委托性能优化
在一个UI李有10个li,实现点击对应的li,输出对应的下标
var lis = querySelectorAll('li')
for(var i = 0 ; i < 10 ; i++){
lis[i].onclick = (function(a) {
return function() {
alert(a)
}
})(i) //闭包实现块级作用域
}
使用事件委托
利用冒泡的原理,把事件加到父级上,触发执行效果。
1.可以大量节省内存占用,减少事件注册。
2.可以方便地动态添加和修改元素,不需要因为元素的改动而修改事件绑定。
var ul = document.querySelector('ul');
var list = document.querySelectorAll('ul li');
ul.addEventListener('click', function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElemnt;
for(var i = 0, len = list.length; i < len; i++){
if(list[i] == target){
alert(i + "----" + target.innerHTML);
return
}
}
});
!!!!注意:addEventListener()方法添加的匿名函数是无法移除的,所以如果需要移除监听器,添加时应使用函数名添加。(若多次添加相同的监听器不会覆盖,而是在触发时执行两次)
11,split、join、splice、slice
var a = [1,2,3,4,5]
a = a.join('-') //将数组以传入的参数连接起来,返回一个合并的字符串
console.log(a) //1-2-3-4-5
a = a.split("") //将字符串以传入的参数分隔,返回一个分隔的数组
console.log(a) //[1,-,2,-,3,-,4,-,5]
var del = a.splice(0,3) //直接对源数组进行修改从下标0开始的长度为3数组
console.log(del) //[1,-,2]
console.log(a) //[-,3,-,4,-,5]
a = a.slice(0,1) //不修改原数组,返回从下标0开始长度为1的截取的数组
console.log(a) //[-]
***********************************************************************************
split(' ')操作字符串
join('-')操作数组 -->合并为字符串
splice(0,3)操作数组 -->删除
slice(0,3)操作字符串,数组皆可 -->即可分隔数组,又可分隔字符串
12,Object.creat()函数
Object.creat()函数接受两个参数,第一个设置的是这个新创建的对象所指向的原型对象,第二个是这个新创建对象的属性。收获一种新的创建对象的方法hhh
var obj = Object.create(null,{ //此处原型对象可以传空值,此时obj的__proto__指针指向null
name:{
value:'cty', //使用Object.create创建对象时,对象的属性名内,属性值必须用value设置
enumerable: true //enumerable设为true将其设置为可枚举属性
}
})
console.log(obj.name) //cty
13,文件上传
直接上代码
label for="resource" class="upload">pdf上传</label>
<input type="file" id="resource" name="resource" ref="resource" @change="fileChange">
----------------分割线-----------------------
fileChange(e) {
//通过事件获取到上传的文件,操作字符串获得文件格式,files的size方法控制上传文件大小
var fileSize = 0;
获取上传的文件
var files = e.target.files || e.dataTransfer.files;
fileSize = e.target.files[0].size;
var size = fileSize / 1024;
if(size>2000){
alert("附件不能大于2M");
e.target.value="";
return
}
var name = e.target.value;
var fileName = name.substring(name.lastIndexOf(".")+1).toLowerCase();
if(fileName != "pdf" && fileName != "mp4" && fileName != "ppt" && fileName != "pptx" && fileName != "avi"){
this.$alert('文件格式有误,请选择PPT,PDF,PPTX,avi,mp4格式上传', '提示', {
confirmButtonText: '确定',
type: 'warning'
})
e.target.value="";
return
}
14,js获取事件和h5中的data-*属性
在全局下发生点击的事件可以直接传入函数中,如click(e)
(即便绑定时并没有传入这个参数)
然后,通过e.target
可以获取目标元素,即事件流中的事件触发阶段的最具体的元素
再然后,
获取元素上绑定的data-*属性,用原生js,方法为let value = e.target.dataset.*
。
动态设置,用原生js,方法为e.target.dataset.*='xxx'
dataset属性的值是DOMStringMap的一个实例,名值对的映射。每个data-name形式的属性都有一个对应的属性,只不过该属性名没有data-前缀。
15,reduce方法
reduce为数组方法,数组对象可以调用,接收的回调函数接收两个参数,第一个是上一次处理后的属性的值,第二个是上一个属性的下一个属性
var arr = [1,2,3,4,5]
arr.reduce(function(pre,cur){
return pre+cur
})
//可以简单地对number数组求和
//回调函数第一次执行pre为空,cur为1
//第二次执行pre为上一次返回的数值,即1,cur进入数组下一个值为2
//第三次执行pre为上一次返回的数值,即3,cur进入数组下一个值为3
//...以此类推,最后得出1至5的累加为15
15,Object.key(obj)
或得一个对象数组的属性值,通常检测属性值可以使用hasOwnProperty
var o = {a:'123',b:'456'}
Object.keys(o).forEach(res=>{
console.log(res)
}) //a b
2017年10月
1,这里放一些Vue全局对象的基本操作
1,axios.defaults.withCredentials = true
默认允许后台跨域操作,如在客户端存储cookie等需要权限的操作。重要,若请求不设置,后端无法在客户度设置cookie,再发起请求时无法在请求头中携带cookie会发生302错误
2,Vue.config.productionTip = false
设置 Vue.config.productionTip = false 来关闭生产模式下给出的提示
3,Vue.prototype.$axios = axios
Vue实例添加axios方法
4,前端响应式布局
rem怎么来的?
rem是css3中新增加的一个单位属性(font size of the root element),根据页面的根节点的字体大小进行转变的单位。根节点,也就是html。
例:(下面例子中的根节点是html ,它的字体大小是100px,所以根节点下面的元素所设置的rem,都是1rem=100px。)
rem的初始值是16px,也就是说在没有设置根节点的font-size的时候,1rem=16px;
于是,只要在媒体查询中改变根节点的font-size设置,rem将自动根据根节点设置的font-size进行适配。
html,body{
height: 100%;
margin: 0;
padding: 0;
font-size: 14px;
}
@media screen and (max-width:320px ) {
html{font-size: 12px;}
}
@media screen and (min-width:321px) and (max-width:750px ) {
html{font-size: 14px;}
}
@media screen and (min-width:751px ) {
html{font-size: 16px;}
}
以此适配三种屏幕大小。
5,判断一个字符串是否是回文字
function isreverse(str){
//reverse只能作用于数组,将数组反转
return str.split('').reverse().join('') == str
}
6,统计一个字符串中出现最多的字符
var str = 'aabbcc'
function findMaxDuplicateChar(str){
var obj = {}
var max = 0
var maxindex = []
for(var index in str){
//存储在对象类数组中,并统计次数
if(!obj[str[index]]){
obj[str[index]] = 1
}else{
obj[str[index]] += 1
}
}
for(var index in obj){
//for..in..也可以作用于类数组
if(obj[index] >= max){
max = obj[index]
maxindex.push(index)
}
}
return maxindex
}
findMaxDuplicateChar(str)
> 输出(3) ["a", "b", "c"]
以下排序算法皆是从小到大
7,冒泡排序
冒泡排序原理是,每次比较数组中相邻的两个元素,每次将大的数放在后面,小的数向上冒泡,所以经过第一轮冒泡后,最大的数已经在最后一位了。第一轮比较了n-1次,第二轮只要比较n-2次,最后最大的那个数已经不用比较了。代码如下:
function bubbleSort(arr){
//每次要比较的次数减一
for(var i = arr.length ; i > 0 ; i--){
for(var j = 0 ; j < i ; j++){
if(arr[j] > arr[j+1]){
//如果满足条件,交换位置
var tmp = arr[j]
arr[j] = arr[j+1]
arr[j+1] = tmp
}
}
}
return arr
}
var arr = [1,4,3,6,7,23,56,2]
bubbleSort(arr)
> 输出(8) [1, 2, 3, 4, 6, 7, 23, 56]
8,快速排序
快速排序的原理是:递归
每次递归判断数组长度是否小于或等于1个数。若否,则取出数组中的第一个数,对剩下的n-1个数进行遍历,把较大的数放在右边,较小的数放在左边,再对左右数组再次进行快排,分别以左右两边数组的第一个数为哨兵,再次比较分组,最后将所有的分组数组使用[].concat方法连接,得到一个从小到大的数组。代码如下:
function quickSort(arr){
//此处还有左边或右边数组一个元素都没有的情况
if(arr.length <= 1){
return arr
}
let leftArr = []
let rightArr = []
let p = arr[0]
for(var i = 1 ; i < arr.length ; i++){
if(arr[i] < p){
leftArr.push(arr[i])
}else{
console.log(arr[i])
rightArr.push(arr[i])
}
}
return [].concat(quickSort(leftArr),arr[0],quickSort(rightArr))
}
var arr = [7,3,45,2]
quickSort(arr)
> 输出(4) [2,3,7,45]
9,斐波那契数列
又称黄金分割数列:0,1,1,2,3,5,8,13.....
斐波那契数列的原理也是递归,代码如下
function getFibonacci(n){
var fibarr = []
for(var i = 0 ; i < n ; i++){
if(i < 2){
//前面两个数不需要递归,从0,1开始产生递归
fibarr.push(i)
}else{
fibarr.push(fibarr[i-2]+fibarr[i-1])
}
}
//其实整个方法只调用了一次,只是通过fibarr[i-2]+fibarr[i-1]不断调用了之前的数组,所以也叫递归
return fibarr
}
上次笔试竟然写不出来。。。。平时用不到,但是原理不能忘!!!
10,前端上传多种格式文件参数设置
fileChange(e){
//监听文件上传的input框change事件
var value = e.target.dataset.type
var name = e.target.value
var fileName = name.substring(name.lastIndexOf(".")+1)
//获取文件后缀名,这里也可以用slice
//var fileName = name.substring(name.lastIndexOf(".")+1).toLowerCase()
if(value == 'pdf'){
if(fileName != "pdf"){
this.$alert('文件格式有误,请选择PDF格式上传', '提示', {
confirmButtonText: '确定',
type: 'warning'
})
e.target.value="";
return
}else{
this.file1 = event.target.files[0]
}
}
if(value == 'ppt'){
if(fileName != "ppt" && fileName != "pptx"){
this.$alert('文件格式有误,请选择PPT,PPTX格式上传', '提示', {
confirmButtonText: '确定',
type: 'warning'
})
e.target.value="";
return
}else{
this.file2 = event.target.files[0]
}
}
this.loading = true
//通过验证
this.$axios.post(BASEPATH+'/subject/info/list/all').then(
res=>{
var data = res.data.allSubjectList
var subId = document.getElementById('subjectid').value
//重复验证
for(var index in data){
if(subId == data[index].subjectid){
this.$alert('此课程id重复,请重新输入!', '提示', {
confirmButtonText: '确定',
type: 'warning'
})
return
}
}
//文件转为formData格式才能正确上传带文件的from表单
var formData = new FormData();//formData属性
formData.append('subjectid',this.subjectid)
formData.append('title',this.title)
formData.append('remark',this.remark)
formData.append('parentid',this.parentid)
formData.append('status',this.status)
//formData.append('imgPath',this.imgPath)
formData.append('lessonDetail',this.lessonDetail)
formData.append('relatedLesson',this.relatedLesson)
if(this.file1){
//file文件append到formData后数据格式发生变化
formData.append('resource',this.file1)
}
formData.append('lessonPptnum',this.lessonPptnum)
var config = {
//文件上传使用multipart/form-data格式上传,设置ajax参数
headers: {
'Content-Type': 'multipart/form-data'
}
}
//发送请求 this.$axios.post(BASEPATH+'/subject/info/upload',formData,config).then(res=>{
if(res.data.code == 1){
this.$message({
type: 'success',
message: '上传成功!'
})
this.$router.push({path:'super_courselist'})
}else{
this.$message({
type: 'error',
message: '上传失败!'
})
this.loading = false
}
})
}).catch(err=>{
this.$alert('提交出错!', '提示', {
confirmButtonText: '确定',
type: 'error'
})
this.loading = false
})
}).catch((err) => {
this.$message({
type: 'warning',
showClose: true,
message: '已取消提交'
});
});
},
//判断输入字符格式,使用了ES6模板解析
isString(...s){
for(var i of s){
if(i!=null && typeof i != 'string'){
return false
}
}
return true
},
isNumber(...n){
var pattern =/^[0-9]+([.]{1}[0-9]{1,2})?$/
for(var i of n){
if(i!=null && !pattern.test(i)){
return false
}
}
return true
}
}
11,css伪类创建三角形箭
原理是利用绝对定位的伪类元素,创建边框颜色为透明色的,仅有边框的正方形,在需要设箭头方向的的另一侧设置边框为所需箭头颜色。即出现一个小△。
若要出现箭头,则使用after,before两个大小相同的三角形通过position定位重叠后留下一个小箭头。
12,闭包
闭包是指能够访问其他函数内部变量的函数。
最常见的产生闭包的方法就是在一个函数内部创建另一个函数。
闭包的作用域链包含所引用的外部函数的活动对象,自身活动对象(如果有的话)和全局变量对象(全局变量对象,谁都有)
理解闭包的作用域链,就可以清晰地知道this
的指向了
this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this指向window对象,而当函数被当作某个对象的方法调用时,this等于那个对象。
匿名函数的this对象延作用域链向上搜寻,但是只会搜索到其活动对象为止,搜索不到外外部函数的活动对象,如果都没有,this则会指向全局对象window
13,清除浮动
1,给父元素设置高度
2,在父元素的结尾处添加一个有clear:both属性的盒子标签
3,overflow:hidden
4,使用伪类元素
.clearfix:after{
content:'';
height:'';
display:block;
visibility:hidden;
clear:both;
}
.clearfix{
zoom:1;//兼容ie
}
第五种方法应用最为广泛,不用添加额外的标签,而且可以通用,添加一个class类名即可。
14,BFC(block fomating context)块级格式上下文
描述:简单地说,BFC描述的是块级盒的布局规则
作用:BFC可以用来清除浮动和防止margin重叠
防止margin重叠:因为当块级盒外层没有BFC作保护时,margin-top和margin-bottom会发生重叠,解决办法是在外层套一个BFC保护,则不会再发生重叠
**清除浮动""
- BFC会阻止垂直外边距(margin-top、margin-bottom)折叠
- BFC不会重叠浮动元素
- BFC可以包含浮动
我们可以利用BFC的第三条特性来“清浮动”,这里其实说清浮动已经不再合适,应该说包含浮动。也就是说只要父容器形成BFC就可以,如何形成BFC
- float为 left|right
- overflow为 hidden|auto|scroll
- display为 table-cell|table-caption|inline-block
- position为 absolute|fixed
我们可以对父容器添加这些属性来形成BFC达到“清浮动”效果。
15,undefined和null的区别
如果一个变量声明后未初始化,那么改值为undefined
如果一个变量声明后接下来是为了保存某种对象的,那么就把它初始化为null,也因此typeof null
结果为object
16,文档声明<!DOCTYPE>
文档声明在html文档的最前面,作用是为了告知浏览器的解析器,用什么文档类型规范来解析这个文档,只有正确地确定了一个文档类型,html和css才能正常生效。
html4.01是基于SGML(标准通用标记语言,xml可扩展标记语言是它的子集)的,在文档声明中需要引用.dtd文件(DTD文件就是文档类型声明文件)
根据DTD引入的不同会触发两种格式
标准模式和混杂模式
标准模式,浏览器以其支持的最高标准呈现页面
混杂模式,页面以一种比较宽松的向后兼容的方式显示。混杂模式通常模拟老式浏览器的行为以防止老站点无法工作。
而html5既然没有DTD,也就没有严格模式与宽松模式的区别,html5有相对宽松的语法,实现时,已经尽可能大的实现了向后兼容。文档声明只要简单的<!DOCTYPE html>
17,==运算符
下面程序得到的结果分别是什么?()
console.log(([])?true:false);
console.log(([]==false?true:false));
console.log(({}==false)?true:false)
A.false true true B.true true true C.true false true D.true true false
解析:
Boolean([]); //true Number([]); //0 Number({}); // NaN Number(false); //0
因此:
console.log(([])?true:fasle);// => console.log((true)?true:false); //true
console.log([]==false?true:false); // => console.log(0==0?true:false); //true
console.log(({}==false)?true:false); // => console.log((NaN==0)?true:false); //false
选D选项
拓展:《JavaScript权威指南》的部分相关知识点
“==”运算符(两个操作数的类型不相同时)
如果一个值是null,另一个值是undefined,则它们相等
如果一个值是数字,另一个值是字符串,先将字符串转换为数学,然后使用转换后的值进行比较。
如果其中一个值是true,则将其转换为1再进行比较。如果其中的一个值是false,则将其转换为0再进行比较。
如果一个值是对象,另一个值是数字或字符串,则将对象转换为原始值,再进行比较。
18,Vue Virtual DOM
由于原始的DOM操作非常耗时,对性能造成了很大的影响,但是js很快。
vue框架使用的是virtual dom来进行dom操作。
虚拟dom的核心思想是:对复杂的文档dom结构,提供一种方便的工具进行最小化的dom操作。dom的子节点,标签,属性,都可以用js来表示,当数据状态发生改变时,先通过js对象表示的虚拟dom计算出实际dom需要进行的最小改动再去操作dom。
11月
1,简单的git操作
提交
$ git add . 将文件添加到缓存区
$ git commit -m "说明" 提交缓存区的代码
$ git push origin master 推送到源分支
拉取并合并
$ git pukk origin master
2,--save和--save-dev
- --save将install的依赖包名放入package.json的dependencies中,dependencies属于项目发布之后还是需要依赖的东西。
- --save-dev将insatll的依赖包名放入package.json的devDependencies中,devDependencies属于项目发布前打包,编译等需要所依赖的工具,项目上线以后并不需要这些东西。webpack属于打包工具,安装时npm install webpack --sava-dev
3,css选择器权重
行内样式(1000) > id选择器(100) > class选择器(10) == 属性选择器(10) > 伪类选择器(+1) > 标签选择器(1) > 通用选择器(0)
4,逗号选择器总是由逗号最后的一个表达式决定的
5,浏览器渲染过程
- html文档加载后,构建dom tree
- css文档加载后,构建css rule tree
- dom tree 和 rule tree 结合生成 render tree,渲染树
- layout 计算出每一个渲染对象的位置和尺寸,将其安置在浏览器窗口的正确位置,叫回流,或者布局
- 绘制(Painting)根据上一步的layout计算出的位置和元素尺寸进行页面的绘制
dom tree --> rule tree --> render tree --> layout --> painting
6,call,apply
通过document.getElementsByTagName选择的dom 节点是一种类似array的array。它不能应用Array下的push,pop等方法。我们可以通过:
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
这样domNodes就可以应用Array下的所有方法了。
12月
1,Object.prototype.toString.call([1,2,3])
数组是类对象,但它不是真正的对象,不能直接调用toString方法,通过call改变this的指向,使得数组调用对象原型上的toString方法,数组作为类对象返回[Object string],而真正的对象则返回[Object object]。
另外判断其是否为数组
[1,2,3].__proto__.constructor == Array
true
2,vue生命周期的操作问题
vue生命周期从init到destroy,应该在哪个地方操作dom,那个地方操作数据?
首先,获取异步数据在created中,因为created中还未挂载vue实例,且未渲染,如果在其后获取异步数据,虽然也可以,但是会导致页面刷新两次,导致加载时间过长,所以获取异步数据,预处理数据都应该在created中操作。
其次,操作dom,应该在mounted或者vm.nextTick之后,因为此时所有的dom的挂载和渲染都已经完成,此时操作dom才不会出现问题。
最后再提一下updated,updated在每次数据更新的时候都会被触发,而mounted只触发一次,如果updated中获取异步数据,则每次页面有数据变化时都会触发这个异步请求。所以updated一般不推荐使用。
3,fork和clone的区别
- 区别
git clone 是在自己电脑(这里我是ubuntu)直接敲命令,结果是将github仓库中的项目克隆到自己本地电脑中了
fork是直接访问github网站,在项目页面中点击fork,然后自己github项目中就会多出一个复制的项目 - 用法
如果我们想要修改他人github项目的话,我们直接git clone代码到本地是不能pull的,所以我们使用fork,先把代码复制到自己的github仓库,然后git clone到本地修改,然后在提交pull(这里的pull是pull到自己github仓库了,我们自己的github仓库中的代码是fork源的一个分支),这时候我们想要把修改的代码提交给他人的话,就可以在自己github上pull,等其他人看到后就可以把代码做一个合并。
2018.5.21
1,重温圣杯布局和双飞翼布局
圣杯布局和双飞翼布局都是三列布局左右长度固定,中间宽度随左右变化的的一种方式,当然现在可以使用flex,中间flex为1,左右固定。
圣杯布局:
双飞翼布局:
盒子固定,中间自适应内容用新的宽度100%的盒子包裹,新盒子向内padding,左右两侧仅需利用margin负边距即可。