目录
element.属性/element.getAttribute(‘属性’)
JavaScript
浏览器执行JS
- 渲染引擎:解析HTML与CSS,俗称内核。
- JS引擎:JS解释器,读取网页中的js代码,对其处理后运行。
- 浏览器本身并不会执行JS代码,通过内置JS引擎来执行JS代码,逐行解析。
JS的组成
- ECMAScript:javaScript语法,ECMAScript规定了JS的编程语法和基础核心知识。
- DOM:页面文档对象模型,通过DOM接口对页面上的各种元素进行操作
- BOM:浏览器对象模型,与浏览器窗口进行互动的对象结构,通过BOM可以操作浏览器窗口。
JS是什么语言
JS是一种弱类型或者说动态语言,这意味着不用提前声明变量的类型,类型会被自动确定。
JS八进制和十六进制
在JS中八进制前面加0,十六进制前面加0x
null/undefined
- null表示空的对象(该处的对象现在为空),空的值(该处的值现在为空),转为数值时为0。
- undefined表示未定义,没有赋值,转为数值时为NaN。
isNaN()
如果是数字返回false,如果不是数字返回true。
前置自增/后置自增
前置自增:先加1,后返回原值。
后置自增:先返回原值,后加1。
==/===
区别
- ==:类型自动转换并比较两个值是否相等。
- ===:不进行类型自动转换,比较两个值的类型和值是否完全相同。
用哪个
- ===不进行类型自动转换,因此更加严格和安全,建议使用。
- 明确知道两个值的类型,需要进行类型转换后再比较,使用==。
逻辑与
表达式1&&表达式2:
- 如果第一个表达式的值为真,则返回表达式2。
- 如果第一个表达式的值为假,则返回表达式1。
- 逻辑与的优先级要高于逻辑或。
Switch
变量和case里面的值必须是全等。
Array
可以把一组相关的数据一起存放。
JS作用域
就是代码名字在某个范围内起作用和效果,目的是为了提高程序的可靠性更重要的是减少命名冲突。
全局作用域/局部作用域
- 全局作用域:整个script标签或者是一个单独的js文件。
- 局部作用域:在函数内部就是局部作用域,这个代码的名字只在函数内部起效果和作用。
- 全局变量:在全局作用域下的变量,或者在函数内部没有声明的变量也属于全局变量。
- 局部变量:在局部作用域下的变量,或者在函数内部的变量就是局部变量。
- 全局变量只有浏览器关闭的时候才会销毁,比较占资源。
- 局部变量当我们程序执行完毕的就会销毁,比较节约内存资源。
- Js中没有块级作用域,在es6的时候新增块级作用域。
作用域链
内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值。就近原则。
JS预解析
- js引擎会把js里面所有的var和function提升到当前作用域的最前面,然后按照代码书写的顺序从上 往下执行。
- JS预解析分为变量预解析(变量提升)和函数预解析(函数提升)。
- 变量提升就是把所有变量声明提升到当前作用域最前面,不提升赋值操作。
- 函数提升就是把所有函数声明提升到当前作用域的最前面,不调用函数。
- 函数表达式调用必须写在函数表达式的下面。
- 预解析过程:先提升变量,然后提升函数,然后变量赋值,然后调用函数,函数内部也是先提升变量 然后输出。
JS执行机制
- 同步任务:同步任务都在主线程上执行,形成一个执行栈。
- 异步任务:JS的异步是通过回调函数实现的。
- 普通事件:click,resize等。
- 资源加载:load,error等。
- 定时器:setInterval,setTimeout等。
- 执行顺序:
- 先执行执行栈中的同步任务
- 异步任务(回调函数)放入任务队列中。
- 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
事件循环
同步任务进入主线程,异步任务进入任务队列。主线程内的任务执行完毕,会从任务队列读取对应的任务,推入主线程执行,上述过程的不断重复就是事件循环。
JS对象创建
一组无序的线性属性和方法的集合,字符串,数值,数组,函数都是对象。
- 字面量创建对象:{}。
- new Object()创建对象。
- 构造函数创建对象:把对象里面的一些相同的属性和方法抽象出来封装到函数里面。
- ES6中通过Class和constructor创建对象。
- 我们利用构造函数创建对象的过程也称为对象的实例化
new关键字执行过程
- new构造函数可以在内存中创建一个空对象。
- this就会指向刚才创建的空对象。
- 执行构造函数里面的代码给这个空对象添加属性和方法。
- 返回这个对象。
内置对象/浏览器对象
内置对象:Math,Date,Array,String,Number,Boolean,Object,Error,Global,Function,RegExp。
浏览器对象:Window,Navigator,Screen,History,Location。
数组常用方法
- slice:截取原数组的一部分,返回一个新数组,原数组不变。
- splice:删除原数组的一部分,并且可以在删除的位置添加新的数组成员,返回被删除的元素 数组,原数组会改变。
- push,pop,unshift,shift,concat,filter,map,forEache,join,sort,reverse。
基本包装类型
就是把简单数据类型包装成了复杂数据类型。
字符串
- 字符串具有不可变性,看上去是可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
- 字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串。
字符串常用方法
charAt,charCodeAt,str[index],concat,substr,slice,substring,replace,trim,trimStart,trimEnd,startWith,endWith。
值类型/引用类型
- 简单数据类型/基本数据类型,在存储变量中存储的是值本身,也叫值类型。String,number,boolean,undefined,null。null返回的是一个空的对象(object),如果有个变量我们打算存储对象,但是没想好就可以赋值null。
- 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此也叫做引用数据类型,通过 new关键字创建的对象(系统对象,自定义对象),如Object,Array,Date等。
- 简单数据类型是存放在栈里面,栈里面直接开辟一个空间存放的是值。
- 复杂数据类型首先在栈里面存放地址,十六进制表示,然后这个地址指向堆里面的数据。
prototype
prototype:每一个构造函数都有一个prototype属性,prototype就是一个对象,这个对象的所有属性和方法都会被构造函数所拥有。可以把不变的方法直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。prototype的所有属性和方法,都能被实例对象共享,可以用来做对象继承或者用来扩展内置对象。
原型链查找规则
- 访问对象的属性方法时,先找这个对象自身。
- 如果没有就找它的原型(也就是_proto_指向的prototype原型对象)。
- 如果还没有就找原型对象的原型(Object的原型对象)。
- 依次类推一直找到Objetct为止(null)。
- _proto_对象原型意义在于为对象成员查找机制提供一个方向,一条路线。
闭包
一个作用域可以访问另外一个函数内部的局部变量,可以用作延伸变量的作用范围。
call/apply/bind
call
理解
call用来指定函数内部的this指向。
应用场景
调用对象的原生方法。
apply
理解
apply用来指定函数内部的this指向,接收数组作为函数执行时的参数。
应用场景
- 找出数组最大元素。
- 将数组的空元素变为undefined。
- 转换类似数组的对象。
bind
bind用于将函数内部的this绑定到某个对象,然后返回一个新函数。
继承
- 使用原型链继承。
- ES6中使用class和extends。
浅拷贝/深拷贝
浅拷贝:只拷贝一层,深层次对象只拷贝引用,Object.assign(target,...sources)
深拷贝:拷贝多层,每一级别的数据都会拷贝,需要判断数据类型用到递归。
事件对象/事件源/事件类型
- 事件对象:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event。比如:键盘按键状态,鼠标的位置,鼠标按钮。
- 事件源:事件被触发的对象,例如按钮。
- 事件类型:如何触发,什么事件,比如鼠标点击(onclick)还是鼠标经过,还是键盘按下。
- 事件处理程序:通过一个函数赋值的方式完成。
innerText/innerHTML
innerText不识别html标签,去除空格和换行
innerHTML识别html标签,保留空格和换行
this
this指向的是事件函数的调用者。
js修改Style
js修改style样式操作,产生的是行内样式,CSS权重比较高。
element.属性/element.getAttribute(‘属性’)
- element.属性:获取内置属性值(元素本身自带的属性)。
- element.getAttribute(‘属性’):主要获得自定义的属性(标准)和我们程序员自定义的属性。
事件冒泡/事件捕获
- 事件冒泡:事件开始由最具体的元素接受,然后逐级向上传播到DOM最顶层节点。
- 事件捕获:由DOM最顶层节点开始,逐级向下传播到最具体的元素接受。
- e.target:点击了哪个元素,就返回哪个元素的。
- this:哪个元素绑定了这个点击事件,那么就返回谁。
- e.stopPropagation():阻止冒泡。
Load/DOMContentLoaded
Load:等页面内容全部加载完毕,包含页面dom元素,图片,flash,css等等。
DOMContentLoaded:是DOM加载完毕,不包含图片,flash,css等就可以执行,加载速度比load更快一些。
setTimeout/setInterval
setTimeout():在定时器到期后执行调用函数。
setInterval():每隔一段时间,就去调用一次回调函数。
Promise
是什么
Promis是一种用于处理异步操作的对象,代表一个尚未完成但是最终会完成或失败的操作,并且允许你在其完成或失败之后继续执行代码,类似于C#中的Task。
为什么用
- JavaScript执行的时候,一次只能执行一个任务,会阻塞其它任务,这个缺陷导致JavaScript的所有网络操作,浏览器事件都必须是异步执行,异步执行可以使用回调函数执行。
- 常见的异步模式有定时器,接口调用,事件函数。
- ajax可能有多个网络请求是关联的,先执行第一个请求返回结果后,第一个返回结果作为第二个请求 的参数,调用第二个网路请求。如果业务复杂,网路请求太多时,回调也很多,会容易出现回调地狱。
- Promise专门解决异步的回调地狱问题。
pending/fulfilled/rejected
- pending:进行中,表示Promise还在执行阶段,没有执行完成。
- fulfilled:成功状态,表示Promise成功执行完成。
- rejected:拒绝状态,表示Promise执行被拒绝,也是失败。
resolve/reject
- resolve():把Promise的状态从进行中pending变为成功状态fulfilled。
- reject():把Promise的状态从进行中pending变为拒绝状态rejected。
then/catch
then
执行resolve时,Promise状态变为fulfilled,会执行then方法,then方法接受的参数也是一个函数,函数中携带一个参数,该参数是resolve(res)返回的数据。
catch
执行reject时,Promise 状态从pending变为rejected,会执行catch方法,catch方法接收的也是一个函数,函数中携带一个参数,该参数是reject(err)返回的数据。
all
Promise.all()方法,提供了并行执行异步操作的能力,并且在所有异步操作完成之后,统一返回所有结果。
嵌套简写
- Promise和resolve()简写,直接return。
- Promise和reject()简写,直接throw。
async/await
- async/await是用于处理异步操作的语法糖。
- async用于定义一个函数是异步的,当函数被标记为async时,它将返回一个Promise对象,无论实际返回值什么。async函数内部可以使用await关键字来暂停函数的执行,直到一个Promise完成并返回 结果。
- await关键字只能在async函数内部使用,它用于等待一个Promise对象完成,并且暂停async函数的执行,直到Promise对象状态变为resolved(已完成)或rejected(已失败)。
防抖/节流
为什么要防抖节流
限制JS代码频发执行。
防抖
- 单位时间内触发多次,最后一次生效。
- 做法:每次触发函数清除原来的定时器,重新开始计时。
节流
- 单位时间内,只触发一次。
- 做法:触发函数时判断是否到达了指定时间,如果到达了则执行,否则不执行。
- 时间戳法:
- 定时器法:
应用场景
- 防抖:搜索的时候会出现搜索提示,即通过input事件发送请求数据,这是一个很频繁的请求,防止用户在输入过程中发送请求,在停顿或停止的时候请求一下数据。
- 节流:鼠标不断触发某事件时,如点击,只在单位时间内触发一次。
SessinStorage/LocalStorage
本地存储特性:
- 数据存储在用户浏览器中。
- 设置,读取方便,甚至页面刷新不丢失数据。
- 容量较大,sessionStorage约5M,localStorage约20M。
- 只能存储字符串,可以将对象JSON.stringify()编码后存储。
window.sessionStorage:
- 生命周期为关闭浏览器窗口。
- 在同一个窗口(页面)下数据可以共享。
- 以键值对的形式存储使用。
- 存储数据:sessionStorage.SetItem(key,value)。
- 获取数据:sessionStorage.getItem(key)。
- 删除数据:sessionStorage.removeItem(key)。
- 删除所有数据:sessionStorage.clear()。
- 应用场景:敏感账号一次性登录。
window.localStorage:
- 生命周期为永久,除非手动删除,否则关闭页面也会存在。
- 可以多窗口(页面)共享(同一浏览器可以共享)。
- 以键值对的形式存储使用。
- 存储数据:localStorage.setItem(key,value)。
- 获取数据:localStorage.getItem(key)。
- 删除数据:localStorage.removeItem(key)。
- 删除所有数据:localStorage.clear()。
- 应用场景:长期登录,长期保存在本地的数据。
立即执行函数
立即执行函数最大的作用就是创建了一个独立的作用域。里面所有的变量都是局部变量,不会有命名冲突。
箭头函数中的this
理解
- 普通函数的this在全局作用域中指向全局对象,在对象方法中指向调用该方法的对象。
- 箭头函数没有自己的this,它会从最近的非箭头的父级作用域中继承this。
- 箭头函数的this在其定义时就确定了,无法通过call,apply,bind来改变。
示意图
forEach中的this指向
理解
foreEach中的this,在严格模式下,指向undefined。在非严格模式下,指向全局对象。
修正this指向
- 使用箭头函数。
- 使用bind绑定。
- 保存this到变量。
- forEach第二个参数绑定this。
Vue2
渐进式
可以将Vue作为你应用的一部分嵌入其中,带来更丰富的交互体验。
响应式
当数据发生改变的时候,界面会自动发生一些响应。
MVVM
理解
- ViewModel帮助Model和View通信,实现数据双向绑定。
- Data Bing:数据绑定,将Model的改变实时反应到View中。
- DOM Listener:Dom监听,DOM发生事件,可以监听到并改变对应的Data。
示意图
单向绑定
- 单向绑定是指把Model绑定到View上面,当更新Model的时候View就会自动更新。
- 插值形式{{}}和v-bind,都是单向绑定的体现形式。
双向绑定
- 双向绑定是指把Model绑定到View的同时也把View绑定到Model上面,使Model和View能够相互更新。
- v-model就是双向绑定的体现形式。
响应式
原理
动态添加对象属性,Vue无法渲染
- Vue只能追踪已经被初始化为响应式的数据属性,在创建Vue实例时,数据对象的属性必须要在data选项中进行初始化。
- 如果想动态添加属性并使其能够被Vue追踪和渲染出结果,可以使用Vue.set或者this.$set方法。
生命周期
理解
- 事物从诞生到消亡的整个过程。当Vue初始化的时候,执行到某一步的时候会对你自己定义的函数执行一个回调。
- Create:html模板渲染之前,这时候获取不到dom元素,通常初始化某些属性值,然后再渲染试图,视图渲染前前先获取下数据(ajax请求)。
- Mounted:html模板渲染之后,这时候可以获取到dom元素,通常是初始化页面完成之后,再对html的dom节点进行一些操作。视图渲染后初始化echarts实例。
示意图
$nextTick
理解
- Vue实现响应式并不是数据发生变化之后dom立即变化,而是按照一定的策略进行dom的更新。
- 当你想在改变dom元素的数据之后基于新的dom做点什么,那么对新dom的一系列js操作都需要放到$nextTick()的回调函数中。
- $nextTick()表示当数据更新了,并且在dom中渲染完成之后,自动执行该函数。
- 在created()进行dom操作一定要放在$nextTick()的回调函数中,因为在created()执行的时候dom其实并没有进行任何的渲染,此时进行dom操作无异于徒劳,所以此处一定要将dom操作的js代码放到$nextTick()的回调函数中,与之对应的就是mounted(),在mounted()执行的时候所有的dom挂载已经完成。
原理
- Vue是异步执行dom更新,一旦观察到数据变化,就会开启一个队列,然后把在同一个事件循环当中的watcher推送到这个队列。
- 如果watcher被触发多次,那么只会被推送到队列一次,这种缓冲行为可以有效的去掉重复数据造成的不必要计算和dom操作,而在下一个事件循环时,Vue会清空队列,并进行必要的dom更新。
- 为了在数据变化之后等待Vue完成dom更新,可以在数据变化之后立即使用Vue.nextTick(callback),这样回调函数在dom更新完成之后就会被调用。
示意图
$foreUpdate()
应用场景
如果直接添加或者修改data中的对象或者数组时,页面是不识别的,这个时候可以考虑使用$foreUpdate()。
示例
编译过程
- 初始化工作。
- 执行beforeCreated函数。
- 初始化data数据。
- 执行created函数。
- 判断是否传了el选项。
- 如果没传,等到vm主动调用$mount()再继续执行。
- 如果传了el,再判断是否传template模板选项。
- 如果没有传template,将el对应容器的所有内容,当成template。
- 将template通过render函数编译成虚拟DOM树。
变量作用域
变量在什么范围内是可用的。var是没有块级作用域。
虚拟Dom
在Vue中,当数据发生变化时,Vue会生成一个新的虚拟DOM并将其与之前的虚拟DOM进行比较。然后Vue会计算出需要进行的最小化的DOM操作,并将这些操作批量应用到真实的DOM上。这样就避免了频繁地直接操作真实DOM,提高了性能。
mustache语法
{{}},插值操作。
let/const
let:变量需要改变。let具有块级作用域。
const:变量不需要改变。
- const修改的标识符为常量,不可以再次赋值。
- const修饰的标识符必须赋值。
- 当我们修饰的标识符不会被再次赋值时,使用const来保证数据的安全性。
- 优先使用const,只有需要改变某一个标识符的时候才使用let。
常用属性
data为什么是一个函数
- 如果data是一个对象,那么所有实例将会共享相同的数据对象,这就会导致当一个实例的状态发生变化时,其它实例也会受到影响。
- data是函数,能确保每个实例都返回一个独立的数据对象,互不影响。每个实例都会调用该函数来获取独立的数据对象,从而保持各自的状态独立性。
computed
理解
计算属性,支持缓存,不支持异步,只有依赖数据发生变化,才会重新进行计算。
computed没有触发更新
- 在Vue中,如果直接修改数组中元素的属性而不改变数组本身,会导致computed属性没有正确地触 发更新。这是因为Vue默认只对整个数组地变化进行响应式处理。
- 如果需要在修改数组中元素地属性时触发computed属性更新,可以使用Vue.set方法或者使用扩展运算符创建新的数组来触发响应式更新。
watch
不支持缓存,支持异步操作,数据变化时执行异步或开销较大的操作,一般可以监听变量,数组,计算属性。
常用指令
v-on
v-for
1. 官方推荐在使用v-for时,给对应的元素或组件添加上一个Key属性为了更好的复用。
2. 使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
3. key的作用主要是为了高效的更新虚拟DOM。
v-model
v-model用于实现表单元素和数据的双向绑定,可以同时绑定输入框的值和数据对象中的属性,从视图到数据的变化会自动同步到数据对象,反之亦然。
v-if/v-show
区别
- v-if只有在表达式为真时才会渲染对应的元素,当表达式为假时,元素不会被渲染到DOM中。
- v-show不管表达式的值是真还是假,元素始终会被渲染到DOM中,只是通过设置CSS的display属性来控制是否显示。
应用场景
v-if适合那些很少发生切换的场景,v-show适合需要频繁切换显示/隐藏状态的场景。
v-if和v-for为什么不建议一起使用
原因
v-for比v-if具有更高的优先级,每次遍历重新渲染时都会对每个循环项的条件进行判断。
解决方案
- 使用元素包裹,将v-if和v-for放到不同的元素上面进行包裹。
- 使用计算属性,对数据进行过滤,然后只使用v-for渲染已经过滤的数据。
事件
wheel
理解
- wheel是一个DOM事件,它代表了鼠标滑轮滚动的事件。
- 在Vue中,可以通过在模板中使用@wheel来监听这个事件,然后在对应的方法中处理滚轮的滚动逻辑,比如垂直滚动条的滚动,放大缩小等操作。
鼠标滑轮垂直滚动
sync
理解
- .sync表示对prop进行”双向绑定”。
- Vue推荐在子组件中使用update:myPropName的方式向父组件传值。
- 在父组件中通过.sync修饰符,可以将@update删除,并且能直接修改父组件中变量的值。
示意图
组件
组件化
- 将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。
- 我们将一个完整的页面拆分成很多个组件。每个组件都用于实现页面的一个功能块。而每一个组件又可以进行细分。
组件化思想
- 它提供了一种抽象,让我们可以开发出一个独立可复用的小组件来构造我们的应用。
- 任何的应用都会被抽象成一颗组件树。
组件化思想的应用
尽可能的将页面拆分成一个个小的,可复用的组件。
组件如何使用
- 组件的使用分成三个步骤:1.创建组件构造器 2.注册组件 3.使用组件。
- Vue.extend():创建的是一个组件构造器。通常在创建组件构造器时,传入template代表我们自定义组件的模板。该模板就是在使用到组件的地方,要显示的HTML代码。
- Vue.component():将组件构造器注册为一个组件,并且给它起一个组件的标签名称。需要 传递两个参数:1.注册组件的标签名 2.组件构造器。
- Vue组件内部是不能访问Vue实例里面的数据的。
- Vue组件的数据存放在组件对象的data属性里面,这个data属性必须是一个函数,而且这个函数返回一个对象,对象内部保存着数据。如果data属性不是一个函数Vue直接就报错,Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象,组件在多次使用后会相互影响。
父子组件通信
- 父组件通过props向子组件传递数据。
- 子组件通过自定义事件向父组件发送消息。
- 父组件访问子组件:使用$children或者$refs。
- 子组件访问父组件:$parent。
子组件修改props
子组件避免修改props
Vue中,子组件应该尽量避免修改props属性值,因为props被设计为单向数据流,即父组件传递数据给子组件使用,不应该由子组件直接修改。这是为了保证数据流的清晰和可预测性。
解决方案
使用本地数据进行修改
可以将props的值赋给子组件中的变量,然后在子组件中修改本地变量而不影响父组件的props。
通过事件通知父组件
当子组件需要修改props的值时,可以触发自定义事件,让父组件处理相应的更新操作。
使用计算属性
在子组件内部使用计算属性对props的值进行加工处理,以便返回一个经过处理的新值。
使用watch监听props的变化
可以使用watch来监听props的变化,一旦变化就执行相应操作。
子组件动态绑定样式
通过props传递样式
通过计算属性传递样式
兄弟组件通信
EventBus
组件混入
- 全局混入:Vue.mixin()({}),全局混入只能定义Vue组件生命周期的属性或方法,定义其它属性或方法不生效。
- 组件混入:把功能注入到指定的组件,先把通用功能提取出来,然后再注入到需要的组件上。
组件扩展
extends,把两个组件的合并,组成新组件。
slot
- 插槽是让我们原来的设备具有更多的扩展性。把相同的东西进行封装,不同的东西使用插槽。父组件替换插槽的标签,但是内容由子组件来提供。
- 组件的插槽:
- 组件的插槽也是为了让我们封装的组件更加具有扩展性。
- 让使用者可以决定组件内部的一些内容到底展示什么。
编译作用域
父组件模板的所有东西都会在父级作用域内编译,子组件模板的所有东西都会在子级作用域内编译。父组件替换插槽的标签,但是内容由子组件来提供。
keep-alive
Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
深度选择器
是什么
- 当style标签有scoped属性时,它的CSS只作用于当前组件中的元素,父组件的样式不会渗透到子组 件。
- 在父组件scoped中根据子组件内部元素的类名修改子组件的样式,深度选择器可以使样式渗透到子组件。
怎么用
- ::v-deep:Vue3.0单文件规范中,会有警告。
- >>>:Sass,Less预处理器无法正确解析。
- /deep/:Vue3.0中,安装项目时选择了dart-sass,这个不支持/deep/和>>>。
- :deep():推荐写法。
CLI
命令行界面,俗称脚手架。
路由
前端路由
先通过js获取全部后端资源,然后通过前端路由,根据不同的url抽取全部资源里面的js代码渲染不同的页面。
$router
- $router:路由实例,使用$router.push方法导航到不同的URL。
- $route:处于活跃状态的路由对象,可以获取当前浏览器URL路由的参数值,比如name,path,query, params等。
hash/history
- hash模式:锚点,指url尾巴后的#号和后面的字符。浏览器刷新不会向服务器发送请求,hash改变会触发hashchange事件,只能改变#后面的url片段。
- history模式:页面定位,提供了pushState和replaceState两个方法记录路由状态,这两个方法改变URL不会引起页面刷新,浏览器刷新会向服务器发送请求。
路由懒加载
把不同路由对应的组件分割成不同的代码块,当路由被访问的时候才加载对应组件。路由懒加载的主要作用就是将路由对应的组件打包成一个个的Js代码块。只有在这个路由被访问到的时候,才加载对应的组件。
router-link
设置导航的链接来实现不同的HTML内容切换,会被渲染为a标签。我们点击a标签时可能会重载页面,router-link会被vue监听,跳转链接时不会刷新界面。
- :to相当于a标签的href属性
- replace:页面切换时不会留下历史记录
- tag:被渲染成相应的标签
- active-calss:设置激活链接时class属性,当前页面及所有与当前页面地址匹配的链接都会被添加class属性
- append:当前(相对)路径前添加基路径。
router-view
- 一个页面里面可以切换着展现不同的组件页面,单页面中与router-link配合,渲染router-link映射过来的组件。
- 直接包在keep-alive里面,所有路径匹配到的视图组件都会被缓存。
Vuex
- 存储需要多页面共享的状态,全局单例对象,集中式存储管理。
- state:单一状态树,就是把所有的数据都放在一起。
- getters:可以当作是store的计算属性,可以访问store中的所有state,并且可以被多个模块重用。
- mutations:状态更新,不支持异步操作。
- action:代替mutations支持异步操作。
Vue命令
npm run dev:开发环境,在本地node中运行了一个前端服务器。
npm run build:将前端资源以及js源码打包并压缩,打包成一个新的静态的资源文件夹,放在Web(Tomcat/Ngnix)容器中即可运行。
...(扩展运算符)
...用于将一个可迭代的对象(比如数组,字符串等)展开为多个参数或者元素,属于浅拷贝。
npm报错
- npm config set proxy null
- npm config set https-proxy null
- npm config set registry https://registry.npm.taobao.org
Edge浏览器调试
- F8:暂停脚本执行。
- F10:跳过下一个函数调用。
- F11:进入下一个函数调用。
- Shift+F11:跳出当前函数。
- F9:单步调试。
- Ctrl+F8:停用断点。
VSCode配置Edge调试
Vue3
优势
- 打包大小减少41%,打包快。
- 初次渲染快55%,更新渲染快133%。
- 内存减少54%,占用内存少。
- 使用Proxy代替defineProperty实现响应式。
- 重写虚拟DOM的实现。
- 更好的支持TypeScript。
- 在Vue2.0中,使用传统的Options API,新增或者修改一个需求,就需要分别在data,methods,computed 里面进行修改。而在Vue3.0中可以利用Composition API可以更加有序的将代码,函数组织在一起。
Vite
- 开发环境中,无需打包操作,可快速的冷启动。
- 轻量快速的热重载。
- 真正的按需编译,不再等待整个应用编译完成。
生命周期
Vue3.0中,将beforeDestroy改名为beforeUnmount,destroyed改名为unmounted。
响应式原理
Vue2.0的响应式
实现原理
- 对象类型通过Object.defineProperty()对属性的读取,修改进行拦截(数据劫持)。
- 数组类型通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
存在问题
- 新增属性,删除属性,界面不会更新,可以通过this.$set,Vue.set来解决。
- 直接通过下标修改数组,界面不会自动更新。
Vue3.0的响应式
- 通过Proxy(代理),拦截对象中任意属性的变化,包括属性值的读写,添加,删除等。
- 通过Reflect(反射),对源对象的属性进行操作。
通信方式
props
Vue3.0中可以通过defineProps获取父组件传递的数据,并且在组件内部不需要引入defineProps方法就可以直接使用,props是只读的,不能修改。
自定义事件
原生DOM事件
- 原生DOM事件可以让用户与网页进行交互,比如click,change等。
- Vue2.0中组件标签需要通过native修饰符才能变为原生DOM事件。
- Vue3.0中,原生DOM事件不管是在标签,自定义标签,还是在组件标签上,它都是原生DOM事件。
自定义事件
- 自定义事件可以实现子组件给父组件传递数据。
- Vue3.0中,使用defineEmits方法传递一个数组,数组元素即为将来组件需要触发的自定义事件类型,此方法执行会返回一个$emit方法用于触发自定义事件。
- 在事件回调内部调用$emit方法去触发自定义事件,第一个参数为触发事件的类型。第二个,第三个等 等的参数为传递给父组件的数据。
- 在子组件中,defineEmits方法会将父组件的原生DOM事件变为自定义事件。
全局事件总线
- 全局事件总线可以实现任意组件通信,在Vue2.0中可以根据VM与VC的关系推出全局事件总线。
- Vue3.0中没有Vue的构造函数,也就没有Vue.prototype,并且组合式API写法没有this,那么在Vue3.0 中想实现全局事件总线的功能就有点不现实。
- 在Vue3.0中想使用全局事件总线的功能,可以使用mitt插件。
v-model
1. v-model可以用来收集表单数据,进行数据的双向绑定。
2. 还可以实现父子组件的数据同步,相当于给子组件传递一个props(modelValue)和绑定一个自定 义事件 update:modelValue,来实现父子组件的数据同步。
3. Vue3.0中一个组件可以通过使用多个v-model,实现父子组件多个数据的同步。
useAttrs
- Vue3.0中可以利用useAttrs方法获取组件的属性和事件,事件包含原生DOM事件或者自定义事件,类 似于Vue2.0中的$attrs属性和$listeners方法。
- 如果在子组件中用defineProps方法接受了某一个属性,那么useAttrs方法返回的对象身上就没有相应的属性和属性值。
ref/$parent
- ref可以获取元素的DOM或者获取子组件实例的VC。
- 既然可以在父组件内部通过ref获取子组件的实例VC,那么子组件内部的方法和响应式的数据父组件 都可以使用。
- Vue3.0中,组件内部的数据对外是“关闭的”,外部不能访问。
- 如果想让父组件获取子组件的数据或者方法,子组件需要通过defineExpose对外进行暴露。
- $parent可以获取某一个组件的父组件实例VC,因此可以使用父组件内部的数据和方法。
- 当然,父组件的数据和方法也需要通过defineExpose对外进行暴露。
provide/inject
在Vue3.0中,可以利用provide和inject实现祖先和后代组件间的通信。
pinia
pinia也是集中式管理的状态容器,类似于Vuex。
slot
默认插槽
具体名称插槽
具体名称插槽就是在组件内部留多个指定名字的插槽。
作用域插槽
作用域插槽可以理解为,子组件的数据由父组件提供,但是子组件内部决定不了自身结构和外观样式。
setup
是什么
组件中所用到的数据,方法等等,都需要配置在setup中。
注意点
- 尽量不要与Vue2.0配置混用。
- Vue2.0配置(data,methods,computed...)中可以访问到setup中的属性,方法。
- 但在setup中不能访问Vue2.0配置。
- 如果有重名,setup优先。
- setup不能是一个async函数,因为返回值不再是return的对象,而是Promise,后期也可以返 回一个Promise实例,但是需要Suspense和异步组件的配合。
- setup在beforeCreate之前执行一次,这个时候的this是undefined。
ref/reactive
定义数据角度对比
- ref用来定义基本类型数据,也可以用来定义对象(或数组)类型数据,它内部会自动通过reactive转为代理对象。
- reactive用来定义对象(或数组)类型数据。
原理角度对比
- ref通过Object.defineProperty()的get和set来实现响应式(数据劫持)。
- reactive通过Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据。
使用角度对比
- ref定义的数据,操作数据时需要.value,读取数据时模板中直接读取不需要.value。
- reactive定义的数据,操作数据与读取数据都不需要.value。
customRef
customRef用来创建一个自定义的ref,并且对其依赖项跟踪和更新触发进行显示控制。
toRef/toRefs
- toRef将响应式对象中的某个属性单独提供给外部使用。
- toRefs和toRef的功能一致,但是可以批量创建多个ref对象。
computed
watch/watchEffect
watch
- 监视reactive定义的响应式数据时,oldValue无法正确获取,强制开启了深度监视(deep配置失效)。
- 监视reactive定义的响应式数据中某个属性时,deep配置有效。
watchEffect
- watch既要指明监听的属性,也要指明监听的回调。
- watchEffect不用指明监听哪个属性,监视的回调中用到哪个属性,那就监听哪个属性。
- watchEffect类似computed,但是computed注重的是计算出来的值(回调函数的返回值),所以必须要写返回值,而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
shallowReactive/shallowRef
- ShallowReactive只处理对象最外层属性的响应式。
- shallowRef只处理基本数据类型的响应式,不进行对象的响应式处理。
readonly/shallowReadonly
- readonly让一个响应式的数据变为只读的(深只读)。
- shallowReadonly让一个响应式的数据变为只读的(浅只读)。
toRaw/markRaw
- toRaw将一个由reactive生成的响应式对象转为普通对象,用于读取响应式对象对应的普通对象, 对这个普通对象的所有操作,不会引起页面的更新。
- markRaw用于标记一个对象,使该对象永远不会再成为响应式对象。
- 有些值不应该被设置为响应式的,例如复杂的第三方类库。
- 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
provide/inject
- provide和inject用来实现祖先和后代组件间的通信。
- 父组件有一个provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据。
响应式数据的判断
- isRef用来检查一个值是否为一个ref对象。
- isReactive用来检查一个对象是否由reactive创建的响应式代理。
- isReadonly用来检查一个对象是否由readonly创建的只读代理。
- isProxy用来检查一个对象是否由reactive或者readonly方法创建的代理。
Fragment
- 在Vue2.0中,组件必须有一个根标签。
- 在Vue3.0中,组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中,减少标签层级,减少内存占用。
Teleport
Teleport能够将我们的组件内html结构移动到指定位置的技术。
Suspense
Suspense在等待异步组件时渲染一些额外的内容,让应用有更好的用户体验。