vue

295 阅读17分钟

vue和jquery区别

  • jq直接操作dom,vue不直接操作dom,vue的数据与视图是分开的,只需要操作数据即可
  • jq操作dom行为是频繁的,vue利用虚拟dom,大大提高了性能
  • vue集成的一些库比如vuex、router等大大提高了开发效率

vue的优势

  • 数据视图分离,数据双向绑定
  • 组件化
  • 虚拟dom,运行速度快
  • 单页面应用,局部刷新,提高访问速度和用户体验
  • 与第三方ui框架配合使用良好

vue2、vue3的生命周期有哪些及每个生命周期做了什么?

vue2vue3 options APIvue3 composition API做了什么
beforeCreatebeforeCreatesetup代替创建一个空白Vue实例;data、method尚未被初始化,不可使用
createdcreatedsetup代替Vue实例初始化完成,完成响应式绑定; data、method都可以初始化使用,可调用;尚未渲染模板
beforeMountbeforeMountonBeforeMount编译模板,调用render生成vdom;还没有开始渲染dom
mountedmountedonMounted完成dom渲染;组件渲染完成;开始由创建阶段进入运行阶段
beforeUpdatebeforeUpdateonBeforeUpdatedata发生变化之后;准备更新dom(尚未更新dom)
updatedupdatedonUpdateddata发生变化,且dom更新完成(ps注意:不要在updated中修改data,可能会导致死循环)
beforeDestroybeforeUnmountonBeforeUnmount组件即将进入销毁(尚未销毁,可以正常使用);可移除解绑一些全局事件、自定义事件
destroyedunmountedonUnmounted组件、子组件销毁完成
  • v3 composition api生命周期

    setup 代替了beforeCreate和created

    使用hooks函数形式,如mounted改为onMounted,updated改为onUpdated

父子生命周期

  • 创建阶段

    父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

  • 更新阶段

    父beforeUpdate->子beforeUpdate->子updated->父updated

  • 销毁阶段

    父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

接口请求一般放在哪个生命周期中?为什么要这样做?

接口请求可以放在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。

但是推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面 loading 时间
  • SSR 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于代码的一致性
  • created 是在模板渲染成 html 前调用,即通常初始化某些属性值,然后再渲染成视图。如果在 mounted 钩子函数中请求数据可能导致页面闪屏问题

vue2、vue3区别

  • API
  • 生命周期
  • 响应式
  • vite

vue2、vue3响应式原理

vue2

通过Object.defineProperty将对象所有的property转化成getter和setter,每一个组件对应一个watcher实例,它会在组件渲染的过程中把接触过的数据property记录为依赖,当依赖项的setter触发时会通知watcher来派发更新。

  • 数据劫持:Vue2使用Object.defineProperty方法将对象的每一个属性转化成gettersetter。这样,当访问或修改对象的属性时,就可以触发相应的gettersetter函数,从而进行依赖收集和派发更新。
  • 依赖收集:在渲染视图时,Vue会将watcher(观察者)和具体的属性通过发布订阅者模式管理起来。这样,当数据发生变化时,就能更精准地更新视图。
  • 派发更新:当数据变化时,通过dep(依赖管理器)来执行watchernotify方法,通知所有依赖该数据的watcher进行更新。
vue3
  • 基于proxy实现对getter/setter的代理,在getter中收集依赖,修改数据触发setter。
  • proxy只能代理对象,对于值类型的数据通过包裹一层,也就是我们使用的ref来设成响应式对象
  • Proxy只会代理对象的第一层,vue3中会判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive方法做代理, 这样就实现了深度观测

vue2、vue3优缺点

vue2优点
  1. 渐进式:Vue2可以逐步地以不同的方式使用,只引入需要的部分,这使得它非常灵活和易于集成。
  2. 组件化:Vue2鼓励开发者将UI界面拆分成一个个独立的、可复用的组件,这有助于提升开发效率和项目的可维护性。
  3. 轻量级:Vue2的库体积相对较小,加载速度快,适合构建大型应用。
  4. 虚拟DOM:Vue2使用虚拟DOM来提高性能,减少真实DOM的操作次数,提升应用的渲染效率。
  5. 响应式:Vue2的响应式系统能够自动追踪数据的变化,并在数据变化时更新视图。
  6. 单页面路由:Vue2支持单页面应用(SPA)的开发,通过vue-router可以实现页面的无刷新跳转。
