1)选择器 2)阴影 3)形状转换(2D <-> 3D) 4)变形 5)动画(过渡动画、帧动画) 6)边框
7)多重背景 8)反射 9)文字 10)颜色函数(rgba/hsl/hsla 11)滤镜(filter) 12)弹性布局
13)多列布局 14)栅格布局 15)盒子模型 16)Web字体 17)媒体查询
1、 Canvas绘图;2、表单元素;3、语义化标签;4、媒体元素;5、地理定位;6、拖放API;
7、Web Worker;8、Web Storage;9、Web Socket;10、SVG绘图
CSS盒子模型(Box model)就是在网页设计中经常用到的CSS技术所使用的一种思维模型
首先一个盒模型包含了padding(内边距)margin(外边距)border(边框)内容(content)也就是元素本身的width,height
盒模型能够给我们解决什么问题:
盒子模型主要是针对页面布局的时候来使用,他规范了我们页面的所有所有元素的一个布局规范是由外向内进行布局。
盒模型由外向内:margin(外边距)border(边框)padding(内边距)content(元素)
在标准的盒模型中一个盒子的宽度是:margin(左右外边距)+padding(左右内边距)+border(左右边框)+内容的(width).
当设置box-sizing:content-box时,采用标准模式进行计算,默认就是这种模式;
当设置box-sizing:border-box时,采用怪异模式进行计算;
元素可以随着屏幕宽度变化,页面也会跟着变化,效果就和PC页面的流体布局差不多,
在哪个宽度需要调整的时候使用响应式布局调调就行,这样就实现了移动端适配。
flex-direction
指定容器中的元素的排列方式
可选值:row 默认值,(水平左到右)
row-reverse 反方向(右到左)
column 纵向排列(自上向下)
column-reverse 反方向(自下向上)
主轴:弹性元素的排列方向叫主轴
侧轴:与主轴垂直方向的称为侧轴
flex-wrap:
设置弹性元素是否在弹性容器中自动换行
可选值: nowrap 默认值,元素不会自动换行
wrap 元素沿着辅轴方向自动换行
wrap-reverse 元素沿这辅轴反方向换行
flex-flow:wrap 和 direction 的简写属性
flex-flow:row wrap ;
justify-content
分配主轴上的空白空间
可选值: flex-start 元素沿着主轴起边排列
flex-end 元素沿着主轴终边排列
center 元素居中排列
space-around 空白分布到元素两侧
space-between 空白均价分布到元素间
space-evenly 空白分布到元素单侧
align-items
元素在辅轴上的分布
可选值: stretch 默认值,元素的长度设置为相同值
flex-start 元素不拉伸,沿着辅轴起边对齐
flex-end 沿着辅轴的终边对齐
center 居中对齐
baseline 基线对齐
align-content:
辅轴空白的分布
space-between 空白到两侧
align-self 用来覆盖当前元素上的align-items
align-self给单独的元素设置样式
弹性元素的样式
指定弹性元素的伸展的系数
容器的宽度为400px, 子项1的占用的基础空间(flex-basis)为50px,子项2占用的基础空间是70px,子项3占用基础空间是100px,剩余空间为 400-50-70-100 = 180px。 其中子项1的flex-grow: 0(未设置默认为0), 子项2flex-grow: 2,子项3flex-grow: 1,剩余空间分成3份,子项2占2份(120px),子项3占1份(60px)。所以 子项1真实的占用空间为: 50+0 = 50px, 子项2真实的占用空间为: 70+120 = 190px, 子项3真实的占用空间为: 100+60 = 160px。
父元素右剩余空间,子元素如何排列
flex-shrink指定弹性元素的收缩系数用来“吸收”超出的空间
flex-basis指定的是元素在主轴上的基础长度
flex-basis 用于设置子项的占用空间。如果设置了值,则子项占用的空间为设置的值;如果没设置或者为 auto,那子项的空间为width/height 的值。
order决定弹性元素的排列的顺序
animation-delay 设置动画的延迟时间,值为时间
animation-duration 设置动画的一次完整运动周期,值为时间
animation-timing-Function 设置动画的运动曲线
animation-name 设置动画的名称
animation-direction 设置动画该整个周期运动的方向,值为normal alternate
animation-iteration-count 设置动画的播放次数,值为 正整数 、infinite
animation-play-state 设置动画是否允许暂停和重新播放,值为running paused
-webkit-animation-fill-mode: both; 设置动画的结束状态,值为none both forwards
animation 设置动画的简写,属性的格式如下:
animation: (animation-name) (animation-duration) (animation-timing-Function) (animation-delay) (animation-direction-count)
先说2D的transform属性,在下列的属性值中都有两个值,分别是X轴上的值 和 Y轴上的值。
transform: translate() 在水平方向、垂直方向平移参数单位个位置
transform: translateX() 在水平方向上移动参数单位个位置
transform: translateY() 在垂直方向上移动参数单位个位置
transform: rotate() 相对于屏幕的旋转角度,正值为顺时针,负值为逆时针
transfrom: scale() 在水平方向、垂直方向缩放倍数,负值无效
transform: scaleX()
transform: scaleY()
transform:skew() 在X轴,Y轴旋转的参数角度,记住,沿着x轴、和y轴旋转
skewX()
skewY()
各大主流浏览器是由不同厂商开发的
不同浏览器所用的核心架构和代码不同
浏览器厂商出于自身利益考虑而设置的技术壁垒
渐进增强(progressive enhancement):一开始只构建站点的最少特性,然后不断地对不同的浏览器追加不同的功能
优雅降级(graceful degradation):一开始就构建站点的完整功能,然后针对浏览器进行测试和修复
优雅降级即功能衰减是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强(pe)则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。功能衰减意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带。
响应式设计的页面会根据用户的的行为以及设备的环境(系统平台、屏幕尺寸、屏幕定向等)进行相应的响应和调整。
优点
面对不同分辨率设备灵活性强,能够快捷解决多设备显示适应问题
节省设计、开发、维护成本【不再特定的维护PC页面,移动页面】
缺点
流式布局对版面设计有一定要求存在局限性
兼容各种设备工作量大,效率低下
代码累赘,会出现隐藏无用的元素,加载时间加长
影响用户体验(一定程度上改变了网站原有的布局结构,会出现用户混淆的情况,)
兼容问题(IE8以下不支持媒体查询)
@media
@media mediatype and|not|only (media feature){
css-code;
}
mediatype查询类型:将不同的终端设备划分为不同的类型,称为媒体类型
关键字:关键字将媒体类型或多个特性连接到一起做为媒体查询的条件
and:可以将多个媒体特性连接到一起,相当"且"于的意思
not:排除某个媒体类型,相当于"非"的意思,可以省略
only:指定某个特定的媒体类型,可省略
高质量代码的三大要素:
可读性、可维护性和可变更性
做好代码规范、提高代码质量,能显著增强代码的可读性、可维护性和可变更性。努力提高代码的读写可维护性,是做好代码规范的必要非充分条件。
任何语言都需要强调编码风格的一致性。只要是团队开发,每个人都以相同的方式编写代码就是至关重要的。
提高代码的读写可维护性的关键在于是否能落实公司的相关文档,公司的技术总监、项目经理或相关代码审查机关是否具有应有的执行力
软件可维护性是指理解、改正、改动、改进软件的难易程度。通常影响软件可维护性的因素有可理解性、可测试性和可修改性。
将其分为两大类:编写时可维护性和运行时可维护性。
编写时可维护性是指在程序或系统上线后爆出 BUG,开发团队能够及时扑灭这个 BUG 且不会爆出其他 BUG。
保持方法的原子性,提高代码内聚,能使某处修改的影响降到最低,这样某处方法出现 BUG,也不太会影响到其他模块的正常运作。编写时可维护性还包括了代码的可测试性。
运行时的可维护性是指在系统运行过程中(或无需再次编码发布、只需系统重启一次)修改系统的某项配置并使其生效,且不影响现在正在进行的业务和用户的操作。
这要求软件工程师不能把代码写死。例如配置文件、数据库连接字符串、资源文件、日志等。
以下是摘选的可供参考的策略:
不要把代码写死;
预测可能发生的变化
通过提高代码的复用性提高代码的可维护性
代码的可写性包括代码的可变更性,代码的可变更性是软件理论的核心。
代码的可写性是建立在代码的可维护性上的,而代码的可写性与可维护性又都建立在代码的可读性上。如果代码难以阅读,那么 BUG 的修正将变得难以入手,新功能的添加就更是无从入手了。
TypeScript 是由微软开发的一款开源的编程语言,TypeScript 是 Javascript 的超集,遵循最新的 ES6、ES5 规范,TypeScript 扩展了 JavaScript 的语法。
TypeScript 更像后端 Java、C#这样的面向对象语言,可以让 JavaScript 开发大型企业项目
面向对象就是把现实问题抽象为对象,通过调用每个对象的属性或功能去解决问题。
面向对象的三个基本特征是:封装、继承、多态。
内层函数调用外层函数定义的变量
闭包的三大特性
内嵌函数:函数嵌套函数,内嵌函数对函数中的局部变量进行访问
局部变量:在函数内定义有共享意义的局部变量
外部使用:函数向外返回此内嵌函数,外部可通过此内嵌函数访问声明在函数中的局部变量,而此变量在外部是通过其他路径无法访问的
参数和变量不会立即被垃圾回收机制回收(垃圾回收机制:专门用来回收不可用的变量值所占用的内存空间)
可读取函数内部的变量
局部变量可以保存在内存中,实现数据共享
执行过程中所有变量都匿名在函数内部
使函数内部变量存在于内存中,内存消耗大
滥用闭包可能导致内存泄露
闭包可以在父函数外部改变父函数内部的值,慎操作
返回值(最常用)
函数赋值
函数参数
IIFE(自执行函数)
循环赋值
getter和setter
迭代器(执行一次函数往下取一个值)
首次区分(相同的参数,函数不会重复执行)
缓存
节流函数
作用域是一个变量的可用范围,作用域的本质是一个保存变量的对象,作用域避免了不同范围内的数据的相互干扰。
作用域就是限制某个变量只能在某个区域内有效
作用域有全局作用域和局部作用域之分
专门保存所有全局变量的对象。
优点:随处可用,可以反复使用。
缺点:极易被污染。
专门保存函数内可用的局部变量的作用域。
优点:因为仅函数内可用,所以不会被污染。
缺点:不可以重复使用。
作用域链只能向上查找,最终找到全局。不能同级(局部)或者向下查找
作用域链是由多级作用域串联形成的链式结构
每个函数在创建时,就有了自己的作用域链,
普通函数的作用域链包含两级,
离自己近的一级,暂时为空,调用函数时,用来临时引用函数作用域对象。
离自己远的一级,始终保存着全局作用域对象window
作用域链保存着一个函数可用的全部变量
控制着变量的使用顺序:先局部,局部没有,才全局
任何构造函数在被创建的时候,系统都会自动帮我们创建一个与之对应的对象,称为原型对象
这个对象也会自动获得 constructor 属性
而实例都包含一个指向原型对象的内部指针__proto__
每当我们创造了一个构造函数,系统就会贴心的分配了一个老婆-----原型对象
从此,构造函数和原型对象过上了没羞没臊的甜蜜生活,并且有个孩子 ------实例对象
构造函数用.prototype就能找到属于自己原型对象(老婆)
原型对象用constructor就能找到属于自己的构造函数(老公)
实例对象用.proto(亲子鉴定)能找到自己的原型对象(妈妈)
每一个实例对象都有自己的原型,而原型也是对象,也有自己的原型。以此类推,形成链式结构,称之为原型链。
原型链的终点
万物皆对象(object.protype 所有界面的元素都是对象-dom对象),万物皆空(null-原型链重点)
创建了一个新对象;
将构造函数的原型对象赋值到对象的原型链上;
改变了构造函数的this指向,指向新的对象;
返回(return)对象;
let obj = {}
obj.proto = 构造函数.prototype
return obj
apply
apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入。改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次。
function fn(...args){
console.log(this,args);
}
let obj = {
myname:"韩梅梅"
}
fn.apply(obj,[1,2]); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window
//当第一个参数为null、undefined的时候,默认指向window(在浏览器中)
fn.apply(null,[1,2]); // this指向window
fn.apply(undefined,[1,2]); // this指向window
call
call方法的第一个参数也是this的指向,后面传入的是一个参数列表
跟apply一样,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次
function fn(...args){
console.log(this,args);
}
let obj = {
myname:"韩梅梅"
}
fn.call(obj,1,2); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window
bind
bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)
function fn(...args){
console.log(this,args);
}
let obj = {
myname:"韩梅梅"
}
const bindFn = fn.bind(obj); // this 也会变成传入的obj ,bind不是立即执行需要执行一次
fn.bind(obj,1,2)()
bindFn(1,2) // this指向obj
fn(1,2) // this指向window
改变this指向后不会立即执行,而是返回一个永久改变this指向的函数
三者都可以改变函数的this对象指向
三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window
三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入
bind是返回绑定this之后的函数,apply、call 则是立即执行
严格模式
user strict
js是一个弱类型语言,对程序的书写没有太严格的限制,如果 可以不使用var声明变量等,导致在程序员们在开发的过程中,出现很多不并不严谨的代码书写方式。
限定范围:当前执行上下文
1,在全局上下文使用,限定全局上下文
2,在函数上下文使用,限定函数上下文
语法限定
1,必需使用var声明变量
2,八进制被禁用
3,函数必需声明在上下文的最外层
4,函数参数中不能出现相同的形参
5,arguments获取的实参不同
6,自定义的函数中this指向作了修正,值为undefined
7, eval()函数作用域被限定不被外部访问。
1 块级作用域
var有一个问题,就是定义的变量有时候会成为全局变量。
let所声明的变量,只在let所在的代码块内有效
const声明的变量是常量,不能被修改
2 箭头函数
3 字符串扩展
includes(“xxx”):返回布尔值,表示是否包含xxx
startsWith(“xxx”):返回布尔值,表示是否以xxx开头
endsWith(“xxx”):返回布尔值,表示是否以xxx结尾
4模板字符串
5对象属性加强(默认值)
对象的函数属性简写
6 解构赋值、对象解构
7 模块
8 类class 类名{ 构造函数 定义方法 静态方法}
9迭代
10生成器
11Promise
Promise是一个对象,它可以获得异步操作的消息,
通过构造函数来创建Promise对象,并在内部封装一个异步操作的执行的结果
promise对象是一个构造函数,用来生成Promise实例;
promise的两个特点 对象状态不受外界影响 && 一旦状态改变,就不会再变,任何时候都可以得到结果(pending状态–>fulfilled || pending–>rejected)
12 运算符扩展
扩展运算符(spread)是三个点(…),将一个数组转为用逗号分隔的参数序列。
四个阶段,八个钩子
创建,挂载,更新,销毁
create,mount,update,destory
Vue生命周期钩子是如何实现的?
Vue的生命周期钩子是回调函数,当创建组件实例的过程中会调用相应的钩子方法。 内部会对钩子进行处理,将钩子函数维护成数组的形式。
beforeCreate
Create
beforeMount
Mount
beforeUpdate
Update
beforeDestroy
Destroy
beforeCreate 在实例初始化之后,数据观测observer 和event、watcher事件配置之前被调用
created 实例已经创建完成,在这一步,以下配置被完成
数据观测
watch/event时间回调
$el
尚未生成(elment)
beforeMount 在挂载之前被调用,render尚未被调用
mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用
beforeUpdate 数据更新时,被调用,发生在虚拟Dom重新渲染和打补丁之前
update 由于数据更改导致的虚拟Dom重新渲染和打补丁,在这之后调用
beforeDestroy 实例销毁之前调用 (destroy 销毁)
destroyed 实例销毁之后调用,调用后Vue实例的所有东西都会被解绑,所有的事件监听会被移,子实例被销毁,该钩子在服务端渲染期间不被调用keep-alive(activated & deactivated) (alive 活着)
Vue的核心理念是数据驱动的理念,所谓的数据驱动的理念:当数据发生变化的时候,用户界面也会发生相应的变化,开发者并不需要手动的去修改dom。
MVVM是Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。
Model代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到ViewModel层并自动将数据渲染到页面中,视图变化的时候通知viewModel层更新数据。
vue.js 采用数据劫持结合发布-订阅模式,通过 Object.defineproperty 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发响应的监听回调。
单向绑定原理: (响应系统,访问器属性,虚拟DOM树)
双向绑定原理: 在单向绑定基础上,为表单元素自动添加对应的事件处理函数。
(1). new Vue()将data对象打散,使其成员变为单个的属性,直接隶属于当前new Vue()对象。
(2). 为每个data中打散出来的单个属性请保镖(get()/set(value))。将来new Vue内访问data中的属性名,其实是访问保镖,然后通过get set保镖操作data中的属性。
(3). 每个属性的set方法,除了肩负修改data中属性值的功能外,还负责通知虚拟DOM树,哪个变量发生变化了。
(4). 然后,new Vue()继续扫描el:"#app"所指向的页面元素,及其子元素。构建虚拟DOM树。
Axios 是一个异步请求技术,核心作用就是用来在页面中发送异步请求,并获取对应数据在页面中渲染 页面局部更新技术
Axios异步请求
特点:
拦截请求和响应
转换请求数据和响应数据
自动转化JSON数据
什么是跨域
跨域是指一个域下的文档或脚本视图去请求另一个域下的资源,这里跨域是广义的
什么是同源策略?
协议+域名+端口三者相同,即便两个不同的域名指向同一个ip地址,也非同源(只存在于客户端(浏览器))
跨域解决方案
cors(跨域资源共享)
jsonp
iframe
nqinx代理跨域
nodejs中间件代理跨域
WebSocket协议跨域
token
HTTP协议下多次请求的状态管理
由于http协议属于短连接协议,所以每一次的请求会与服务端都是全新的请求(每个请求都是独立的)。服务端默认情况下不能将同一个客户端发送的多次请求当成一个整体来看待,导致同一个客户端涉及到的数据不能“通用”。
HTTP协议下多次请求的状态管理讲究的是服务端需要想办法将同一个客户端的多次请求涉及到的数据(比如:用户信息)存下来,使得同一个客户端发送的多次请求服务端可以当成一个整体来处理。
使用token的鉴权机制解决状态管理问题:
当登录成功后,从服务端获取登录成功后返回的结果,包含有token字符串、用户信息。需要显示用户信息,并且将token字符串保存在客户端供以后使用。
以后同一个客户端发送后续所有请求时,都需要携带token字符串一起发送请求。这样服务端就可以通过请求中的token解析后知晓登录用户是谁,从而完成后续业务。
当一个函数作为参数传入另一个函数中,并且它不会立即执行,只有当满足一定条件后该函数才可以执行,这种函数就称为回调函数。
异步任务
与之相对应的概念是“同步任务”,同步任务在主线程上排队执行,只有前一个任务执行完毕,才能执行下一个任务。
异步任务不进入主线程,而是进入异步队列,前一个任务是否执行完毕不影响下一个任务的执行。
回调地狱:在回调函数中再嵌套回调函数的情况称为回调地狱(是实现代码顺序执行的一种操作方式)
代码的可读性差、可维护性差
代码的扩展性差
回调地狱的问题:
.嵌套层次很深,可读性差,难以维护
.无法正常使用return 和throw
.无法正常检索堆栈信息
.多个回调之间难以建立联系
1)、Promise
2)、async/await
promise
Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。
Promise(承诺)对象有以下两个特点
对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,
只有两种可能:从pending变为fulfilled和从pending变为rejected。
只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。
如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。
这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
虚拟 DOM本质上就是一个普通的 JS 对象,用于描述视图的界面结构
在 vue 中,每个组件都有一个 rende r函数,每个 render 函数都会返回一个虚拟 DOM 树,这也就意味着每个组件都对应一棵虚拟 DOM 树
在 vue 中,渲染视图会调用 render 函数,这种渲染不仅发生在组件创建时,同时发生在视图依赖的数据更新时。
如果在渲染时,直接使用真实 DOM,由于真实 DOM 的创建、更新、插入等操作会带来大量的性能损耗,从而就会极大的降低渲染效率。
因此,vue 在渲染时,使用虚拟 DOM来替代真实 DOM,主要为解决渲染效率的问题。
在一个组件实例首次被渲染时,它先生成虚拟 DOM 树,然后根据虚拟 DOM 树创建真实 DOM,并把真实 DOM 挂载到页面中合适的位置,此时,每个虚拟 DOM 便会对应一个真实的 DOM。
1、 如果一个组件受响应式数据变化的影响,需要重新渲染时,它仍然会重新调用 render 函数,创建出一个新的虚拟 DOM 树,用新树和旧树对比,
通过对比,vue 会找到最小更新量,然后更新必要的真实 DOM 节点
这样一来,就保证了对真实 DOM 达到最小的改动。
vue 框架中有一个 compile 模块,它主要负责将模板转换为 render 函数,而 render 函数调用后将得到虚拟 DOM。
编译的过程分两步:
将模板字符串转换成为 AST(抽象语法树)
将 AST 转换为 render 函数
如果使用传统的引入方式,则编译时间发生在组件第一次加载时,这称之为运行时编译。
如果是在 vue-cli 的默认配置下,编译发生在打包时,这称之为模板预编译。
编译是一个极其耗费性能的操作,预编译可以有效的提高运行时的性能,而且,由于运行的时候已不需要编译,vue-cli 在打包时会排除掉 vue 中的 compile 模块,以减少打包体积
模板的存在,仅仅是为了让开发人员更加方便的书写界面代码
vue 最终运行的时候,最终需要的是 rende r函数,而不是模板,因此,模板中的各种语法,在虚拟 DOM 中都是不存在的,它们都会变成虚拟 DOM 的配置
DOM 指的是文档对象模型。它指的是把文档当做一个对象,这个对象主要定义了外理网而内容的方法和接口
BOM 指的是浏览器对象模型,它指的是把浏览器当做一个对象来对待,这个对象主要定义了与浏览器进行交互的法和接口
所有的标签属性都可以在这个对象上找到
修改这个对象的属性会自动映射到标签身上
把网页内容当作对象来处理
document 对象
是 DOM 里提供的一个对象
所以它提供的属性和方法都是用来访问和操作网页内容的
例:document.write()
网页所有内容都在 document 里面
DOM同时两种事件模型:冒泡型事件和捕获型事件
事件最开始由最具体的元素接收(文档层次中嵌套最深的那个节点),然后逐级向上传播最不具体的节点(document)。
事件由最不具体的元素接收,最后传播至最具体的元素。addEventListener添加事件侦听器
浅拷贝 :只复制指向某个对象的指针,而不复制对象本身,相当于是新建了一个对象,该对象复制了原对象的指针,新旧对象还是共用一个内存块
深拷贝:是新建一个一模一样的对象,该对象与原对象不共享内存,修改新对象也不会影响原对象
arguments 是一个类数组对象。用来实现函数重载
本质:类数组是简单对象,它的原型关系与数组不同。
相同点:
都可用下标索引访问每个元素
都有length属性
不同点:
数组对象类型为Array,遍历数组可以用for…in…和for循环
类数组对象类型为Object,遍历类数组只能用for循环,没有普通数组的API
重载就是函数的一种特性或者方法,使用它可以减少函数名的数量,避免名字空间的占用,
用编程语言说就是定义多个同名的函数,每一个函数接收的参数的个数不同,程序会根据调用时传递的实参个数进行判断,调用那个参数相同的函数来使用,
在JavaScript中是没有重载的,但是我们可以使用其他的一些方法来模拟重载。
//定义三个add函数,函数的名称相同,但是形参的个数不同
function add(a,b){return a + b; //返回 a+b}
function add(a,b,c){return a + b + c;//返回 a+b+c}
function add(a,b,c,d){return a + b + c + d;//返回 a+b+c+d}
//调用函数 - 传递参数
console.log(add(1,2));//结果为NaN
console.log(add(1,2,3));//结果为NaN
console.log(add(1,2,3,4));//结果为10
为什么结果得到两个NaN,一个10呢,因为在JavaScript中如果定义多个同名的函数,只有最后一个定义是有效的
怎样去模拟实现函数的重载
我们要用到一个arguments对象,它是一个类数组对象,作用就是传给function一个参数列表
//创建一个add函数,设置四个形参a,b,c,d
function add(a,b,c,d){
console.log(arguments);//直接输出arguments
}
add(1,2,3,4);
//传递四个实参我们会得到[object Arguments]: {0: 1, 1: 2, 2: 3, 3: 4}
//我们能看到结果非常像一个数组,但它不是一个数组,
//结果看见arguments有索引值我们还可以这么使用
function fn(a,b,c,d){
console.log(arguments[2]);//添加一个索引值
}
fn(1,2,3,4);//3
当我们了解了arguments对象的使用方法就可以模拟函数的重载效果了
//模拟函数的重载效果
//定义一个add的函数
function add(){
//声明一个len局部变量获取arguments的长度
var len = arguments.length;
switch(len){//使用switch语句依次去比较arguments的参数
case 2:
return arguments[0] + arguments[1];
case 3:
return arguments[0] + arguments[1] + arguments[2];
case 4:
return arguments[0] + arguments[1] + arguments[2] + arguments[3];
break;
}
}
//输出得到结果就可以实现函数的重载了
console.log(add(1,2));//3
console.log(add(1,2,3));//6
console.log(add(1,2,3,4));//10
路由传参query(path是路由地址,query是需要传递的参数)
goDetail() {
this.$router.push({
path: “/publish”,
query: {
roleName: “admin”,
id: 1,
},
});
},
如果传入的参数存在对象,则必须转成JSON字符串传入,接收的时候再转换
goDetail() {
let arr = [{name:“admin”,value:111},{name:“admin2”,value:222}]
this.KaTeX parse error: Expected 'EOF', got '}' at position 137: … }, }); }̲, 路由传参params(na…router.push({
name: “publish”,
params: {
roleName: “admin”,
id: 1,
},
});
},
注意:params传参刷新页面的时候会丢失数据,解决方法是在路由的配置文件里给该路由后面拼接需要的参数
{
path: “/Publish/:roleName/:id”,//:roleName与:id之间的/可以省略,看自己喜好
name: “publish”,
component:import(“…/components/PublishApp”),
},
接收路由参数:
1.query的接收方式:
//参数不存在对象时
created() {
console.log(this.KaTeX parse error: Expected 'EOF', got '}' at position 16: route.query) }̲, //参数存在对象时,只能单…route.query.roleName));
},
2.params的接收方式:
created() {
console.log(this.$route.params);
},
注意:
1.query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会再地址栏中显示;
2.如果用params又不想刷新后丢失参数,只能拼在路由path后面;
3.个人觉得用params把参数拼在路由后面比query好看很多;
4.params想携带数组对象这些类型的数据,又不想刷新后丢失,存为当地存储localserve
router为VueRouter的实例,相当于一个全局的路由器对象,里面含有很多属性和子对象,例如history对象。经常用的跳转链接就可以用this.$router.push,和router-link跳转一样。
r o u t e r 是路由管理器,管理了所有的路由对象。 router 是路由管理器,管理了所有的路由对象。 router是路由管理器,管理了所有的路由对象。router 提供了路由管理器所拥有的属性和方法,跳转页面等功能。
route相当于当前正在跳转的路由对象。每一个路由都会有一个router对象,可以从里面获取name,path,params等
在 vue 组件中通过 this.$route 可以获取当前组件所对应的路由对象(相当于router/index.js 中定义的一段配置:{path,name,component})。
$route 封装当前路由的属性:name、path、component、query、param 等属性。
slot就是插槽,主要的作用就是拓展组件,在重复使用一个组件的时候可以通过少量的修改就达到复用的效果。分成默认插槽、具名插槽和作用域插槽。其中前两个都是元素在父组件中,拓展的结构也在父组件中,直接在子组件中占位,在父组件中添加结构即可,区别就是具名插槽给插槽取了名字,多个插槽存在时可以一一对应。而作用域插槽的数据在子组件中,扩展的结构要在父组件中,这是就要利用slot进行子===>父的通信,给数据一个新的作用域,因此叫做作用域插槽。
使用场景
通过插槽可以让用户拓展组件,去更好地复用组件和对其做定制化处理;
如果父组件在使用到一个复用组件的时候,这个组件在不同的地方有少量的更改,如果去重写组件是很浪费,这时,通过slot插槽向组件内部指定位置传递内容,完成这个复用组件在不同场景的应用。
比如:布局组件、表格列、下拉选项、弹框显示内容等。
1、stop:阻止事件冒泡,顺序是执行顺序是div>body>document,js默认开启事件冒泡。e.stopPropagation()、e.stopImmediatePropagation() 阻止改dom所有该类型事件的冒泡。
2、self:阻止事件冒泡&&阻止事件捕获,div>body>document,document>body>div,默认是冒泡。
3、capture: 开启事件捕获,写在需要捕获的元素上,他会捕获内部元素的同类型事件 document>body>div // 默认关闭事件捕获,开启事件冒泡。addEventListener(“click”, this.Parent, {capture:true}); capture,true开启,反之关闭
4、once: 事件只触发一次就会被移除。addEventListener(“click”, this.Parent, {once:true}); once,true开启,反之关闭
5、prevent: 阻止事件的默认行为 e.preventDefault() e.defaultPrevented 查看默认阻止的状态,true:已阻止。addEventListener(“click”, this.Parent, {passive:true}); passive,true:阻止preventDefault函数调用,反之不阻止
6、native: 事件直接绑定到组件的原生节点上,
7、lazy: vue v-model 修饰符。修改语法糖的input事件为change。
8、number: vue 修饰符。把值转换为number类型。
9、trim: vue 修饰符。去除数值前后空格。
$ref
一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例。
ref
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,
当 v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。
关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。