开始准备面试,在参考了一些大神的总结文章,结合自己收集的一些其他资料,汇总并整理了一份自己的复习资料
父子组件生命周期顺序?
子组件的生命周期嵌套在父组件的beforeMount和mounted之间
如何监听子组件的生命周期?
在子组件里通过vm.$emit()触发一个自定义事件,在父组件中监听该事件执行对应函数
使用@hook:生命周期函数名称=“回调函数”
Vue.$nextTick
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
nextTick 是 Vue 提供的一个全局 API,由于 Vue 的异步更新策略,导致我们对数据修改后不会直接体现在 DOM 上,此时如果想要立即获取更新后的 DOM 状态,就需要借助该方法。
Vue 在更新 DOM 时是异步执行的。当数据发生变化,Vue 将开启一个异步更新队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入队列一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。nextTick方法会在队列中加入一个回调函数,确保该函数在前面的 DOM 操作完成后才调用。
使用场景:
- 如果想要在修改数据后立刻得到更新后的
DOM结构,可以使用Vue.nextTick() - 在
created生命周期中进行DOM操作
Vue 实例挂载过程中发生了什么?
挂载过程指的是 app.mount()过程,这是一个初始化过程,整体上做了两件事情:初始化和建立更新机制。
初始化会创建组件实例、初始化组件状态、创建各种响应式数据。
建立更新机制这一步会立即执行一次组件的更新函数,这会首次执行组件渲染函数并执行patch将vnode 转换为 dom; 同时首次执行渲染函数会创建它内部响应式数据和组件更新函数之间的依赖关系,这使得以后数据发生变化时会执行对应的更新函数。
Vue的组件data为什么必须是一个函数?
new Vue是一个单例模式,不会有任何的合并操作,所以根实例不必校验data一定是一个函数。
组件的data必须是一个函数,是为了防止两个组件的数据产生污染。 如果都是对象的话,指向同一个地址。 而如果是函数返回的对象,会产生两个空间对应的内存地址。
Vue 的响应式原理
-
Vue 2 中的数据响应式会根据数据类型做不同的处理。如果是对象,则通过
Object.defineProperty(obj,key,descriptor)拦截对象属性访问,当数据被访问或改变时,感知并作出反应;如果是数组,则通过覆盖数组原型的方法,扩展它的7个变更方法(push、pop、shift、unshift、splice、sort、reverse),使这些方法可以额外的做更新通知,从而做出响应。
缺点:- 初始化时的递归遍历会造成性能损失;
- 通知更新过程需要维护大量
dep实例和watcher实例,额外占用内存较多; - 新增或删除对象属性无法拦截,需要通过
Vue.set及delete这样的 API 才能生效; - 对于
ES6中新产生的Map、Set这些数据结构不支持。
-
Vue 3 中利用
ES6的Proxy机制代理需要响应化的数据。可以同时支持对象和数组,动态属性增、删都可以拦截,新增数据结构均支持,对象嵌套属性运行时递归,用到时才代理,也不需要维护特别多的依赖关系,性能取得很大进步。
虚拟DOM
-
概念:
虚拟DOM,顾名思义就是虚拟的DOM对象,它本身就是一个JS对象,只不过是通过不同的属性去描述一个视图结构。 -
虚拟DOM的好处:
(1) 性能提升
直接操作DOM是有限制的,一个真实元素上有很多属性,如果直接对其进行操作,同时会对很多额外的属性内容进行了操作,这是没有必要的。如果将这些操作转移到JS对象上,就会简单很多。另外,操作DOM的代价是比较昂贵的,频繁的操作DOM容易引起页面的重绘和回流。如果通过抽象VNode进行中间处理,可以有效减少直接操作DOM次数,从而减少页面的重绘和回流。
(2) 方便跨平台实现
同一VNode节点可以渲染成不同平台上对应的内容,比如:渲染在浏览器是DOM元素节点,渲染在Native(iOS、Android)变为对应的控件。Vue 3 中允许开发者基于VNode实现自定义渲染器(renderer),以便于针对不同平台进行渲染。 -
结构:
没有统一的标准,一般包括tag、props、children三项。
tag:必选。就是标签,也可以是组件,或者函数。
props:非必选。就是这个标签上的属性和方法。
children:非必选。就是这个标签的内容或者子节点。如果是文本节点就是字符串;如果有子节点就是数组。换句话说,如果判断children是字符串的话,就表示一定是文本节点,这个节点肯定没有子元素。
Vue为什么要用虚拟DOM?
- 虚拟dom就是用js对象来描述真实Dom,是对真实Dom的抽象
- 由于直接操作Dom性能低,但是js层的操作效率高,可以将Dom操作转化成对象操作。最终通过diff算法比对差异进行更新Dom
- 虚拟Dom不依赖真实平台环境,可以实现跨平台
【虚拟DOM保证性能下限,实现最小量DOM更新】
diff 算法
-
概念:
diff算法是一种对比算法,通过对比旧的虚拟DOM和新的虚拟DOM,得出是哪个虚拟节点发生了改变,找出这个虚拟节点并只更新这个虚拟节点所对应的真实节点,而不用更新其他未发生改变的节点,实现精准地更新真实DOM,进而提高效率。 -
对比方式:
diff算法的整体策略是:深度优先,同层比较。比较只会在同层级进行, 不会跨层级比较;比较的过程中,循环从两边向中间收拢。key的作用主要是为了更加高效的更新虚拟 DOM。
Vue 判断两个节点是否相同时,主要是判断两者的key和元素类型tag。因此,如果不设置key ,它的值就是 undefined,则可能永远认为这是两个相同的节点,只能去做更新操作,将造成大量的 DOM 更新操作。
Vue的组件data为什么必须是一个函数?
new Vue是一个单例模式,不会有任何的合并操作,所以根实例不必校验data一定是一个函数。
组件的data必须是一个函数,是为了防止两个组件的数据产生污染。 如果都是对象的话,指向同一个地址。 而如果是函数返回的对象,会产生两个空间对应的内存地址。
组件的传值方式有哪些?
- props和emit:父组件向子组件传递数据,通过prop传递。子组件传递数据给父组件是通过emit
- parent、children获取当前组件的父组件和当前组件的子组件
- attrs和listeners 。
- 父组件通过provide提供,子组件通过inject注入变量
- $ref获取实例
- eventBus平级组件数据传递
- Vuex
-
v-show和v-if的区别是什么?
共同点:v-if 和 v-show 都能实现元素的显示隐藏
区别:
1. v-show 只是简单的控制元素的 display 属性,而 v-if 才是条件渲染(条件为真,元素将会被渲染,条件为假,元素会被销毁);
2. v-show 有更高的首次渲染开销,而 v-if 的首次渲染开销要小的多;
3. v-if 有更高的切换开销,v-show 切换开销小;
4. v-if 有配套的 v-else-if 和 v-else,而 v-show 没有
5. v-if 可以搭配 template 使用,而 v-show 不行
v-for和v-if哪个优先级更高?
v-for和v-if 不能在同一个标签中使用。先处理v-for,再处理v-if。
如果同时遇到的时候,应该考虑先用计算属性处理数据,在进行v-for,可以减少循环次数。
v-for和v-if为何不推荐同时使用?
v-for的优先级高于v-if,所以不管条件是否成立,v-for都会做循环,所以是达不到先判断再循环的作用。
如果存在需要先判断条件是否成立,再循环数据的场景我们可以使用template标签使用v-if指令做条件判断,在tempalte中的子标签做循环。
computed和watch的区别是什么?
- computed和watch都基于watcher来实现的。
- computed的属性是具备缓存的,依赖的值不发生变化,对其取值时计算属性方法不会重复执行
- watch是监控值的变化,当值发生改变的时候,会调用回调函数
keep-alive 是什么?
- 作用:实现组件缓存,保持组件的状态,避免反复渲染导致的性能问题。
- 工作原理:Vue.js 内部将 DOM 节点,抽象成了一个个的 VNode 节点,
keep-alive组件的缓存也是基于 VNode 节点的。它将满足条件的组件在 cache 对象中缓存起来,重新渲染的时候再将 VNode 节点从 cache 对象中取出并渲染。 - 可以设置以下属性:
①include:字符串或正则,只有名称匹配的组件会被缓存。
②exclude:字符串或正则,任何名称匹配的组件都不会被缓存。
③max:数字,最多可以缓存多少组件实例。
匹配首先检查组件的name选项,如果name选项不可用,则匹配它的局部注册名称(父组件 components选项的键值),匿名组件不能被匹配。
如果同时使用了include、exclude,那么exclude的优先级高于include。
设置了keep-alive缓存的组件,会多出两个生命周期钩子:activated、deactivated。
首次进入组件时:beforeCreate --> created --> beforeMount --> mounted --> activated --> beforeUpdate --> updated --> deactivated
再次进入组件时:activated --> beforeUpdate --> updated --> deactivated
mixin
mixin(混入), 它提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。
使用场景: 不同组件中经常会用到一些相同或相似的代码,这些代码的功能相对独立。可以通过mixin 将相同或相似的代码提出来。
缺点:
- 变量来源不明确
- 多 mixin 可能会造成命名冲突(解决方式:Vue 3的组合API)
- mixin 和组件出现多对多的关系,使项目复杂度变高。
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
插槽
slot插槽,一般在组件内部使用,封装组件时,在组件内部不确定该位置是以何种形式的元素展示时,可以通过slot占据这个位置,该位置的元素需要父组件以内容形式传递过来。slot分为:
-
默认插槽:子组件用<slot>标签来确定渲染的位置,标签里面可以放DOM结构作为后备内容,当父组件在使用的时候,可以直接在子组件的标签内写入内容,该部分内容将插入子组件的<slot>标签位置。如果父组件使用的时候没有往插槽传入内容,后备内容就会显示在页面。 -
具名插槽:子组件用name属性来表示插槽的名字,没有指定name的插槽,会有隐含的名称叫做default。父组件中在使用时在默认插槽的基础上通过v-slot指令指定元素需要放在哪个插槽中,v-slot值为子组件插槽name属性值。使用v-slot指令指定元素放在哪个插槽中,必须配合<template>元素,且一个<template>元素只能对应一个预留的插槽,即不能多个<template>元素都使用v-slot指令指定相同的插槽。v-slot的简写是#,例如v-slot:header可以简写为#header。 -
作用域插槽:子组件在<slot>标签上绑定props数据,以将子组件数据传给父组件使用。父组件获取插槽绑定 props 数据的方法:- scope="接收的变量名":
<template scope="接收的变量名"> - slot-scope="接收的变量名":
<template slot-scope="接收的变量名"> - v-slot:插槽名="接收的变量名":
<template v-slot:插槽名="接收的变量名">
- scope="接收的变量名":
Vue 中的修饰符有哪些?
在Vue 中,修饰符处理了许多 DOM 事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理。Vue中修饰符分为以下几种:
-
表单修饰符
lazy填完信息,光标离开标签的时候,才会将值赋予给value,也就是在change事件之后再进行信息同步。
number自动将用户输入值转化为数值类型,但如果这个值无法被parseFloat解析,则会返回原来的值。
trim自动过滤用户输入的首尾空格,而中间的空格不会被过滤。 -
事件修饰符
stop阻止了事件冒泡,相当于调用了event.stopPropagation方法。
prevent阻止了事件的默认行为,相当于调用了event.preventDefault方法。
self只当在event.target是当前元素自身时触发处理函数。
once绑定了事件以后只能触发一次,第二次就不会触发。
capture使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理。
passive告诉浏览器你不想阻止事件的默认行为。
native让组件变成像html内置标签那样监听根元素的原生事件,否则组件上使用v-on只会监听自定义事件。 -
鼠标按键修饰符
left左键点击。
right右键点击。
middle中键点击。 -
键值修饰符
键盘修饰符是用来修饰键盘事件(onkeyup,onkeydown)的,有如下:keyCode存在很多,但vue为我们提供了别名,分为以下两种:- 普通键(enter、tab、delete、space、esc、up...)
- 系统修饰键(ctrl、alt、meta、shift...)
对 SPA 的理解?
-
概念:
SPA(Single-page application),即单页面应用,它是一种网络应用程序或网站的模型,通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换时打断用户体验。在SPA中,所有必要的代码(HTML、JavaScript 和 CSS)都通过单个页面的加载而检索,或者根据需要(通常是响应用户操作)动态装载适当的资源并添加到页面。页面在任何时间点都不会重新加载,也不会将控制转移到其他页面。举个例子,就像一个杯子,上午装的是牛奶,中午装的是咖啡,下午装的是茶,变得始终是内容,杯子始终不变。 -
SPA与MPA的区别:
MPA(Muti-page application),即多页面应用。在MPA中,每个页面都是一个主页面,都是独立的,每当访问一个页面时,都需要重新加载 Html、CSS、JS 文件,公共文件则根据需求按需加载。SPA MPA 组成 一个主页面和多个页面片段 多个主页面 url模式 hash模式 history模式 SEO搜索引擎优化 难实现,可使用SSR方式改善 容易实现 数据传递 容易 通过url、cookie、localStorage等传递 页面切换 速度快,用户体验良好 切换加载资源,速度慢,用户体验差 维护成本 相对容易 相对复杂 -
SPA的优缺点:
优点:-
具有桌面应用的即时性、网站的可移植性和可访问性
-
用户体验好、快,内容的改变不需要重新加载整个页面
-
良好的前后端分离,分工更明确
缺点:
-
不利于搜索引擎的抓取
-
首次渲染速度相对较慢
-
双向绑定?
- 概念:
Vue 中双向绑定是一个指令v-model,可以绑定一个响应式数据到视图,同时视图的变化能改变该值。v-model是语法糖,默认情况下相当于:value和@input,使用v-model可以减少大量繁琐的事件处理代码,提高开发效率。 - 使用:
通常在表单项上使用v-model,还可以在自定义组件上使用,表示某个值的输入和输出控制。 - 原理:
v-model是一个指令,双向绑定实际上是Vue 的编译器完成的,通过输出包含v-model模版的组件渲染函数,实际上还是value属性的绑定及input事件监听,事件回调函数中会做相应变量的更新操作。
子组件是否可以直接改变父组件的数据?
-
所有的
prop都遵循着单项绑定原则,props因父组件的更新而变化,自然地将新状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。
另外,每次父组件更新后,所有的子组件中的props都会被更新为最新值,这就意味着不应该子组件中去修改一个prop,若这么做了,Vue 会在控制台上抛出警告。 -
实际开发过程中通常有两个场景导致要修改
prop:prop被用于传入初始值,而子组件想在之后将其作为一个局部数据属性。这种情况下,最好是新定义一个局部数据属性,从props获取初始值即可。- 需要对传入的
prop值做进一步转换。最好是基于该prop值定义一个计算属性。
-
实践中,如果确实要更改父组件属性,应
emit一个事件让父组件变更。当对象或数组作为props被传入时,虽然子组件无法更改props绑定,但仍然可以更改对象或数组内部的值。这是因为JS的对象和数组是按引用传递,而对于 Vue 来说,禁止这样的改动虽然可能,但是有很大的性能损耗,比较得不偿失。
router 和 route 的区别?
$router是VueRouter的实例对象,是一个全局的路由对象,包含了所有路由的对象和属性。$route是一个跳转的路由对象,可以认为是当前组件的路由管理,指当前激活的路由对象,包含当前url解析得到的数据,可以从对象里获取一些数据,如:name,path,params,query等。
vue-router 的路由传参方式?
- 声明式导航
router-link:
ruby
复制代码
<router-link :to="'/users?userId:1'"></router-link>
<router-link :to="{ name: 'users', params: { userId: 1 } }"></router-link>
<router-link :to="{ path: '/users', query: { userId: 1 } }"></router-link>
-
编程式导航
router-push:- 通过
params传参
php 复制代码 this.$router.push({ name: 'users', params: { userId: 1 } }); // 路由配置 { path: '/users', name: 'users', component: User } // 跳转后获取路由参数 this.$route.params.userId // 为 1- 通过
query传参
php 复制代码 this.$router.push({ path: '/users', query: { userId: 1 } }); // 路由配置 { path: '/users', name: 'users', component: User } // 跳转后获取路由参数 this.$route.query.userId- 动态路由
kotlin 复制代码 this.$router.push('/users/${userId}'); // 路由配置 { path: '/users/:userId', name: 'users', component: User } // 跳转后获取路由参数 this.$route.params.userId - 通过
Vue Router中的常用路由模式和原理?
- hash 模式:
location.hash的值就是url中#后面的东西。它的特点在于:hash虽然出现url中,但不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面。- 可以为hash的改变添加监听事件
window.addEventListener("hashchange", funcRef, false),每一次改变hash (window.location.hash),都会在浏览器的访问历史中增加一个记录,利用hash的以上特点,就可以实现前端路由更新视图但不重新请求页面的功能了。
特点:兼容性好但是不美观
- history 模式:
利用 HTML5 History Interface 中新增的pushState()和replaceState()方法。
这两个方法应用于浏览器的历史记录栈,在当前已有的back、forward、go的基础上(使用popState()方法),他们提供了对历史记录进行修改的功能。
这两个方法有个共同点:当调用他们修改浏览器历史记录栈后,虽然当前url改变了,但浏览器不会刷新页面,这就为单页面应用前端路由“更新视图但不重新请求页面”提供了基础
特点:虽然美观,但是刷新会出现 404 需要后端进行配置。
动态路由?
很多时候,我们需要将给定匹配模式的路由映射到同一个组件,这种情况就需要定义动态路由。例如,我们有一个 User组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用动态路径参数(dynamic segment)来达到这个效果:{path: '/user/:id', compenent: User},其中:id就是动态路径参数。
对Vuex的理解?
-
概念:
Vuex 是 Vue 专用的状态管理库,它以全局方式集中管理应用的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 -
解决的问题:
Vuex 主要解决的问题是多组件之间状态共享。利用各种通信方式,虽然也能够实现状态共享,但是往往需要在多个组件之间保持状态的一致性,这种模式很容易出问题,也会使程序逻辑变得复杂。Vuex 通过把组件的共享状态抽取出来,以全局单例模式管理,这样任何组件都能用一致的方式获取和修改状态,响应式的数据也能够保证简洁的单向流动,使代码变得更具结构化且易于维护。 -
什么时候用:
Vuex 并非是必须的,它能够管理状态,但同时也带来更多的概念和框架。如果我们不打算开发大型单页应用或应用里没有大量全局的状态需要维护,完全没有使用Vuex的必要,一个简单的 store 模式就够了。反之,Vuex将是自然而然的选择。 -
用法:
Vuex 将全局状态放入state对象中,它本身是一颗状态树,组件中使用store实例的state访问这些状态;然后用配套的mutation方法修改这些状态,并且只能用mutation修改状态,在组件中调用commit方法提交mutation;如果应用中有异步操作或复杂逻辑组合,需要编写action,执行结束如果有状态修改仍需提交mutation,组件中通过dispatch派发action。最后是模块化,通过modules选项组织拆分出去的各个子模块,在访问状态(state)时需注意添加子模块的名称,如果子模块有设置namespace,那么提交mutation和派发action时还需要额外的命名空间前缀。
页面刷新后Vuex 状态丢失怎么解决?
Vuex 只是在内存中保存状态,刷新后就会丢失,如果要持久化就需要保存起来。
localStorage就很合适,提交mutation的时候同时存入localStorage,在store中把值取出来作为state的初始值即可。
也可以使用第三方插件,推荐使用vuex-persist插件,它是为 Vuex 持久化储存而生的一个插件,不需要你手动存取storage,而是直接将状态保存至 cookie 或者 localStorage中。
关于 Vue SSR 的理解?
SSR即服务端渲染(Server Side Render),就是将 Vue 在客户端把标签渲染成 html 的工作放在服务端完成,然后再把 html 直接返回给客户端。
- 优点:
有着更好的 SEO,并且首屏加载速度更快。 - 缺点:
开发条件会受限制,服务器端渲染只支持 beforeCreate 和 created 两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于 Node.js 的运行环境。服务器会有更大的负载需求。
了解哪些 Vue 的性能优化方法?
- 路由懒加载。有效拆分应用大小,访问时才异步加载。
keep-alive缓存页面。避免重复创建组件实例,且能保留缓存组件状态。v-for遍历避免同时使用v-if。实际上在 Vue 3 中已经是一个错误用法了。- 长列表性能优化,可采用虚拟列表。
v-once。不再变化的数据使用v-once。- 事件销毁。组件销毁后把全局变量和定时器销毁。
- 图片懒加载。
- 第三方插件按需引入。
- 子组件分割。较重的状态组件适合拆分。
- 服务端渲染。
pinia和vuex的区别:
- pinia它没有mutation,他只有state,getters,action【同步、异步】使用他来修改state数据
- pinia他默认也是存入内存中,如果需要使用本地存储,在配置上比vuex麻烦一点
- pinia语法上比vuex更容易理解和使用,灵活。
- pinia没有modules配置,没一个独立的仓库都是definStore生成出来的
- pinia state是一个对象返回一个对象和组件的data是一样的语法
Vuex 和 Pinia 的优缺点:
Pinia的优点:
- 完整的 TypeScript 支持:与在 Vuex 中添加 TypeScript 相比,添加 TypeScript 更容易
- 极其轻巧(体积约 1KB)
- store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或 MapAction 辅助函数,这在Vuex中很常见
- 支持多个Store
- 支持 Vue devtools、SSR 和 webpack 代码拆分
Pinia的缺点:
- 不支持时间旅行和编辑等调试功能
vuex的优点:
- 支持调试功能,如时间旅行和编辑
- 适用于大型、高复杂度的Vue.js项目
vuex的缺点:
- 从 Vue 3 开始,getter 的结果不会像计算属性那样缓存
- Vuex 4有一些与类型安全相关的问题
何时使用Pinia,何时使用Vuex:
- 由于Pinea是轻量级的,体积很小,它适合于中小型应用。它也适用于低复杂度的Vue.js项目,因为一些调试功能,如时间旅行和编辑仍然不被支持。
- 将 Vuex 用于中小型 Vue.js 项目是过度的,因为它重量级的,对性能降低有很大影响。因此,Vuex 适用于大规模、高复杂度的 Vue.js 项目。
pinia和vuex在vue2和vue3都可以使用,一般来说vue2使用vuex,vue3使用pinia。
vue2和vue3的区别有以下8点:1、双向数据绑定原理不同;2、是否支持碎片;3、API类型不同;4、定义数据变量和方法不同;5、生命周期钩子函数不同;6、父子传参不同;7、指令与插槽不同;8、main.js文件不同。
vue2和vue3的区别
1、双向数据绑定原理不同
vue2:vue2的双向数据绑定是利用ES5的一个APIObject.definePropert() 对数据进行劫持,结合发布订阅模式的方式来实现的。
vue3:vue3中使用了ES6的Proxy API对数据代理。相比vue2.x,使用proxy的优势如下:
- defineProperty只能监听某个属性,不能对全对象监听
- 可以省去for in,闭包等内容来提升效率(直接绑定整个对象即可)
- 可以监听数组,不用再去单独的对数组做特异性操作vue3.x可以检测到数组内部数据的变化。
2、是否支持碎片
vue2:vue2不支持碎片。
vue3:vue3支持碎片(Fragments) ,就是说可以拥有多个根节点。
3、API类型不同
vue2:vue2使用选项类型api,选项型api在代码里分割了不同的属性:data,computed,methods等。
vue3:vue3使用合成型api,新的合成型api能让我们使用方法来分割,相比于旧的api使用属性来分组,这样代码会更加简便和整洁。
4、定义数据变量和方法不同
vue2:vue2是把数据放入data中,在vue2中定义数据变量是data(){} ,创建的方法要在methods:{} 中。
vue3:,vue3就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。使用以下三个步骤来建立反应性数据:
- 从vue引入reactive;
- 使用reactive() 方法来声明数据为响应性数据;
- 使用setup()方法来返回我们的响应性数据,从而template可以获取这些响应性数据。
5、生命周期钩子函数不同
vue2:vue2中的生命周期:
- beforeCreate 组件创建之前
- created 组件创建之后
- beforeMount 组价挂载到页面之前执行
- mounted 组件挂载到页面之后执行
- beforeUpdate 组件更新之前
- updated 组件更新之后
vue3:vue3中的生命周期:
- setup 开始创建组件
- onBeforeMount 组价挂载到页面之前执行
- onMounted 组件挂载到页面之后执行
- onBeforeUpdate 组件更新之前
- onUpdated 组件更新之后
而且vue3.x 生命周期在调用前需要先进行引入。除了这些钩子函数外,vue3.x还增加了onRenderTracked 和onRenderTriggered函数。
6、父子传参不同
vue2:父传子,用props,子传父用事件 Emitting Events。在vue2中,会调用this$emit然后传入事件名和对象。
vue3:父传子,用props,子传父用事件 Emitting Events。在vue3中的setup()中的第二个参数content对象中就有emit,那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。
7、指令与插槽不同
vue2:vue2中使用slot可以直接使用slot;v-for与v-if在vue2中优先级高的是v-for指令,而且不建议一起使用。
vue3:vue3中必须使用v-slot的形式;vue3中v-for与v-if,只会把当前v-if当做v-for中的一个判断语句,不会相互冲突;vue3中移除keyCode作为v-on的修饰符,当然也不支持config.keyCodes;vue3中移除v-on.native修饰符;vue3中移除过滤器filter。
8、main.js文件不同
vue2:vue2中我们可以使用pototype(原型) 的形式去进行操作,引入的是构造函数。
vue3:vue3中需要使用结构的形式进行操作,引入的是工厂函数;vue3中app组件中可以没有根标签。
拓展阅读
setup()函数特性
- setup()函数接收两个参数:props、context(包含attrs、slots、emit)。
- setup函数是处于生命周期beforeCreated和created俩个钩子函数之前。
- 执行setup时,组件实例尚未被创建(在setup()内部,this不会是该活跃实例得引用,即不指向vue实例,Vue为了避免我们错误得使用,直接将setup函数中得this修改成了undefined)。
- 与模板一起使用时,需要返回一个对象。
- 因为setup函数中,props是响应式得,当传入新的prop时,它将会被更新,所以不能使用es6解构,因为它会消除prop得响应性,如需解构prop,可以通过使用setup函数中得toRefs来完成此操作。
- 在setup()内使用响应式数据时,需要通过 .value 获取。
- 从setup() 中返回得对象上得property 返回并可以在模板中被访问时,它将自动展开为内部值。不需要在模板中追加.value。
- setup函数只能是同步的不能是异步的。