Es6
# Es6
1、let和const 2、symbol 3、模板字符串 3.1 字符串新方法(补充) 4、解构表达式 4.1 数组解构 4.2 对象解构 5、对象方面 5.1 Map和Set 5.1.1 Map 5.1.2 Set 5.3 数组的新方法 5.3.1 Array.from()方法 5.3.2 includes()方法 5.3.3 map()、filter() 方法 5.3.4 forEach()方法 5.3.4 find()方法 5.3.6 some()、every() 方法 5.4 object的新方法 5.4.1 Object.is() 5.4.2 Object.assign() 5.4.3 Object.keys()、Object.values()、Object.entries() 5.5 对象声明简写 5.6 ...(对象扩展符) 6、函数方面 6.1 参数默认值 6.2 箭头函数 6.3 箭头函数和普通函数最大的区别在于其内部this永远指向其父级对象的this。(重点) 7、class(类) 8、promise和proxy 9、模块化 10、运算符
# 前端基本数据类型
在前端开发中,JavaScript 是最常用的编程语言之一。JavaScript 拥有多种数据类型,这些数据类型可以分为基本数据类型和引用数据类型。
基本数据类型
基本数据类型是存储在栈内存中的简单数据段,占用的内存较小,可以直接操作它们的值。JavaScript 的基本数据类型包括:
String:字符串,用于表示文本值,例如 "Hello, World!"
1
。
Number:数字,可以是整数或浮点数,例如 42 或 3.14
2
。
Boolean:布尔值,有两个值:true 和 false
2
。
Null:表示空值,是一个特殊的关键字,表示变量没有值
1
。
Undefined:表示未定义,是一个特殊的关键字,表示变量未赋值
1
。
Symbol:ES6 引入的一种新的原始数据类型,表示独一无二的值
3
。
BigInt:可以表示任意大的整数,超过了 Number 的安全整数限制
1
。
引用数据类型
引用数据类型是存储在堆内存中的对象,变量中保存的是一个指针,指向内存堆中的实际值。JavaScript 的引用数据类型包括:
Object:对象,是一种复合数据类型,可以包含多个键值对
2
。
Array:数组,是一种特殊的对象,用于存储有序的元素集合
3
。
Function:函数,是一种可调用的对象,用于封装可执行的代码块
3
。
RegExp:正则表达式,是一种用于匹配字符串模式的特殊对象
3
。
Date:日期对象,用于处理日期和时间
3
。
数据类型判断方法
在 JavaScript 中,可以使用多种方法来判断变量的数据类型:
typeof:用于判断基本数据类型,例如 typeof 42 返回 "number"
1
。
instanceof:用于判断引用数据类型,例如 [1, 2, 3] instanceof Array 返回 true
1
。
constructor:用于判断对象的构造函数,例如 [1, 2, 3].constructor === Array 返回 true
1
。
Object.prototype.toString.call():用于判断任意数据类型,例如
# 路由的设计理念
路由的设计理念是为了在不重新加载整个页面的情况下,实现页面内容的切换。这通常用于单页面应用(SPA),其中URL路径的变化对应于页面内容的局部更新。
2. hash模式
原理:hash模式通过改变URL中的hash部分(即#符号及其后面的部分)来实现路由的变化。这种变化不会导致页面的重新加载。
实现方式:通过监听onhashchange事件来捕捉hash值的变化,并据此更新页面内容。
示例代码:
<a href="#/index">首页</a>
<a href="#/about">关于</a>
当点击链接时,URL会变为http://example.com/#/index或http://example.com/#/about,但不会重新加载页面。
3. history模式
原理:history模式利用HTML5的history.pushState方法,允许在不刷新页面的情况下,改变URL的路径部分。
实现方式:通过history.pushState方法来改变URL,并监听popstate事件来处理浏览器的前进和后退操作。
优点:与hash模式相比,history模式的URL更加美观,没有#符号,看起来更像传统的URL。
4. 主要区别
URL表现:hash模式的URL包含#符号,而history模式的URL则看起来更传统。
刷新行为:在hash模式下,改变URL的hash部分不会导致页面刷新;而在history模式下,虽然也不会刷新页面,但可以更灵活地控制URL。
# vue2 (opens new window)和vue3响应式原理
Vue2和Vue3的响应式原理都是基于Object.defineProperty实现的,但是Vue3在性能和功能上做了一些优化和改进。
- 响应式原理:Vue.js 中的响应式原理是基于它的核心特性之一,即能够追踪数据变化并在数据变化时自动更新视图。Vue.js 使用了
Object.defineProperty方法来实现数据的响应式,这允许它追踪对象的属性变化,并在这些属性发生变化时更新依赖它们的组件。 - 双向绑定原理:在 Vue.js 中,双向绑定通常指的是
v-model指令,它是一种简写方式,用于在表单输入元素(如<input>、<textarea>、<select>)上创建双向数据绑定。当用户在表单元素上输入时,Vue.js 会自动将输入值绑定到相应的数据属性上,并且当数据属性发生变化时,Vue.js 会自动更新表单元素的值。
# Vue2的响应式原理:
Vue2通过Object.defineProperty对data中的属性进行劫持,当属性值发生变化时,会触发对应的更新函数,从而更新视图。
Vue2通过Watcher来实现数据与视图的双向绑定,当数据发生变化时,Watcher会通知对应的视图进行更新。
Vue2的响应式原理存在一些缺陷,例如无法监听数组的变化,需要通过特殊的方法来实现.
Vue3的响应式原理:
Vue3使用Proxy代替了Object.defineProperty,Proxy可以监听到对象的所有属性,包括新增和删除操作。
Vue3使用了WeakMap来存储依赖关系,避免了Vue2中Watcher的内存泄漏问题。
Vue3支持了多个根节点的组件,可以更方便地进行组件的复用和组合。 ————————————————
Vue3带来了什么
更快的渲染速度:Vue3使用了Proxy代理对象,可以更快地跟踪数据变化,从而提高渲染速度。
更小的体积:Vue3的体积比Vue2更小,同时也支持按需加载,减少了页面加载时间。
更好的TypeScript支持:Vue3对TypeScript的支持更加完善,可以更好地进行类型检查和代码提示。
更好的组件封装:Vue3引入了Composition API,可以更好地封装组件逻辑,使得组件更加可复用和易维护。
更好的响应式系统:Vue3的响应式系统进行了重构,可以更好地处理嵌套对象和数组的变化,同时也提供了更多的API来处理响应式数据。
总之,Vue3带来了更好的性能、更小的体积、更好的TypeScript支持、更好的组件封装和更好的响应式系统,使得开发者可以更加高效地开发Vue应用。
# composition API 优势好处特点
由于vue2有局限性:
组件的逻辑膨胀导致组件的可读性变差;
无法跨组件重用代码;
vue2对TS的支持有限
3.2、组合式API解决了什么问题?
1、面对vue2的局限性,可以将相同的代码组织在一起,而不会散落在各个角落
3.3、组合式API的优点?
composition API是根据逻辑相关性组织代码的,提高可读性和维护性
代码量少,更好的重用逻辑代码
没有引入新的语法,只是单纯函数
异常灵活
工具语法提示友好,因为是单纯函数所以很容易实现语法提示、自动补偿
更好的Typescript支持
在复杂功能组件中可以实现根据特性组织代码,代码内聚性强
组件间代码复用
# setup配置
Vue 3中的 setup 函数接收两个参数,分别是 props 和 context。
1、props:值为对象,包含: 组件外部传递过来。切组件内部声明接收了的属性。需要注意的是,Vue3中的 props 是只读的,即在setup 函数中不能修改 props 的值。如果需要修改传递过来的数据,可以使用响应式对象或ref。
2、context:上下文对象。
attrs:值为对象,包含组件外部传递过来,但没有在props配置中声明的属性。相当于this.$attrs
slots:收到的插槽内容,相当于this.$slots
emit:分发自定义事件的函数,相当于this.$emit
注意:
1、这个钩子会在created之前执行
2、内部不存在this
3、如果返回值是一个对象,那么这个对象中的键值对会被合并到created钩子的this中,而在视图上也能访问相应的数据值
# ref与reactive
reactive:
(1)、它的响应式是更加‘深层次’的,底层本质是将传入的数据包装成一个Proxy。
(2)、参数必须是对象或者数组,如果要让对象的某个元素实现响应式时比较麻烦。需要使用toRefs
# ref:
(1)、函数参数可以是基本数据类型,也可以接受对象类型
(2)、如果参数是对象类型时,其实底层的本质还是reactive,系统会自动根据我们给ref传入的值转换成:reactive
(3)、在template中访问,系统会自动添加.value;在js中需要手动.value
(4)、ref响应式原理是依赖于Object.defineProperty()的get()和set()的。
# 计算属性
、什么是计算属性:
1、computed函数,是用来定义计算属性的,计算属性不能修改。
2、模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。
3、计算属性还可以依赖多个Vue 实例的数据,只要其中任一数据变化,计算属性就会重新执行,视图也会更新。
methods和computed看起来都可以实现我们的功能, 那么为什么还要多一个计算属性这个东西呢?
原因:
1、计算属性会进行缓存,如果多次使用时,计算属性只会调用一次;
2、而方法会使用一次则调用一次,因此计算属性相对而言性能更好。
注意:
回调函数必须return,结果就是计算的结果
如果计算属性依赖的数据发生变化,那么会重新计算
不要在计算中中进行异步操作
高级:computed有两个方法,分别是set()和get()。
计算属性可以直接读取或者修改
如果要实现计算属性的修改操作,那么computed的实参应该是对象
读取数据触发get方法
修改数据触发set方法,set函数的形参就是你赋给他的值
# watch与watchEffect
1、watch和watchEffect都是vue3中的监听器,但是在写法和使用上是有区别的,主要是介绍一下watch和watchEffect的使用方法以及他们之间的区别。
2、 watch 的工作原理:侦听特定的数据源,并在回调函数中执行副作用。它默认是惰性的——只有当被侦听的源发生变化时才执行回调,不过,可以通过配置 immediate 为 true 来指定初始时立即执行第一次。可以通过配置 deep 为 true,来指定深度监视。
3、immdiate: 默认情况下,侦听器需要 data 后面值改变了才会生效,若需要侦听器一进入页面就生效,那就需要使用 immediate。 4、deep: 默认情况下,侦听器只会监听数据本身的改变,若要进行深度监听,那就需要使用 deep。 5、immediate 和 deep 配置在第三个参数对象里。 第一个参数:监听谁,第二个参数:回调函数,第三个参数:配置对象
# watchEffect
watchEffect 函数的特点:
优点:
会自动收集依赖,不需要手动传递侦听内容——自动侦听回调函数中使用到的响应式数据。
默认 immdiate 是 true,所以初始化时会立即执行。
缺点:
无法获得变化前的值(oldVal)。
1、watch() 是懒执行的:当数据源发生变化时,才会执行回调。但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调。
2、watchEffect相当于将watch 的依赖源和回调函数合并,当任何你有用到的响应式依赖更新时,该回调函数便会重新执行。不同于 watch,watchEffect 的回调函数会被立即执行(即 { immediate: true })
3、简单来说,watchEffect 是 Vue3 中的一个响应式 API,它允许你监听响应式状态的变化,并在其发生变化时触发副作用函数。这个特性非常有用,在我们需要对响应式数据进行操作的时候,我们可以在监听到变化后马上做出反应。
# provide与inject
1、provide和inject是一对新的API,用于在父组件中提供数据,然后在子组件中注入数据。
2、provide:是一个对象,或者是一个返回对象的函数。里面呢就包含要给子孙后代的东西,也就是属性和属性值。
3、inject:一个字符串数组,或者是一个对象。属性值可以是一个对象,包含from和default默认值。
# .vue3新的生命周期钩子
Vue3中新增了两个生命周期钩子函数:
beforeUnmount:在组件卸载之前调用,可以用来做一些清理工作,比如取消订阅、清除定时器等。
onRenderTracked:在组件渲染时调用,可以用来监视组件的状态变化,比如打印组件的状态、记录组件的变化等。
除此之外,Vue3还对原有的生命周期钩子函数进行了优化和改进,比如:
beforeCreate和created合并为setup函数,使得组件的初始化更加简洁和灵活。
beforeMount和mounted合并为onMounted函数,使得组件的挂载更加高效和可控。
beforeUpdate和updated合并为onUpdated函数,使得组件的更新更加精准和可靠。
beforeDestroy和destroyed合并为onUnmounted函数,使得组件的卸载更加安全和可靠。
# 执行最终顺序:
Vue3生命周期:setup
Vue3生命周期:onBeforeMount
Vue3生命周期:onMounted
Vue3生命周期:onBeforeUpdate
Vue3生命周期:onUpdated
Vue3生命周期:onBeforeUnmount
Vue3生命周期:onUnmounted
Vue2生命周期:beforeCreate
Vue2生命周期:created
Vue2生命周期:beForeMount
Vue2生命周期:mounted
Vue2生命周期:beforeUpdate
Vue2生命周期:updated
Vue2生命周期:beforedestoryed
Vue2生命周期:destoryed
# 自定义hook函数
1、以函数形式抽离一些可复用的方法像钩子一样挂着,随时可以引入和调用,实现高内聚低耦合的目标;
2、将可复用功能抽离为外部JS文件
3、函数名/文件名以use开头,形如:useXX
4、引用时将响应式变量或者方法显式解构暴露出来如:const {nameRef,Fn} = useXX()
(在setup函数解构出自定义hooks的变量和方法)
10.1、Vue3自定义Hooks和Vue2时代Mixin的关系:
Mixin不足 在 Vue 2 中,mixin 是将部分组件逻辑抽象成可重用块的主要工具。但是,他们有几个问题: 1、Mixin 很容易发生冲突:因为每个 mixin 的 property 都被合并到同一个组件中,所以为了避免 property 名冲突,你仍然需要了解其他每个特性。 2、可重用性是有限的:我们不能向 mixin 传递任何参数来改变它的逻辑,这降低了它们在抽象逻辑方面的灵活性。
10.2、vue3自定义hooks和vue2中mixin的区别和比较?
1、Mixin难以追溯的方法与属性!Vue3自定义Hooks却可以
2、无法向Mixin传递参数来改变逻辑,但是Vue3自定义Hooks却可以:
3、Mixin同名变量会被覆盖,Vue3自定义Hook可以在引入的时候对同名变量重命名
# toRef和toRefs
toRef 和 toRefs 可以用来复制 reactive 里面的属性然后转成 ref,而且它既保留了响应式,也保留了引用,也就是你从 reactive 复制过来的属性进行修改后,除了视图会更新,原有 ractive 里面对应的值也会跟着更新,如果你知道 浅拷贝 的话那么这个引用就很好理解了,它复制的其实就是引用 + 响应式 ref 不加 s 和 加 s 的区别就是这样:
toRef: 复制 reactive 里的单个属性并转成 ref toRefs: 复制 reactive 里的所有属性并转成 ref
# shallowReactive 与 shallowRef
1、shallowRef:只处理基本数据类型的响应式
2、shallowReactive:只处理对象最外层属性的响应式(浅响应式)
3、浅层作用的响应式数据处理:只处理第一层对象的数据,再往下嵌套的数据,操作数据是不起作用的
4、shallowReative与shallowRef在某些特殊的应用场景下,是可以提升性能的,前者针对对象,用于浅层作用的响应式数据处理,而后者只处理基本数据类型的响应式,不进行对象的响应式处理。
# Readonly 与 shallowReadonly
readonly与shallowReadonly都是让响应式数据只具备读的能力,后者是浅层次的只读,也就是只对数据对象第一层起作用,深层次的嵌套,当时用shallowReadonl()处理时,深层次数据支持被修改
1、readonly: 让一个响应式数据变为只读的 (深只读),让一个响应式数据变为只读的,接收一个响应式数据,经过readonly加工处理一下,那么新赋值的数据都不允许修改
2、接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理
3、shallowReadonly: 让一个响应式数据变为只读的 (浅只读),接收一个响应式数据,经过shallowreadonly的处理,变成一个只读的,只考虑对象的第一层数据,不可以修改,但是第一层嵌套里的深层数据却支持修改
4、让一个响应式数据变为只读能力(浅只读)
# toRaw与markRaw转换为普通数据和标记属性非响应式
toRaw,将响应式对象(由 reactive定义的响应式)转换为普通对象,然后赋值给新的变量(不影响原来的对象)
markRaw,标记一个对象,使其不能成为一个响应式对象。
toRaw: 作用: 将一个由 reactive 生成的响应式对象转为普通对象 使用场景:
1、用于读取响应式对象对应的普通对象
2、对这个普通对象的所有操作,不会引起页面更新。
markRaw: 作用:标记一个对象,使其永远不会再成为响应式对象 应用场景: 1、有些值不应被设置为响应式的,例如复杂的第三方类库等 2、当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能
# customRef 自定义ref使用
customRef:返回一个ref对象,可以显示的控制依赖追踪和触发响应
# vue3中的父传子,子传父
、父传子:
1、在父组件的子组件标签上通过:传到子组件的数据名=‘需要传递的数据’
2、子组件中通过props进行接收并在模板中使用
2、子传父:
1、子组件触发事件通过setup函数的第二个参数,context.emit来实现子传父
# vue3中使用插槽
1、插槽 slot 通常用于两个父子组件之间,最常见的应用就是我们使用一些 UI 组件库中的弹窗组件时,弹窗组件的内容是可以让我们自定义的,这就是使用了插槽的原理。
2、理解:
slot 是 Vue3 中的内置标签。
slot 相当于给子组件挖出了一个槽,可以用来填充内容。
父组件中调用子组件时,子组件标签之间的内容元素就是要放置的内容,它会把 slot 标签替换掉
3、具名插槽:具有名字的 插槽。简单来说这个具名插槽的目的就是让一个萝卜一个坑,让它们呆在该呆的位置去。比如带 name 的插槽被称为具名插槽
4、作用域插槽:能够接受参数的插槽就被称为了作用域插槽。
# vue3中路由守卫onBeforeRouteLeave,onBeforeRouteUpdate
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
1、vue3 router中新增的onBeforeRouteLeave方法表示添加一个导航守卫,此方法会在组件将要离开的时候触发,类似于以前的beforeRouteLeave,但onBeforeRouteLeave可以在任何组件中使用,当组件被卸载的时候,导航守卫也将被移除。当我们使用router执行跳转或返回的时候,就会触发onBeforeRouteLeave方法。
2、 onBeforeRouteUpdate:添加一个导航守卫,在当前位置即将更新时触发。
import { onBeforeRouteUpdate } from "vue-router";
onBeforeRouteUpdate(to => {
console.log(to, "路由变动");
});
3、onBeforeRouteLeave:添加一个导航守卫,在当前位置的组件将要离开时触发。
//使用组件内守卫,对离开页面事件做一些操作,
beforeRouteLeave(to, from, next){
if(from.path=='/b'){ //当前页面路由
next({replace: true,redirect: '/a'}); //目标路由 重定向
}else {
next()
}
}
# vue3中使用vuex useStore?
1、在Vue3中,可以使用useStore函数来获取Vuex store实例。useStore函数是一个Vue Composition API函数,它可以在组件中使用。
使用`useStore`函数的步骤如下:
1. 在组件中导入`useStore`函数和`createStore`函数。
import { useStore, createStore } from 'vuex'
2. 创建一个Vuex store实例。
const store = createStore({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
})
3. 在组件中使用`useStore`函数来获取Vuex store实例。
export default {
setup() {
const store = useStore()
return {
store
}
}
}
4. 在组件中使用Vuex store实例。
<template>
<div>
<p>Count: {{ store.state.count }}</p>
<button @click="store.commit('increment')">Increment</button>
</div>
</template>
<script>
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
return {
store
}
}
}
</script>
# vue3中使用vue-router,useRoute和useRouter ?
1、在Vue.js中,useRoute和useRouter是Vue Router提供的两个钩子函数,用于在组件中访问路由信息和路由实例。
2、useRoute相当于是vue2中的this.$route
import { useRoute } from 'vue-router'
export default {
setup() {
const route = useRoute()
console.log(route.path) // 当前路由路径
return {
route
}
}
}
3、useRouter相当于是vue2中的this.$router,可以使用useRouter进行路由跳转
import { useRouter } from 'vue-router'
export default {
setup() {
const router = useRouter()
console.log(router.currentRoute.value.path) // 当前路由路径
return {
router
}
}
}
4、区别:
useRoute函数返回当前路由的信息对象,包括路由路径、参数、查询参数等信息。
useRouter函数返回Vue Router的实例,我们可以在组件中使用useRouter函数来获取Vue Router的实例。
# vue3中nextTick使用
1、nextTick 是将回调推迟到下一个 DOM 更新周期之后执行。在更改了一些数据以等待 DOM 更新后立即使用它
2、异步使用:
import { nextTick } from 'vue'
//异步使用
setup() {
const message = ref('Hello!')
const changeMessage = async newMessage => {
message.value = newMessage
await nextTick()
console.log('Now DOM is updated')
}
}
//基本使用
nextTick(()=>{
...
})
# 原型绑定全局属性
1、通过config.globalProperties
2、通过provide注入:在应用实例上设置一个可以被注入到应用范围内所有组件中的值。当组件要使用应用提供的 provide 值时,必须用 inject 来接收。
3、在main.js中全局引入,然后在组件中获取
# vue3中使用keeplive ?
1、keep-alive是Vue提供的一个抽象组件,主要用于保留组件状态或避免重新渲染。
2、 包裹动态组件时,会缓存不活动的组件实例,而不是销毁他们。
和 是一个抽象组件,它自身不会渲染一个DOM元素,也不会出现在父组件链中。但是 keep-alive 会把其包裹的所有组件都缓存起来。
3、使用:
1、配置app.vue 使用v-if判断是否缓存
2、添加meta属性,在路由元信息中添加缓存的标识
3、实现页面的部分刷新