vue2缺点
  • 深度监听,需要递归到底,一次性计算量大(需要递归到底+Object.defineProperty)
  • 无法监听新增属性、删除属性,需要用到Vue.set和Vue.delete
  • 无法原生监听数组,需要特殊处理(重新定义数组原型)
vue3优点
  1. 更小巧的体积:Vue3在保留功能的同时,通过对代码重构和优化,将库的大小减少了约30%,降低了前端页面加载时间和占用空间。
  2. 更高效的渲染机制:Vue3通过异步渲染和编译优化等措施,大幅提升了页面渲染的效率,特别是在处理大量数据和复杂组件时效果更为明显。
  3. 更简单的组件开发方式:Vue3引入了Composition API,这是一种基于函数的API,它让组件代码更加简洁和可复用,提升了开发者的编码体验。
  4. 更严格的TypeScript支持:Vue3对TypeScript进行了更严格的支持,提供了更加完整、准确的类型检查和错误提示,有助于开发者编写更加健壮的代码。
  5. 更好的可维护性和拓展性:通过组件化和模块化的方式,Vue3极大地增加了代码的可维护性和拓展性,让开发者在项目开发过程中更加容易进行代码管理和扩展。
vue3缺点
  • 学习成本
  • 迁移成本
  • 生态完善程度
  • proxy为es6新特性,旧版本浏览器会出现兼容问题

Vue2相关

vue2如何监测数据变化

  • 使用了函数劫持的方式,重写了数组的方法,
  • Vue将data中的数组进行了原型链重写,指向了自己定义的数组原型方法。这样当调用数组api时,可以通知依赖更新。
  • 如果数组中包含着引用类型,会对数组中的引用类型再次递归遍历进行监控。这样就实现了监测数组变化
// 重新定义数组原型
const oldArrayProper = Array.prototype;
const arrProto = Object.create(oldArrayProper); // 创建新对象,原型指向oldArrayProper, 再扩展新方法不会影响到原型
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(methodName => { 
    // 上述方法会改变原数组,所以需要重写
    arrProto[methodName] = function(arguments) {
        updateView(); // 更新视图
        oldArrayProper[methodName].call(this, ...arguments)
    }
})

MVVM

  • M代表Model数据,V代表View视图,VM-ViewModel是他们之间的桥梁,实现了数据到视图和视图到视图的转化

MVC、MVP、MVVM

mvc理论上是单向数据流,其中controller负责业务逻辑,每个事件都会经过controller, 理论上可行,但是实际开发中view已经具备独立处理事件的能力,当每个事件都经过c的时候会变得非常臃肿 而且v和c一一对应,过于紧密的连接使得无法复用

mvp中p处理业务逻辑,v和m分开他们是独立的,p需要手动将v和m之间的数据进行同步,使得p非常沉重,维护也比较困难

mvc和mvp的对比: 相同点:p、c负责业务逻辑,m负责数据管理,v负责视图 不同点:mvp中v和m是分开的,而mvc在实际过程中v是可以操作m的

mvvm是model-view-viewmodel的简写, 是一种开发模式,它实现了视图和数据的分离, model是数据,view是视图,viewmodel是他们之间的桥梁, 实现了视图到数据、数据到视图的转化,也就是双向数据绑定, 使用这种开发模式的框架有vue和react

v-model 双向绑定的原理是什么?

v-model本质就是一个语法糖,可以看成是value + input方法的语法糖。

  • input元素的value=this.xxx
  • 绑定input事件 this.xxx = $event.target.value
  • data更新触发re-render
// 父组件
<Test v-model="text">

// 子组件Test
<template>
    <input type="text" :value="text" @input="$emit('change', $event.target.value)" />
</template>

export default {
    model: {
        prop: 'text', // 和props里面的text字段对应, 绑定到value
        event: 'change' // 与emit事件对应
    },
    props: {
        text: {
            type: String,
            default: ''
        }
    }
}

数据响应式和双向绑定的主要区别在于: 数据响应式是数据驱动视图更新 双向绑定是数据和视图相互驱动更新

vue2 diff算法

  • O(n^3)-->O(n)做出的调整:(diff算法特点)
  • 只比较同一层级,不跨级比较
  • tag不同则直接删掉重建,不再深度比较
  • tag和key两者都相同则认为是相同节点,不再重复对比

