JavaScript
- JS 特点
- 不主动开启新的线程的情况下单线程
- 如何开启新线程 var worker=new Worker('js 文件路径')
- js 是弱类型语言 所有的声明都是通过 var 在赋值的时候会自动转换
- js 不是编程语言,是脚本语言
- 解释型 由 js 引擎解析执行 chromeV8
- 动态类型:代码执行到变量声明的位置才知道该变量具体的值,而且这个值的类型可以随意更换
- 基于对象,js 是一门基于对象的语言,模拟了面向对象的思想
- 不主动开启新的线程的情况下单线程
原型和原型链
- 原型
- 在 JavaScript 中每个函数都有自己的属性,都有一个特殊的属性 prototype
- 每个 prototype 原型都有一个 constructor 属性,指向它关联的构造函数
- 原型就是一个为实例对象定义了一些公共属性和公共方法的对象模板
- 每个函数都有一个 prototype 属性,被称为显示原型
- 每个实例对象都会有一个** proto **属性,被称为隐式原型
- 在 JavaScript 中每个函数都有自己的属性,都有一个特殊的属性 prototype
- 原型链
- 在获取对象的属性时,如果对象本身没有这个属性,那就会去他的原型上去找,如果还查不到就去它原型的原型上去找,直到找到最外层为止,这个链式过程称之为原型链(说白了就是原型对象创建过程的历史记录)
在 javascript 中,所有的对象都拥有一个proto属性指向该对象的原型
-
关系
- 构造函数的 prototype 指向其原型对象
- 原型对象的 constructor 指向其构造函数
- 使用 new 关键字实例化构造函数
- 实例化对象的proto指向其原始的原型对象。
-
原型作用
- 存放所有实例对象需要数据共享(属性或方法),
- 节省了内存空间,
- 避免了全局污染
闭包
-
闭包就是一个能够读取外层函数内部变量的函数(可以在内部函数访问到外部函数作用域。)
-
为什么要使用闭包
- 使用闭包,一可以读取函数中的变量,二可以将函数中的变量存储在内存中,保护变量不被污染。
-
闭包的两种形式
- 函数做为返回值的形式
- 函数作为参数的形式
-
闭包的使用场景
- 封装功能时(需要使用私有的属性和方法),
- 函数防抖、函数节流
- 单例模式
-
优点:可以重复使用变量,且不造成变量污染
-
缺点:增加常驻内存, 容易造成内存泄漏
作用域
- 全局作用域:最外层函数定义的变量拥有全局作用域,即对任何内部函数来说,都是可以访问的;
- 局部作用域:局部作用域一般只在固定的代码片段内可访问到,而对于函数外部是无法访问的,最常见的例如函数内部。
作用域链
- 当查找变量的时候,会先从当前作用域的变量对象中查找,如果没有找到,就会从父级作用域(上层环境)的变量对象中查找,一直找到全局作用域的变量对象,也就是全局对象。这样由多个作用域的变量对象构成的链表就叫做作用域链。
this 指向
- 普通函数中调用,this 指向 window
- 对象方法中调用,this 指向当前对象
- call apply bind 中调用, this 指向被传入的对象
- class 中的方法中调用, this 指向实例对象
- 箭头函数,this 就是父级上下文中的 this
同步异步
-
主线程任务——>微任务——>宏任务
- 主线程任务——>微任务——>宏任务——>宏任务里的微任务——>宏任务里的微任务中的宏任务——>知道任务全部完成
所有任务都在一个主线程上执行形成一个执行栈
在执行过程中发现异步任务,如果是微任务就把他放在微任务的消息队列里,如果是宏任务就把他放在宏任务的消息队列中,
等执行栈上的同步任务执行完后
执行微任务然后在执行宏任务
-
异步和同步的区别:
- 异步不会阻塞程序的执行,
- 同步会阻塞程序的执行,
-
前端使用异步的场景:
- 定时任务:setTimeout,setInverval
- 网络请求:ajax 请求,动态加载
- 事件绑定
-
宏任务包括:setTimeout、setInterval、Ajax、DOM 事件
-
微任务:Promise、async/await
-
微任务比宏任务的执行时间要早
数据类型的判断
- typeof 主要用来检测基础数据类型
- instanceof 用于检测构造函数中的原型(prototype)属性是否出现在某个实例对象的原型链上
- constructor 用于检测实例对象是否由某个构造函数实例化出来的
- Object.prototype.toString.cal()
- 适用于所有类型
- 检测对象的时候不用加 call 也可以
- 别的数据类型必须用 call,否则的话就变成了转成字符串的方法了
数组排序
-
冒泡排序
- 将数组中的相邻两个元素进行比较,将比较大(较小)的数通过两两比较移动到数组末尾(开始),执行一遍内层循环,确定一个最大(最小)的数,外层循环从数组末尾(开始)遍历到开始(末尾)
-
插入排序法(插队排序)
- 将要排序的数组分成两部分,每次从后面的部分取出索引最小的元素插入到前一部分的适当位置
-
快速排序
- 实现思路是,将一个数组的排序问题看成是两个小数组的排序问题,以一个数为基准(中间的数),比基准小的放到左边,比基准大的放到右边,而每个小的数组又可以继续看成更小的两个数组,一直递归下去,直到数组长度大小最大为 2。
深浅拷贝
- 深拷贝和浅拷贝的区别
-
浅拷贝: 将原对象或原数组的引用直接赋给新对象/新数组,新对象/数组只是原对象的一个引用
-
深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”
-
为什么要使用深拷贝?
- 我们希望在改变新的数组(对象)的时候,不改变原数组(对象)
-
浅拷贝
- 数组的浅拷贝
- 直接遍历
- slice()
- concat()
- 对象的浅拷贝
- 直接遍历
- ES6 的 Object.assign
- ES6 扩展运算符
- 数组的浅拷贝
-
深拷贝
- 先转换成字符串,在转换成(数组/对象) JSON.parse(JSON.stringify(XXXX))
- 递归
- jQuery 的 extend 方法
null 和 undefind 的区别
-
在 if 语句中 null 和 undefined 都会转为 false 两者用相等运算符比较也是相等
-
null 表示没有对象,可能将来要赋值一个对象,即该处不应该有值
-
undefined 表示缺少值,即此处应该有值,但没有定义
继承
-
原型链继承
- 父类的实例作为子类的原型
-
借用构造函数继承
- 复制父类的实例属性给子类
-
组合式继承
- 调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用
-
es5 和 es6 继承的区别
- ES5 的继承是通过原型或构造函数机制实现的;它先创建子类,再实例化父类并添加到子类 this 中。
- ES6 先创建父类,再实例化子集中通过调用 super 方法访问父级后,再通过修改 this 实现继承。
js 中事件委托
-
事件委托,又名事件代理。事件委托就是利用事件冒泡,就是把子元素的事件都绑定到父元素上。如果子元素阻止了事件冒泡,那么委托也就没法实现了。
-
好处:提高性能,减少了事件绑定,从而减少内存占用
-
应用场景 在 vue 中事件委托
- 我们经常遇到 vue 中 v-for 一个列表,列表的每一项都绑定了@click 处理事件。我们都知道绑定这么多监听,从性能方面来说是不太好的。那我们我们可以通过把每个 item 的 click 事件委托给父元素的形式来实现。
事件绑定、事件传播、事件捕获、事件冒泡、自定义事件
-
DOM 事件三种级别
-
DOM0 级事件
- 一是直接在标签内直接添加执行语句
- 二是定义执行函数。
-
DOM2 级事件
- 第一个参数:事件名称
- 第二个参数:执行函数
- 第三个参数:指定冒泡还是捕获,默认是 false,冒泡。
element.addEventListener("click", function () {}, false);
- DOM3 级事件
- 同 DOM2 级一样,只不过添加了更多的事件类型,鼠标事件、键盘事件。
element.addEventListener("keyup", function () {}, false);
-
-
DOM 事件两种类型
- 事件类型分两种:事件捕获、事件冒泡。
- 事件捕获就是由外往内,从事件发生的顶点开始,逐级往下查找,一直到目标元素。
- 事件冒泡就是由内往外,从具体的目标节点元素触发,逐级向上传递,直到根节点。
- 事件类型分两种:事件捕获、事件冒泡。
-
DOM 事件的事件流(事件传播)
- 事件流就是,事件传播过程。
- DOM 完整的事件流包括三个阶段:事件捕获阶段、目标阶段和事件冒泡阶段。
-
事件捕获具体流程
- 当事件发生在 DOM 元素上时,该事件并不完全发生在那个元素上。在捕获阶段,事件从 window 开始,之后是 document 对象,一直到触发事件的元素。
-
事件冒泡具体流程
- 当事件发生在 DOM 元素上时,该事件并不完全发生在那个元素上。在冒泡阶段,事件冒泡,或者事件发生在它的父代,祖父母,直到到达 window 为止。
- 阻止事件冒泡:事件对象.stopPropagation()
可以通过 new Event()自定义事件
Ajax 创建流程
-
创建流程
- 创建 xhr 核心对象
var xhr = new XMLHttpRequest();
- 调用 open 准备发送
- 参数一:请求方式
- 参数二: 请求地址
- 参数三:true 异步,false 同步
xhr.open("post", "http://www.baidu.com/api/search", true);
- 如果是 post 请求,必须设置请求头。
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
- 调用 send 发送请求 (如果不需要参数,就写 null)
xhr.send("user=tom&age=10&sex=女"); xhr.send(null);
- 监听异步回调 onreadystatechange
xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if(xhr.status==200){ console.log(xhr.responseText); var res=JSON.parse(xhr.responseText); console.log(res); if(res.code==1){ modal.modal('hide'); location.reload(); } } }
-
状态值:readyState
- 0:创建了 xhr 对象
- 1:与服务器建立了连接,向服务器发送数据
- 2:服务器开始接收数据
- 3:服务器接受完数据,开始处理数据
- 4:数据处理完成,js 可以调用处理的结果
-
status:状态码
- 200:请求成功
- 304:请求的文件没有修改,去本地缓存读数据
- 404:路径错误
- 403:权限(forbidden)
- 50x:服务器错误
-
状态码说明
- 1**:请求收到,继续处理
- 2**:操作成功收到,分析、接受
- 3**:完成此请求必须进一步处理
- 4**:请求包含一个错误语法或不能完成
- 5**:服务器执行一个完全有效请求失败
jsonp 原理
-
jsonp 是一种跨域通信的手段,它的原理其实很简单:
- 首先是利用 script 标签的 src 属性来实现跨域。
- 通过将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,实现服务器端向客户端通信。
- 由于使用 script 标签的 src 属性,因此只支持 get 方法
cookie、localStorage、sessionStorage 区别
- cookie
- Cookie 设计初衷是用来和服务器通讯,而不是本地存储,他只是被‘借用’到本地存储。
- cookie 的缺点
- 存储大小,最大 4kb
- http 请求时需要发送到服务端,增加请求数据量
- 只能用 document.cookie = '...' 来修改,太过丑陋
在HTML5中,新加入了一个localStorage/sessionStorage特性
这个特性主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题
(cookie中每条cookie的存储空间为4k),localStorage中一般浏览器支持的是5M大小。
-
localStorage、sessionStorage 与 cookie 相比:
- html5 专门为存储而设计,最大可存 5M
- API 简单易用 setItem、getItem
- 不会随着 http 请求被发送出去
-
localStorage、sessionStorage 不同点
- localStorage 数据会永久存储,除非代码或手动删除
- sessionStorage 数据只存在于当前会话,浏览器关闭则清空
- 一般用 localStorage 会更多
localStorage只支持string类型的存储。
let、const、var 的区别
-
- 是否存在变量提升
- var 声明的变量存在变量提升(将变量提升到当前作用域的顶部)。即变量可以在声明之前调用,值为 undefined。
- let 和 const 不存在变量提升。即它们所声明的变量一定要在声明后使用,否则报 ReferenceError 错。
-
- 是否存在暂时性死区
- let 和 const 存在暂时性死区。即只要块级作用域内存在 let 命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
- 在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和用该变量。
-
- 是否允许重复声明变量
- var 允许重复声明变量。
- let 和 const 在同一作用域不允许重复声明变量。
-
- 是否存在块级作用域
- var 不存在块级作用域。
- let 和 const 存在块级作用域。
d
-
- 是否能修改声明的变量
- var 和 let 可以。
- const 声明一个只读的常量。一旦声明,常量的值就不能改变。const 声明的变量不得改变值,这意味着,const 一旦声明变量,就必须立即初始化,不能留到以后赋值。
var存在变量提升,let和const不存在变量提升
var不存在暂时性死区,let和const存在暂时性死区
var和let可以修改声明的变量,const不能修改声明的变量
var可以重复声明,let和const不能重复声明
箭头函数与普通函数区别
- 箭头函数是匿名函数,不能作为构造函数,不能使用 new
- 箭头函数内没有 arguments,可以用展开运算符...解决
- 箭头函数的 this,始终指向父级上下文
- 箭头函数不能修改 this 指向。
节流和防抖
-
节流是指当一个事件触发的时候,为防止事件的连续频繁触发,设置定时器,达到一种一段事件内只触发一次的效果,在 当前事件内不会再次触发,当前事件结束以后,再次触发才有效.
-
防抖是指当一个事件触发的时候, 为防止频繁触发事件, 设置定时器,以达到一种 频繁触发期间不处理, 只有当最后 一次连续触发结束以后才处理
Promise
-
什么是 Promise
-
- Promise 是 ES6 自带的构造方法
-
- Promise 用于处理异步编程
-
-
Promise 构造函数的使用
- new Promise(fn)
- fn 是一个立即执行的函数,因此它的内容是同步执行的
- fn 的形式为 function(resolve, reject) {}
- resolve 在成功时调用,并传值,将 promise 状态更改为成功
- reject 在失败时调用,并传错误原因,将 promise 状态更改为失败
-
Promise 实例状态特点
-
三种状态
- pending - 进行中,悬而未决(也是初始状态)
- fulfilled - 满足条件,成功
- rejected - 被抛弃,失败
-
promise 的状态只能改变一次,且只能从 pending->fulfilled 或 pending->rejected,没有其他转化可能性
-
-
Promise 实例的方法
- .then(successFn, failedFn) - fulfilled 时进入 successFn 或 rejected 时进入 failedFn
- .catch(failedFn) - rejected 时进入回调函数
- .finally(fn) - 无论结果是 fulfilled 或者是 rejected,都会执行指定的回调函数
- then / catch / finally 返回新 promise
- 回调函数里 return 的时候,则成功
- 在 return 中返回另一个 promise,下一次 then 的时候得到的值是这个 promise 状态改变后的值
- 回调函数里 throw 的时候,则失败
-
Promise.resolve(v)
- 返回一个成功的 Promise 实例,用 v 作为 promise 的值
-
Promise.reject(e)
- 返回一个失败的 Promise 实例,用 e 作为 promise 的错误
axios
- axios 是一个基于 Promise 的方法,可以发送 get、post 等请求,并且前后端都可以使用。
js 设计模式
- 共 23 种设计模式,介绍其中 6 种应用较为广泛的模式。
发布订阅模式:
这种设计模式可以大大降低程序模块之间的耦合度,便于更加灵活的扩展和维护。
中介者模式 :
观察者模式通过维护一堆列表来管理对象间的多对多关系,中介者模式通过统一接口来维护一对多
关系,且通信者之间不需要知道彼此之间的关系,只需要约定好 API 即可。
代理模式 :
为其他对象提供一种代理以控制对这个对象的访问。
代理模式使得代理对象控制具体对象的引用。代理几乎可以是任何对象:文件,资源,内存中的对
象,或者是一些难以复制的东西。
单例模式 :
保证一个类只有一个实例,并提供一个访问它的全局访问点(调用一个类,任何时候返回的都是同
一个实例)。
工厂模式 :
工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一
个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型
装饰者模式 : 装饰者(decorator)模式能够在不改变对象自身的基础上,在程序运行期间给对像动态的
添加职责(方法或属性)。与继承相比,装饰者是一种更轻便灵活的做法。
因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,
如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,
是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
- 观察者、订阅者模式
- vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
<
- vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
面向对象和面向过程
-
区别
- 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可 以了;
- 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在 整个解决问题的步骤中的行为。
-
面向过程
- 优点:
- 性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;
- 比如单片机、嵌入式开发、 Linux/Unix 等一般采用面向过程开发,性能是最重要的因素。
- 缺点:没有面向对象易维护、易复用、易扩展
- 优点:
-
面向对象
- 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更 加灵活、更加易于维护
- 缺点:性能比面向过程低
面向对象的三大特征:封装、继承(通过原型模拟继承)、多态(类与类之间的关系,同一个事物在不同环境的不同表现形式,父类引用指向子类对象)
Vue
- vue 是渐进式框架
- 采用双向数据流
- 属于 MVVM 框架
- Vue 的优点:易用、灵活、高效
- vue.js 的两个核心
- 双向数据绑定。
- 组件系统。
Vue 中的 MVVM
-
MVVM 与 MVC 的区别
-
MVC 框架
- M:model 数据层 处理数据的逻辑,负责在数据库中存数据
- V:view 视图层 处理数据的显示 渲染
- C:controller 控制器 应用程序的交互部分,在视图层去读数据,向数据层发送数据
-
MVC 通信流程:
- 1、视图层接收到用户传入的数据,传送指令给控制器
- 2、控制器完成一些业务逻辑,要求数据层去改变数据状态
- 3、数据层将新的数据发送给视图层,用户得到最终反馈
-
采用的单向数据流
-
MVC 局限性:
- 1、view 层包含一些业务逻辑
- 2、view 层中的业务逻辑。无法复用
- 3、数据层的代码越来越少。控制器的代码越来越多
-
MVVM 是最早是有由微软提出的,视图层和数据完全分离
- M:model 数据层
- V:view 视图层
- 高效 vw:viewModel 视图模型号 V 和 M 之间的一个通信桥梁
-
MVVM 通信流程:
- 1、通过数据绑定将数据层到的内容渲染到视图层
- 2、再通过 DOM 监听,监听视图层的改变,一旦视图层改变
- 3、将视图层内容发送给数据层
-
采用的双向数据流
-
MVVM框架:angular Vue
MVC框架:react
- 什么是 MVVM 框架
- 是一个结合 MVC 及 MVP 的双向数据流框架,m 表示数据层,v 表示视图层,vm 表示视图模型层,vm 中通过数据绑定可以将数据层的数据绑定到视图中,在利用 DOM 监听,获取视图层变化从而更新数据
Vue 的响应式原理是什么
- vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个数据的 setter 和 getter ,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图
Vue 中的指令
- v-model 多用于表单元素实现双向数据绑定
- v-for 格式: v-for="(item,index) in/of 数组 json" 循环数组或 json
- v-show 显示内容 ,通过 display=block/none 来控制元素隐藏出现
- v-hide 隐藏内容 同上
- v-if 显示与隐藏 (dom 元素的删除添加 同 angular 中的 ng-if 默认值为 false)
- v-else-if 必须和 v-if 连用
- v-else 必须和 v-if 连用 不能单独使用 否则报错 模板编译错误
- v-bind 动态绑定 作用: 及时对页面的数据进行更改
- v-on:click 给标签绑定函数,可以缩写为@,例如绑定一个点击函数 函数必须写在 methods 里面
- v-text 解析文本
- v-html 解析 html 标签
- v-bind:class 三种绑定方法 1、对象型 ‘{red:isred}’ 2、三元型 ‘isred?“red”:“blue”’ 3、数组型 ‘[{red:“isred”},{blue:“isblue”}]’
- v-once 进入页面时 只渲染一次 不在进行渲染
- v-pre 把标签内部的元素原位输出
Vue 中 data 为什么是一个函数
- 因为对象是一个引用数据类型,而我们的组件是可复用的,一旦复用,对象的数据是直接引用对象地址,这样的话所有的组件数据会互通,一个改变另外的其他组件也会收到影响,不利于组件的复用,而如果将 data 改写成函数,返回一个新的对象,这种语法会让组件每一次使用的时候都生成一个数据自己的全新对象,这样每个组件中的数据一旦发生改变,其他组件不会收到任何影响,利于组件的复用
v-if 与 v-show 的区别
- 相同点
- 都可以动态控制着 dom 元素的显示隐藏
- 不同点
- v-if: 控制 DOM 元素的显示隐藏是将 DOM 元素整个添加或删除;
- v-show: 控制 DOM 的显示隐藏是为 DOM 元素添加 css 的样式 display,设置 none 或者是 block,DOM 元素是还存在的
- 性能消耗
- v-if 有更高的切换消耗;
- v-show 有更高的初始渲染消耗
- 使用场景
- v-if 适合运营条件不大可能改变的场景下;
- v-show 适合频繁切换;
生命周期函数
- Vue 生命周期分为 4 个大的阶段
- 初始化、挂载、更新、销毁 触发八个生命周期函数
- beforeCreate:初始化前 vue 实例开始准备加载 data/methods....
- created: 初始化后 vue 已经加载完 data/methods....进行网络请求
- beforeMount : 挂载前 将 vue 实例挂载到某个 DOM 元素前
- mounted : 挂载后 将 vue 实例挂载某个 DOM 元素完成,这时才可以对 DOM 进行操作
- beforeUpdate : 更新前
- updated : 更新后
- beforeDestroy : 销毁前 解除一些事件的绑定
- destroyed : 销毁后
什么是虚拟 DOM 及虚拟 DOM 的优点
- 通过 js 创建一个 Object 对象来模拟真实 DOM 结构,这个对象包含标签名(tag)、属性(attrs)、和子元素对象(children)三个属性,通过 vue 中的 render()函数把虚拟 DOM 编译成真实 DOM,再通过 appendChild()添加到页面中,vue 中的虚拟 DOM 最大的优势就是 diff 算法,减少 javascript 操作真实 DOM 带来的性能消耗
vue 中的 diff 算法
- diff 算法就是进行虚拟节点对比,并返回一个 patch 对象,用来存储两个节点不同的地方,最后用 patch 记录的消息去局部更新 Dom。
vue 组件之间的通信
-
父传子 :
- 在父组件中的子组件标签上写一个自定义属性
- 在子组件的配置项中添加一个 props 配置项
- 在 props 中接收自定义属性的值
- 在子组件中就可以使用 props 中的属性来拿到传递的值
-
子传父 :
- 子组件要触发一定的事件条件(在一个函数内部去向父组件传递数据)
- 在函数内部通过 this.$emit() 向父组件发出一个自定义事件 emit 方法中可以传递两个参数,第一个参数是自定义的事件名,第二个参数是传递给父组件的数据
- 在父组件中的子组件标签上,通过 v-on 来绑定子组件发出的自定义事件
- 为该自定义事件添加一个事件响应函数,该函数有一个默认参数,参数就是传递过来的值
-
非父子组件传值 :
- 创建一个 js 文件,在该文件中导出一个空的 vue 实例
- 需要在向外传递数据的组件中触发一个事件函数,并且需要导入 js 文件中的 vue 实例
- 在事件函数中通过 bus.$emit() 来进行自定义事件的发出
- 在需要接受数据的组件中,导入 js 文件中的 vue 实例
- 通过 bus.$on() 来触发自定义事件,从而拿到相应的数据 $on 方法 可以传递两个参数,第一个参数是自定义事件名,第二个参数回调函数,该回调函数有一个默认参数,就是传递过来的值
- 如果在组件中使用了$on绑定事件,最好是在组件销毁时,使用$off 将该事件进行解绑,这样可以减少内存的消耗
vuex
- Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它由五部分组成:
- state: 数据
- actions:可以包含异步操作
- mutations: 唯一可以修改 state 数据的场所
- getters: 类似于 vue 组件中的计算属性,对 state 数据进行计算(会被缓存)
- modules:模块化管理 store(仓库),每个模块拥有自己的 state、mutation、action、getter
在vuex官方建议,在组件中如果想要修改state中的数据,最好是通过dispatch调用actions中的方法,然后在actions的方法中通过聪commit调用mutations里面的方法,最后在mutations的方法中来修改state中的数据,不建议直接在组件中使用commit调用mutatios中的方法,这样无法使用then来回调接收判断是否vuex响应成功
- vuex 持久化数据
- 插件的使用 Vuex-persistedstate
- 安装:npm i vuex-persistedstate --save
路由
有道云笔记
v-for 为什么要绑定 key 值
- 在节点中如果为节点绑定了一个 key 值,那么这个 key 值会为这个节点绑定唯一的 id 标识,这也是 diff 算法的一种优化,可以根据 key 值,更准确,更快速的找到对应的节点,减少 DOM 的操作,优化页面的性能
不建议用 index 做 key 的原因是什么?key 的作用有哪些?
- 原因
- 用 index 作为 key 时,在对数据进行,逆序添加,逆序删除等破坏顺序的操作时,会产生没必要的真实 DOM 更新,从而导致效率低
- 作用
- key 是虚拟 DOM 对象的唯一标识
- 在 diff 算法中 key 起着极其重要的作用。
vue 路由里的$router和$route 的区别
- $router
- $router 是全局 router 的实例, 包含了一些路由的跳转方法 push, replace 等
- $route
- $route 是当前激活路由的信息对象。每个对象都是局部的,可以获取当前路由的 path, name, params, query 等属性
watch 和 computed 的区别?
- watch 没有缓存, computed 有缓存
- watch 可以监听异步, computed 无法监听异步数据变化
- watch 监听的数据发生变化时,立即触发回调函数; computed 只有依赖的数据变化时才会重新调用 getter
methods 和 computed 两者有什么异同
- 共同点: 两者内部书写的都是方法
- 不同点: computed 有缓存,多次调用只执行一次,而 methods 中没有缓存,多次调用会执行多次
组件中的插槽有几种及他们的使用场景是什么
-
插槽指允许将自定义的组件像普通标签一样插入内容
-
匿名插槽:将定义插槽的变量作用域到使用插槽中
-
具名插槽:给具体的插槽命名,并在使用的时候传入插槽的名称
-
作用域插槽:将定义插槽的变量作用域到使用插槽中
-
解构插槽
简述一下 mutations 和 actions 的区别
- mutations 是处理同步方法,actions 是处理异步方法,
- mutations 可以修改 state 状态,actions 不能修改,
- mutations 中第一个参数是 state,actions 中第一个参数是 vuex 的实例,
- mutations 中的方法中无法使用 then 来监听回调,actions 中的方法可以使用 then 来监听回调
路由的导航守卫有几种,分别有哪些钩子函数
有三种导航守卫:
-
全局路由守卫
- beforeEach():全局前置守卫,在进入到某一个路由之前会触发这个函数
- afterEach():全局后置守卫,在进入到某一个路由之后会触发这个函数
- beforeResolve():全局解析守卫,在进入到某一个路由之前,同时将进入到的路由组件解析完成后触发这个函数,类似于前置守卫
-
路由独享守卫
- beforeEnter():在进入到当前路由之前会触发这个函数
-
组件内的守卫
- beforeRouteEnter():在路由进入到该组件之前触发这个钩子函数
- beforeRouteUpdate():在路由的 url 路径上通过动态路由实现路径的变化,但是该组件重复复用时,会被触发。比如 home/张三跳转到 home/李四,这个时候函数会被触发
- beforeRouteLeave():在路由离开这个组件之前触发钩子函数
vue 中的自定义指令
-
全局指令: 通过 Vue.directive() 函数注册一个全局的指令。
-
局部指令:通过组件的 directives 属性,对该组件添加一个局部的指令。
-
自定义指令的钩子函数
- 一个指令定义对象可以提供如下几个钩子函数 (均为可选):
- bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
- update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 。
- componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
- 一个指令定义对象可以提供如下几个钩子函数 (均为可选):
-
钩子函数参数(即 el、binding、vnode 和 oldVnode)
- el:指令所绑定的元素,可以用来直接操作 DOM。
- binding:一个对象,包含以下 property:
- name:指令名,不包括 v- 前缀。
- value:指令的绑定值。
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression:字符串形式的指令表达式。
- arg:传给指令的参数。
- modifiers:一个包含修饰符的对象。
- vnode:Vue 编译生成的虚拟节点。
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。