前端知识梳理
新元素
audio
、视频video
article nav footer section aside
等新属性
新事件
取消了一些元素(font,center等)
新增DOCTYPE声明
完全支持css3
本地存储
什么是语义化标签
为什么用
怎样用
div
和span
作用
cookie
sessionStorage和localStorage不会讲数据发送给服务器,仅仅保存在本地
存储大小
存储时间
作用域不同
src是指向尾部资源的位置,用于替换当前元素,比如js脚本,图片等。
href指向网络资源所在的位置,用于应用建立连接确定之间的联系。
盒模型由
content padding border margin
组成两个标准:标准盒模型和IE盒模型
两种盒模型的区别
如何设置这两种盒模型?
css3的属性box-sizing
//标准盒模型
box-sizing:content-box
//IE盒模型
box-sizing:border-box
BFC块级格式化上下文。它是一个独立的渲染区域,规定和内部如何布局,并且这个区域和外部毫不相干
BFC原理
怎么创建BFC?
应用场景
clear
属性的元素.news {
background-color: gray;
border: solid 1px black;
}
.news img {
float: left;
}
.news p {
float: right;
}
.clear {
clear: both;
}
<div class="news">
<img src="news-pic.jpg" />
<p>some textp>
<div class="clear">div>
div>
优点:简单代码少,浏览器的兼容好。
缺点:需要添加无语义的html元素,代码不够优雅,不利于维护。
使用CSS的overflow属性
触发BFC清楚浮动
.news {
background-color: gray;
border: solid 1px black;
overflow: hidden;
*zoom: 1;
}
.news img {
float: left;
}
.news p {
float: right;
}
<div class="news">
<img src="news-pic.jpg" />
<p>some textp>
div>
使用CSS的:after伪元素
结合:after
伪元素和IEhack,完美兼容各大主流浏览器.
.clearfix:after{
content: "020";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clearfix {
/* 触发 hasLayout */
zoom: 1;
}
用法
/*apply()方法*/
function.apply(thisObj,[arg1,arg2,arg3])
/*call()方法*/
function.call(thisObj,agr1,arg2,arg3);
共同点
不同点
(function(){...})()
创建一个匿名函数并且立刻执行,由于外部无法引用到它的内部变量,因此在执行完毕后就可以立刻被释放,不会污染全局变量Object是复杂数据类型
typeof
操作符instanceod
操作符js是一门具有自动垃圾回收机制的语言,开发人员不必要过于关心内存分配和回收的问题
DOM是W3C的对象模型,DOM是中立与平台和语言的接口,它允许程序脚本动态的访问和更新文档结构和样式
promise是ES6对于异步编程提供的一种解决方案,比传统的解决方案(回调函数和事件)更加合理
传统回调
// 当参数a大于10且参数func2是一个方法时 执行func2
function func1(a, func2) {
if (a > 10 && typeof func2 == 'function') {
func2()
}
}
func1(11, function() {
console.log('this is a callback')
})
Promise改写
function fun1(a) {
return new Promise((resolve, reject)=>{
if(a>10){
resolve(a)
}else {
reject('b')
}
})
}
fun1(7)
.then(res =>{
console.log('cj')
})
.catch(err=>{
console.log(err)
})
promise对象的两个特点
Promise对象实例的两个参数
promise对象的实例方法
主要的区别就是axios、fetch都支持promise对象的API,ajax只能使用回调函数。
let arr = [1,2,3,4,5];
//第一种
Object.prototype.toString.call(arr) // "[object Array]"
//第二种
Arr.isArray(arr) // true
//第三种
arr instanceof Array // true
//第四种
arr.constructor === Array //true
join()
将数组的元素组成起来变成一个字符串,接受一个参数即分隔符,如果省略参数则用逗号代替
push()和pop()
shift()和unshift()
sort()
按照升序排列数组项,也可以传递一个比较函数来控制是升序还是倒叙排列
reverse()
反转数组的顺序
concat()
将参数添加到原数组中,返回新创建的数组。
slice()
返回原数组中指定开始下标到结束下标之间的新数组。接受两个参数,即开始和结束位置,如果只有一个参数时,结束位置到当前数组的末尾。如果有两个参数,则返回起始位置和结束位置之间的项目,但是不包括结束位置
splice()
可以实现删除,插入和替换。
参数 | 描述 |
---|---|
index | 必须。整数,规定添加或者、删除的位置,使用负数的话从尾部开始算 |
howmany | 必须。要删除的项目的数量。如果为0则表示不删除 |
item1,…, itemx | 可选,向数组添加的新项目 |
始终都会返回一个新数组,返回删除后的值,如果没有删除值则返回空。该方法会修改原数组。
indexOf()和lastIndexOf()
这两个方法都返回要查找的项在数组的中位置,没有找到则返回-1
indexOf() 接受两个参数,要查找的项和查找开始的起点(可选)
lastIndexOf() 同上,区别是从数组的最后一项开始查找。
forEach
对数组进行遍历循环,对数组中的每一项运行给定函数,本身没有返回值。参数为function类型,参数为数组的内容,对应的索引,数组的本身。
map()
指映射,对数组中的每一项运行给定的函数,返回每次函数调用的结果组成的数组。
filter()
过滤功能。数组中的每一项都运行给定的函数,返回满足过滤条件组成的数组。
every()
判断数组中每一项是否都满足条件,只有都满足条件才返回true
some()
判断数组中是否有满足条件的项,有的话返回true
reduce()和reduceRight()
这两个方法都会迭代数组的所有项,然后构建一个最终返回值。
这两个方法都接受两个参数,在每一项是哪个调用的函数和作为归并基础的初始值(可选)
假设B复制了A,当修改A时,如果B发生了变化,那就是浅复制,如果没有发生变化就是深复制。
为什么会出现这种情况?
如何实现深拷贝?
let obj = {
a:34,
b:5,
c:{
a:2,
b:54
}
}
//深拷贝
//使用JSON对象的parse和stringify 先将对象转成字符串形式,再转存过来赋值
let deep = JSON.parse(JSON.stringify(obj))
//递归实现深拷贝
function deep(obj){
let clone = Array.isArray(obj) ? [] : {};
for(let key in obj){
if(obj.hasOwnProperty(key)){
//判断子元素时候是引用类型,是的话使用递归继续拷贝
if( obj[key] && typeof obj[key] === 'object'){
clone[key] = deep(obj[key])
}else {
clone[key] = obj[key]
}
}
}
return clone
}
数据驱动(双向数据绑定)
vue数据观测实现原理是利用
Object.defineProperty
和储存器属性
组件系统
可以监听多个方法
<input type="text" :value="name" @input="onInput" @focus="onFocus" @blur="onBlur" />
但是同一种事件类型会报错
//报错
<`a href="javascript:;" @click="methodsOne" @click="methodsTwo"></a>
key值用于管理可复用的元素。因为vue会尽可能高效的渲染元素,通常会复用已有元素,而不是从头渲染。
但是如果两个元素是相互独立,不需要复用他们。只需要添加一个
key
即可
因为vue的异步更新队列,
$nextTick
是用来知道什么时候DOM更新完成的。
<div id="app">
<div id="div" v-if="showDiv">这是一段文本</div>
<button @click="getText">获取div内容</button>
</div>
<script>
var app = new Vue({
el : "#app",
data:{
showDiv : false
},
methods:{
getText:function(){
this.showDiv = true;
var text = document.getElementById('div').innnerHTML;
console.log(text);
}
}
})
//这里会抛出错误,获取不到div元素,原因就是异步更新队列的存在
使用$nextTick
处理
<div id="app">
<div id="div" v-if="showDiv">这是一段文本</div>
<button @click="getText">获取div内容</button>
</div>
<script>
var app = new Vue({
el : "#app",
data:{
showDiv : false
},
methods:{
getText:function(){
this.showDiv = true;
this.$nextTick(function(){
var text = document.getElementById('div').innnerHTML;
console.log(text);
});
}
}
})
主要用于保留组件状态或者避免重新渲染。
包裹动态组件,会缓存不活动的组件实例,而不是去销毁他们。
include
和exclude
属性允许组件有条件的进行缓存
用法
<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
<!-- 多个条件判断的子组件 -->
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>
<!-- 和 `` 一起使用 -->
<transition>
<keep-alive>
<component :is="view"></component>
</keep-alive>
</transition>
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
vue实例从创建到销毁的一些列过程,在这个过程会运行一些叫做生命周期函数的钩子。给用户在不同的阶段添加自己代码的机会。
钩子函数 | 详情 |
---|---|
beforeCreate | 在实例初始化后,数据观测和事件配置之前被使用 |
created | 在实例化创建完成后立刻被调用,已经完成数据观测,属性和方法的运算、事件回调。但是挂载阶段还没有开始。$el属性目前不可以使用 |
beforeMount | 在挂载开始之前被调用,相关的render函数首次被调用 |
mounted | el被新创建的vm.$el替换,并挂载到实例上去之后,调用该钩子 |
beforeUpdate | 数据更新前调用,发生在虚拟DOM打补丁之前。该钩子函数在渲染器不被调用 |
updated | 数据更新后调用。在渲染期不被调用 |
actived | keep-alived 组件激活时候被调用.在渲染期不被调用 |
beforeDestroy | 实例销毁之前调用,在这一步实例仍然完全可以用,在渲染期不被调用 |
destroyed | 实例销毁后被调用,调用后vue实例指示的所有组件都会被解绑。在服务器渲染期不被调用 |
由于javascript的限制,Vue不能检测对象属性的删除和添加,对于已经创建的实例,vue不能动态的添加根级别的响应式属性,但是可以使用
Vue.set(obj,key,value)
方法嵌套对象,添加响应式属性。
var vm = new Vue({
data:{
user:{
name:jason
}
}
})
//添加新的属性给user对象
Vue.set(vm.user,'age',35)
//如果需要添加多个属性的话
vm.user = Object.assign({},vm.user,{
height:'175cm',
like:'sleep'
})
Vue等单页面应用的优缺点
单页应用:就是只有一张web页面的应用。SPA是加载单个HTML页面并在用户与应用程序交互时动态更新页面的web应用程序。对于单页应用来说模块化的开发和设计显得相当的重要
自定义指令的几个钩子函数
bind
只调用一次,指令第一次绑定到元素的时候调用,在这里可以进行初始化操作inserted
被绑定元素插入父节点时调用update
所在组件的VNode更新前调用componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind
只调用一次,组件解绑时候调用钩子函数的参数
除了
el
之外,其它参数都应该是只读的,切勿进行修改。如果要在钩子之间共享数据,建议通过元素的dataset来进行
v-if
可以在http请求返回后再显示。父子组件通讯
非父子之间的传值
非父子组件之间的通讯需要定义一个公共文件bus.js
,作为中间仓库来传值。
//公共bus.js
import Vue from 'vue'
export default new Vue()
//组件a
<template>
<div>
A组件:
<span>{{elementValue}}</span>
<input type="button" value="点击触发" @click="elementByValue">
</div>
</template>
<script>
// 引入公共的bug,来做为中间传达的工具
import Bus from './bus.js'
export default {
data () {
return {
elementValue: 4
}
},
methods: {
elementByValue: function () {
//触发事件
Bus.$emit('val', this.elementValue)
}
}
}
</script>
//组件B
<template>
<div>
B组件:
<input type="button" value="点击触发" @click="getData">
<span>{{name}}</span>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data () {
return {
name: 0
}
},
mounted: function () {
var vm = this
// 用$on事件来接收参数
Bus.$on('val', (data) => {
console.log(data)
vm.name = data
})
},
methods: {
getData: function () {
this.name++
}
},
destroyed(){
//在组件销毁时,一定要解绑事件.不然会出现一些不可预知的事情
Bus.$off('val')
}
}
</script>
什么是VueX?
使用VueX的核心概念?
vuex和单纯的全部对象有一下不同:
使用CDN加速
添加cache-control或者expire报文头
浏览器和代理使用缓存来减少HTTP的数量和大小,从而加快网页的加载速度。
web服务器使用http响应中的expire头来告诉客服端可以缓存组件资源多久。比如
Expires:Thu,15 Apr 2019 20:00:00 GMT
//表示在2019-04-15前都可以缓存该资源
Gzip压缩传输文件
从HTTP1.1开始支持Access-Encoding进行压缩
Accept-Encoding:gzip,deflate
gzip一般可以减少响应的70%
配置ETags
实体标记ETag使web服务器和浏览器用于确定浏览器缓存中的组件是否与源服务器上组件匹配的机制。添加ETag以提供验证比上次修改日期更灵活的机制。
//服务器端设置
HTTP/1.1 200 OK
Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
ETag: "10c24bc-4ab-457e1c1f"
Content-Length: 12195
浏览器要是需要验证组件,用If-None-Match
头部来传递ETag给服务器。如果ETag匹配,则服务器返回304
//浏览器端设置
GET /i/yahoo.gif HTTP/1.1
Host: us.yimg.com
If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT
If-None-Match: "10c24bc-4ab-457e1c1f"
HTTP/1.1 304 Not Modified
使用GET Ajax请求
XMLHttpRequuest
时,POST在浏览器中实现为两步过程,首先发送头部,然后在发送数据。但是GET只要发送一次。但是在IE中最大url长度为2k,如果长度超过则可能无法发送。避免空的图片src
减少cookie的大小
页面内容使用无cookie域名
当浏览器在发出静态图像并请求cookie与请求一起发送时,服务器对这些cookie没有任何的用处,这些都属于白白浪费的流量
www.example.com
,您可以托管您的静态组件在域名static.example.com
上。但是如果您在顶级域名上设置了cookie,那么所有的请求都会包含这些cookie。@import
和把css放在底部行为一直,所以最好别用。AlphaImgeLoader
过滤器旨在解决IE版本低于7的半透明真彩色PNG的问题。该过滤器的问题在于他在下载图像时候阻止页面渲染并且冻结浏览器。增加内存的消耗,并且每个元素用于而不是每个图像。因此问题成倍增加。docum.write
来插入内容,他就不能被移到底部。defer
属性表明脚本不包含document.write。1**(信息类):表示接收到请求并且继续处理
2** (响应成功类):表示请求被成功接收、理解和接收
3** (重定向类):表示完成了指定的动作,必须接受进一步处理
4** (客户端错误类):请求包含语法错误或者不能正确的执行
5** (服务器错误类)
get请求在浏览器退回的时候是无害的,因为浏览器会缓存get请求的数据,而post请求不会被缓存,所以在post请求在退回时会再次提交请求(除非主动设置)。
get的请求产生的地址可以被存入书签,而post不可以。
get请求的只能进行url编码,而post可以支持多种编码方式
get请求在url中传输是有大小限制的,大约为2k(具体浏览器不一样),而post存放在body中,所以没有大小限制
理论上可以玩url上塞无限的参数,但是由于浏览器和服务器的限制,数据量太大会增大负担,所以大多数参数超过2kb直接不处理。
get将参数暴露在url上,所以一般不用于传递敏感信息。
get请求只产生一个数据包,而post需要发送两次。