diff算法是vdom中最核心、最关键的部分, vdom用js对象模拟dom结构(vnode),数据发生变化时,进行新旧vnode对比,计算出最小变更,有效控制dom操作

vue组件通信

  • 父->子 props
  • 子->父 emitemit、on
  • attrsattrs、listener、provider+inject、$refs
  • 跨级组件:vuex、EventBus

父组件如何得知子组件的生命周期:子组件在每个生命周期中定义emit事件来通知父组件

v-if和v-show的异同、使用场景

  • 相同点:都能控制元素的显示与隐藏
  • 不同点:
  1. 实现方式:v-if是根据条件渲染或销毁元素来实现,v-show是利用cssdisplay:none来实现的。
  2. 性能消耗:v-if 相比 v-show 开销更大的(直接操作dom节点增加与删除)

如果需要非常频繁地切换,则使用 v-show 较好 如果在运行时条件很少改变,则使用 v-if 较好

vue为何使用key

必须使用key,不能是index或者random key是给每一个vnode的唯一id,也是diff算法的一种优化策略,可以更加准确快速的找到对应的节点, diff算法中通过tag和key来判断是否是同一节点sameNode 可以减少渲染次数,提示渲染性能

keep-alive

  • 工作原理

keep-alive可以实现组件缓存,当组件切换时不会对当前组件进行卸载。

两个属性include/exclude,控制组件是否进行缓存

两个生命周期activated/deactivated,用来得知当前组件是否处于活跃状态。

  • 实现原理
  1. 缓存对象<keep-alive>组件内部维护了一个cache对象和一个keys数组,用于存储被缓存的组件实例和它们的键(key)。
  2. 组件匹配:在渲染过程中,<keep-alive>会检查当前要渲染的组件是否满足缓存条件(即是否在include中且不在exclude中)。如果满足条件,则尝试从cache中查找该组件的实例。
  3. 缓存命中:如果cache中存在该组件的实例(即命中缓存),则将该实例的componentInstance赋值给当前要渲染的vnodecomponentInstance属性,并更新keys数组,以保证最近使用的组件实例始终在数组末尾。
  4. 缓存未命中:如果cache中不存在该组件的实例(即未命中缓存),则将该vnode及其组件实例添加到cachekeys中。如果此时cache的大小超过了max属性指定的限制,则根据LRU策略移除最久未使用的组件实例。
  5. 生命周期钩子:当组件被激活(即重新挂载到DOM上)时,会触发activated钩子函数;当组件被缓存(即从DOM上移除但保留在缓存中)时,会触发deactivated钩子函数。
  6. 缓存销毁:当<keep-alive>组件被销毁时,它会遍历cache对象,并销毁所有缓存的组件实例,以释放内存空间。

原理: 内部维护了一个cache对象和一个keys数组,用于存储被缓存的组件实例和它们的键(key) created阶段会将组件实例存入cachekey存入keys mounted阶段会监听includeexclude,检查当前要渲染的组件是否满足缓存条件

使用场景: 缓存组件 频繁切换,不需要重复渲染(如tab页) vue性能优化

nextTick 的作用是什么?他的实现原理是什么?

主要作用是在当前数据变化后等待 DOM 更新完成,然后执行特定的操作。

在 Vue 2 中,Vue.nextTick 的实现依赖于 MutationObserver 或 setTimeout。其基本原理如下:

  1. 依赖收集与变更检测:当 Vue 检测到数据变化时,会将这些变更放入一个异步队列中。
  2. 异步更新:Vue 使用 MutationObserver(如果可用)或 setTimeout 来创建一个微任务或宏任务,在这些任务中执行队列中的所有变更。
  3. nextTick 回调Vue.nextTick 接收一个回调函数,这个回调函数会在所有的 DOM 更新完成后执行。
function nextTick(callback) {
  const p = Promise.resolve();
  p.then(callback);
 
  // 兼容性处理,如果 Promise 不可用,则使用 setTimeout
  if (!isUsingMicroTask) {
    setTimeout(callback, 0);
  }
}

mixin

场景: 多个组件有相同的逻辑,抽离出来

mixin问题

  • 变量来源不明确,不利于阅读
  • 多mixin可能会造成命名冲突
  • mixin和组件可能出现多对多的关系,复杂度高(一个组件引入多个mixin,或者多个组件引入一个mixin)

vue3中提供了hooks作为一种更新、更清晰的逻辑复用方法

优点

- Hooks 提供了一种更清晰的复用逻辑的方式,因为每个 hook 都封装了一个独立的逻辑块。
- 相比于 mixin,hooks 的来源更明确,代码的可读性和可维护性更高。
- Hooks 可以更好地与 TypeScript 集成,提供类型检查和自动补全等特性。

比较与总结

  1. 复用性:Mixin 和 hooks 都提供了代码复用的功能,但 hooks 的复用方式更加清晰和灵活。
  2. 可读性:Hooks 的代码结构更加清晰,因为它们将逻辑封装在独立的函数中,而 mixin 的逻辑则分散在组件的各个部分。
  3. 可维护性:Hooks 提供了更好的可维护性,因为每个 hook 都可以单独测试和调试。而 mixin 的合并策略可能会导致一些难以追踪的问题。
  4. 集成性:Hooks 与 TypeScript 的集成更加紧密,提供了更好的类型检查和开发体验。

slot插槽

  • 基本使用
// 父组件
<Test>
    我是slot内容
</Test>

// 子组件Test
<template>
    <div>
        <slot>
            默认值,如果没有传入则显示这段文字,反之不显示
        </slot>
    </div>
</template>

  • 作用域插槽(父组件使用子组件data)
// 父组件
<Test>
   <template v-slot="childSlotData">
    {{childSlotData.slotData}}
   </template>
</Test>

// 子组件Test
<template>
    <div>
        <slot :slotData="title"></slot>
    </div>
</template>

data() {
    return {
        title: '子组件内容'
    }
}
  • 具名插槽
// 父组件
    <Test>
    <p>未命名的slot内容</p>
   <template v-slot:slot1>
    slot1插槽内容
   </template>
  <template v-slot:slot2>
   slot2插槽内容
  </template>
</Test>

//子组件Test
<template>
    <div>
        <slot></slot>
        <slot name="slot1"></slot>
        <slot name="slot2"></slot>
    </div>
</template>

动态组件

// 用法
<component :is="component-name" />
需要根据数据,动态渲染的场景。即组件类型不确定

<div v-for="(item, key) in data" :key="key">
    <component :is="item.name" />
<div/>

异步组件

异步加载:
import() 函数
按需加载,异步加载大组件(echart等)

export default {
    component: {
        AsyncDemo: () => import('路径')
    }
}

Vuex的几种属性--state、getter、mutation、action、modules

  • state 基本数据(数据存放池)
  • getter 从基本数据派生出来的数据
  • mutation 提交修改数据的方法 同步
  • action 可以整合mutation,可以处理异步
  • modules 模块化vuex

Vue 组件的 data 为什么必须是函数

一个组件被复用多次的话,也就会创建多个实例。本质上,这些实例用的都是同一个构造函数。如果data是对象的话,对象属于引用类型,会影响到所有的实例。所以为了保证组件不同的实例之间data不冲突,data必须是一个函数。

说一下 watch(侦听属性) 与 computed(计算属性) 的区别是什么?以及他们的使用场景分别是什么?

都可以监听数据变化。

  • watch是监听某一个值变化,执行对应操作,第一次不会触发(除非设置inmediate:true),支持异步,watch是函数时接收两个参数,新值和旧值。

    • 使用场景:需要在数据变化时执行一些特定操作的场景,如异步操作、复杂的逻辑处理等。
  • computed会生成新的值,有缓存,监听的数据变化才会变化,computed为函数时有get和set方法。

    • 使用场景:需要根据多个数据来计算得到新值的场景

一起使用时v-if和v-for的优先级

  • Vue2v-for的优先级高于v-if

    这意味着Vue会先遍历列表中的每个元素,然后再对每个元素进行条件判断,它会导致渲染效率下降。

  • Vue3v-if的优先级高于v-for

    这意味着 v-if 将无法访问到 v-for 里面的变量

    解决办法

    • 条件出现在循环内部时:结合computed将数组进行过滤后再去遍历
    • 条件出现在外层时:使用template标签进行包裹,它不会生成dom标签渲染到页面上,在这一层进行v-if判断,然后在内部进行v-for循环

权限管理

  • 接口权限:请求拦截,头部携带token;响应拦截,状态判断
  • 菜单权限:beforeEach进行判断,addRoutes动态添加路由
  • 路由权限:路由跳转时用beforeEach进行判断
  • 按钮权限:v-if或自定义指令

路由传参

  • name + params 地址栏不可见,刷新会消失
  • path + query 显示在地址栏,刷新不会消失

vue-router

  • 常用的路由模式hash(默认)、h5 history(后者需要server端支持)
  • 路由配置(动态路由、懒加载)
  • 动态路由{path: '/user/:id', component: User},以冒号开头
  • 懒加载/异步加载 {path: '/user/:id', component: () => import(./../user)}

前端路由

  • hash
  1. hash变化会触发浏览器的前进、后退,不会刷新页面(spa必须的特点)
  2. hash永远不会提交到server端
  3. onhashchange监听浏览器前进后退
  • h5 history
  1. 用规范的路由,但跳转时不刷新页面
  2. 需要后端支持
  3. history.pushState(...)打开一个新路由
  4. window.onpopstate监听浏览器前进后退
  • 路由选择
  1. to B用hash,简单易用,对url规范不敏感
  2. to C可以考虑h5 history,需要后端支持
  • history模式下部署到服务器会出现404

    vue是单页面应用只会产出一个index.html,输入其他路由会找不到资源, 需要后端在nginx配置将所有路由重定向到index

static和assets区别

相同点: 都可以放置静态资源

区别:

  • static放第三方资源,assets放自己写的css和js等文件
  • static目录直接上传到服务器,assets会经过build打包放到static里面一起上传

vue中如何解决跨域问题

  • JSONP:在客户端定义全局onSuccess函数,通过script发送请求,服务端返回一串字符串,在客户端当作一段js执行,调用onSuccess函数
  • CORS:设置Access-Control-Allow-Origin响应头
  • Proxy:vue.config.js中配置、nginx配置

vue.config.js配置

amodule.exports = {
    devServer: {
        host: '127.0.0.1',
        port: 8084,
        open: true,// vue项目启动时自动打开浏览器
        proxy: {
            '/api': { // '/api'是代理标识,用于告诉node,url前面是/api的就是使用代理的
                target: "http://xxx.xxx.xx.xx:8080", //目标地址,一般是指后台服务器地址
                changeOrigin: true, //是否跨域
                pathRewrite: { // pathRewrite 的作用是把实际Request Url中的'/api'""代替
                    '^/api': "" 
                }
            }
        }
    }
}


通过axios发送请求中,配置请求的根路径
axios.defaults.baseURL = '/api'

nginx配置

server {
    listen    8080;
    # server_name www.xxx.com;
    location / {
        root  /var/www/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
    location /api {
        proxy_pass  http://127.0.0.1:3000;
        proxy_redirect   off;
        proxy_set_header  Host       $host;
        proxy_set_header  X-Real-IP     $remote_addr;
        proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
}

实际工作中vue优化

1、v-if vs v-show 销毁 vs css隐藏

2、v-for使用key

3、使用computed缓存

4、keep-alive缓存组件 频繁切换的组件,如tabs,不要过度使用

5、异步组件 如体积较大的组件,复杂表格等

6、服务端渲染ssr nuxt.js

按需优化,不要为了优化而优化

SPA首屏优化方式

  • 减小入口文件积

  • 静态资源本地缓存

    后端返回资源问题:采用HTTP缓存,设置Cache-ControlLast-ModifiedEtag等响应头;采用Service Worker离线缓存

    前端合理利用localStorage

  • UI框架按需加载

  • 图片资源的压缩

  • 组件重复打包

    在webpack中使用3次及以上的包抽离出来,放进公共依赖文件,避免了重复加载组件

  • 开启GZip压缩

  • 使用SSR

减少首屏渲染时间的方法有很多,总的来讲可以分成两大部分 :资源加载优化 和 页面渲染优化 image.png

SSR

SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端

SSR有着更好的SEO、并且首屏加载速度更快等优点。不过它也有一些缺点,比如我们的开发条件会受到限制,服务器端渲染只支持beforeCreatecreated两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求。

Vue3相关

ref、toRef、toRefs区别

  • ref用于生成值类型的响应式数据,通过.value来调用修改,模版中不需要加.value
const ageRef = ref(18);
ageRef.value = 20

PS:为何需要ref?

返回值类型会丢失响应式(proxy只能代理对象)
如再setup、computed、合成函数中都有可能返回值类型
vue如果不定义ref,用户将自造ref,反而混乱


PS:为何需要.value

ref是一个对象(不丢失响应式), value存储值
通过.value属性的get和set
用于模板、reactive对象是不需要.value,其他情况需要
  • toRef 将响应式数据的某一个属性变成ref
const state = reactive({
  age: 18,
  name:'jubao'
});
const ageRef = toRef(state, 'age')
// 两者保持引用关系
  • toRefs 将reactive响应式对象变为普通对象, 对象的每个属性都是对应的ref,解决reactive对象不能直接解构的问题(直接结构会失去响应式)
    const stateRefs = toRefs(state);
    const { age: ageRef, name: nameRef } = stateRefs;
    return {
      ageRef,
      nameRef
    }
   // 两者保持引用关系
   // 模板里面使用{{ageRef}}和{{nameRef}}
PS:为何需要toRef、toRefs

初衷:不丢失响应式的情况下,把对象数据分解/扩散
前提:响应式对象(reactive封装的)而非普通对象
不创造响应式,而是延续响应式

composition API和options API对比

composition API: 更好的代码组织,更好的逻辑复用,更好的类型推导

  • 小型项目 业务逻辑简单用options api
  • 中大型项目 逻辑复杂用composition api
  • 不建议共用,混乱

composition api和react hooks对比

  • composition api的setup只会调用一次,它是作为created和beforeCreate生命周期来处理的,而react hooks会被多次调用
  • 前者无需useMemo useCallBack,因为setup只会调用一次
  • 前者无需考虑调用顺序,而后者需要保证hooks的顺序一致
  • 前者reactive+ref比后者useState更难理解

v3比v2快的原因(性能体现)

  • 使用proxy
  • patchFlag进行动态标记
  • hoistStatic将静态节点提升到父作用域,多个静态节点进行合并处理
  • cacleHandle缓存事件
  • SSR优化,静态节点直接输出字符串
  • tree-shaking消除没有用到的代码,减少代码体积

v3比v2优势

  • 体积更小(tree-shaking去除无用代码)
  • 性能更好***
  • 更好的ts支持***(几乎都是函数)
  • 更好的代码组织(composition API)
  • 更好的逻辑抽离(composition API)
  • 更多新功能

v3升级了哪些新功能

  • 1、createApp
v2
const app = new Vue({...})
Vue.use(..)

v3
const app = Vue.createApp({...})
app.use(...)
  • 2、emits属性
子组件:
export default {
    emits: ['xxx'];
    setup(props, {emit}) {
        emit(xxx)
    }
}

<script setup>
const props = defineProps(obj/arr)
const emit = defineEmits(['xxx'])
emit('xxx')
</script>
  • 3、生命周期
  • 4、多事件
<button @click="one($event), two($event)">多事件</button>
  • 5、Fragment(template里面可以有多个节点)
  • 6、移除.sync
v2
<Test :title.sync="title"></Test>

v3
<Test v-model:title="title"></Test>
  • 7、异步组件的写法
v2:
new Vue({
    ...
    components: {
        'Test': () => import('./Test.vue')
    }
})

v3:
createApp({
    ...
    components: {
        Test: defineAsyncComponent(() => import('./Test.vue'))
    }
})
  • 8、移除filter
  • 9、Teleport弹窗
  • 10、Suspense(有两个插槽)
<Suspense>
  <!-- 具有深层异步依赖的组件 -->
  <Dashboard />

  <!-- 在 #fallback 插槽中显示 “正在加载中” -->
  <template #fallback>  // 具名插槽
    Loading...
  </template>
</Suspense>
  • 11、Composition API
  • reactive【返回响应式代理】
  • ref相关【返回响应式且可变的引用对象,ref优于reactive】
  • readonly
  • setup
  • watch和watchEffect
  • 生命周期钩子函数

场景题

如何件套路由参数变化

  • watch 监听'$route'的to和from两个参数
  • 通过beforeRouteUpdate获取to、from、next参数变化

如何捕获vue组件错误信息

  • 通过window.error监听其他js错误以及异步组件的报错
  • 通过errorCaptured钩子监听下级组件错误,返回false可以阻止向上传播
  • 通过errorHandle监听全局vue组件错误