vue面试题汇总

  • HTML篇
  • CSS篇
  • JS篇
  • TypeScript篇
  • React篇
  • 微信小程序篇
  • 前端面试题汇总大全(含答案超详细,HTML,JS,CSS汇总篇)-- 持续更新
  • 前端面试题汇总大全二(含答案超详细,Vue,TypeScript,React,微信小程序,Webpack 汇总篇)-- 持续更新

    vue面试题汇总

        • 1. 谈谈你对MVVM开发模式的理解?
        • 2. v-if 和 v-show 有什么区别?
        • 3. r o u t e 和 route和 routerouter区别
        • 4.vue自定义指令
        • 5.vue项目优化
        • 6.vue模板如何编译
        • 7.vue2响应式原理
        • 8.vue3响应式原理
        • 9.刷新浏览器后,Vuex的数据是否存在?如何解决?
        • 10.vue和react共同点?区别
        • 11.vue双向数据绑定原理
        • 12.computed和watch区别
        • 13.Vuex
        • 14.vuex辅助函数
        • 15.vuex模块化使用
        • 16.vue中mixin
        • 17.Vue中给对象添加新属性时,界面不刷新怎么办?
        • 18.vue组件通讯方式
        • 19.vue3setup的父传子怎么去写?
        • 20.setup可不可以直接写async和await?
        • 21.vue生命周期
        • 22.说说 Vue 中 CSS scoped 的原理
        • 23.$nextTick原理
        • 24.data是函数不是对象
        • 25.路由守卫
        • 26.vue设置全局变量
        • 27.vue中keep-alive
        • 28.vue插槽
        • 29.vue2和vue3区别
        • 30.Vue3.0 所采用的 Composition Api (组合式)与 Vue2.x 使用的 Options Api(选项式) 有什么不同?
        • 31.vue3中hook
        • 32.vue组件和插件的区别
        • 33.vue修饰符
        • 34.Vue路由中,history和hash两种模式有什么区别?
        • 35.params和query区别
        • 36.vue2中assets和vue3中public区别 ?
        • 37.单页应用如何提高加载速度?
        • 38.Vue父组件调用子组件的方法
        • 39.vue3中dom获取,ref在组件上使用
        • 40.渐进式框架理解
        • 41.页面初始化闪烁
        • 42.vue属性名和method名称一致出现什么问题
        • 43.class和style如何动态绑定
        • 44.vue遇到的坑
        • 45.v-if和v-for 优先级
        • 46.vue核心原理
        • 47.vue自带动画组件, transition
        • 48.vue-loader工作原理
        • 49.vue的diff算法
        • 50.vue和jquery区别
        • 51.说说你对 SPA 单页面的理解,它的优缺点分别是什么?
        • 52. 怎样理解 Vue 的单向数据流?
        • 53. 父组件可以监听到子组件的生命周期吗?
        • 54.Vue3.0 性能提升主要是通过哪几方面体现的
        • 55.什么是 MVVM?比之 MVC 有什么区别?什么又是 MVP ?
        • 56.vue中hook和react中hook区别
        • 57.Redux和Vuex的区别
        • 58.vue服务端渲染(SSR),解决了哪些问题?
        • 59.Vue 3.0中Treeshaking特性是什么,并举例进行说明?
        • 60. 虚拟 DOM 的优缺点?
        • 61. 虚拟 DOM 实现原理?
        • 62. Vue 中的 key 有什么作用?
        • 62. Object.defineProperty怎么用, 三个参数?,有什么作用啊?
        • 63.reactive与ref的区别?
        • 64.v-on可以监听多个方法吗?
        • 65.vue3中如何获取refs,dom对象的方式?vue2中如何使用?
        • 66.shallowReactive和shallowRef的区别
        • 67.provide与inject如何使用
        • 68.toRaw 与 markRaw是什么作用?
        • 69.Readonly和shallowReadonly理解
        • 70.toref和torefs区别
        • 71.学习 EventBus
        • 72.vue2过滤器(vue3取消)
        • 73. vue可以通过计算属性监听计算属性吗

1. 谈谈你对MVVM开发模式的理解?

MVVM是一种简化用户界面的实践驱动编程方式。在当前主流的前后端分离的开发模式中,MVVM模式的优越性日益体现,相较于经典的MVC模式,其对于程序模块的封装很好地解决了前后端信息交互的冗余和繁琐

MVVM分为Model、View、ViewModel三者。
Model 代表数据模型,数据和业务逻辑都在Model层中定义;
View 代表UI视图,负责数据的展示;
ViewModel 负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作;
Model 和 View 并无直接关联,而是通过 ViewModel 来进行联系的,Model 和 ViewModel 之间有着双向数据绑定的联系。因此当 Model 中的数据改变时会触发 View 层的刷新,View 中由于用户交互操作而改变的数据也会在 Model 中同步。
这种模式实现了 Model 和 View 的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作 dom。

为什么使用MVVM:低耦合,可复用,独立开发,可测试

2. v-if 和 v-show 有什么区别?

  • 手段
    • v-if是动态的向DOM树内添加或者删除DOM元素;
    • v-show是通过设置DOM元素的display样式属性控制显隐;
  • 编译
    • v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译;
    • v-show是在任何条件下,无论首次条件是否为真,都被编译,然后被缓存,而且DOM元素保留;
  • 性能消耗:
    • v-if有更高的切换消耗;
    • v-show有更高的初始渲染消耗

3. r o u t e 和 route和 routerouter区别

  • $route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数
  • $router 是“路由实例”想要导航到不同URL 对象包括了路由的跳转方法,钩子函数等。通过push、replace、go、back等方法,来实现页面间的跳转

4.vue自定义指令

vue指令

vue2

局部注册:directive选项

directives: {
 'focus': {
   bind(el, binding, vnode) {
     el.focus()
   }
 }
}

全局注册:main.js

Vue.directives('focus',{
	bind(el, binding, vnode) {
     el.focus()
   }
})

生命周期

  • bind:只调用一次,指令第一次绑到元素调用,用于初始化
  • inserted:被绑定元素插入父节点时调用
  • update:所在组件vnode更新调用
  • componentUpdate:指令在组件的vnode及子组件的vnode全部更新完调用
  • ubind:只调用一侧,指令解绑

vue3

局部注册:引入 import { Directive , DirectiveBinding } from ‘vue’ 分别校验vFocus,binding




全局注册:main.js,app.vue如上引入

import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)

app.directive('focus', {
 created(el, binding) {
     el.style.backgroundColor = binding.value.color;
     console.log(el, binding.value.color); // 'red'
 }
})

app.mount('#app')

生命周期

  • created 元素初始化的时候
  • beforeMount 指令绑定到元素后调用 只调用一次
  • mounted 元素插入父级dom调用
  • beforeUpdate 元素被更新之前调用
  • update 这个周期方法被移除 改用updated
  • beforeUnmount 在元素被移除前调用
  • unmounted 指令被移除后调用 只调用一次

5.vue项目优化

  • 代码层面
    • 长列表性能优化
    • 事件销毁, beforeDestroy生命周期函数内执行销毁逻辑。
    • 图片懒加载
    • 路由懒加载
    • 按需加载插件
    • v-if,v-for避免同时使用
    • v-if,v-show选择
    • keep-alive组件缓存
    • input防抖节流
  • 基础的web技术优化
    • 开启gzip压缩
    • 浏览器缓存
    • CDN加速
  • webpack优化

6.vue模板如何编译

Vue的模板编译就是将“HTML”模板编译成render函数的过程。这个过程大致可以分成三个阶段:

  • 解析阶段:将“HTML”模板解析成AST语法树;
  • 核心 parseHTML( template ,{}) Vue定义了很多匹配HTML的正则表达式 ,parseHTML根据正则匹配
  • parseHTML是解析模板字符串的“主线程”,它的第一个参数是要解析的模板字符串, 也就是单文件组件中最外层 所包裹的部分;第二个参数是一个选项对象,它会包含一些回调,以及一些配置项。
  • 选项对象:
    • start( tag, attrs, unary ) 匹配到开始标签时的回调,tag为当前标签的标签名,attrs为该标签上的属性列表,unary为当前标签是否为自闭合标签
    • end() 匹配到结束标签时的回调
    • chars(text) 匹配到文本节点的回调
    • comment(text) 匹配到注释节点的回调,其处理逻辑跟文本的处理逻辑类似
  • 优化阶段:从AST语法树中找出静态子树并进行标记(被标记的静态子树在虚拟dom比对时会被忽略,从而提高虚拟dom比对的性能);
    • 上面简单介绍过,优化阶段的工作就是标记静态子树,标记静态子树后主要有以下两个优点:
      • 生成虚拟dom的过程中,如果发现一个节点是静态子树,除了首次渲染外不会生成新的子节点树,而是拷贝已存在的静态子树;
      • 比对虚拟dom的过程中,如果发现当前节点是静态子树,则直接跳过,不需要进行比对。
    • 标记静态子树的过程分为两个步骤:
      • 遍历AST语法树,找出所有的静态节点并打上标记(注:当前节点及其所有子节点都是静态节点,当前节点才会被打上静态节点的标记)
      • 遍历经过上面步骤后的树,找出静态根节点,并打上标记(注:静态根节点是指本身及所有子节点都是静态节点,但是父节点为动态节点的节点,找到了静态根节点也就找到了“静态子树”)
  • 代码生成阶段:通过AST生成代码字符串,并最终生成render函数。

7.vue2响应式原理

vue 采用了几个核心部件 : ObserverDep WatcherScheduler

  • observer把一个普通的对象转换成响应式的对象
  • observer 把对象的每个属性通过 object.defineProperty 转换为带有 getter 和 setter 的属性
  • Dep 表示依赖, vue 会为响应式对象中的每一个属性,对象本身,数组本身创建一个 dep 实例,每个 dep 实例都可以做两件事情 :
  • 记录依赖:是谁在用我
  • 派发更新:我变了,我要通知那些用我的人
  • watcher 在函数执行的过程中,如果发生了依赖记录,那么 dep 就会把这个全局变量记录下来,表示有一个 wathcer 用到了我这个属性。
  • Scheduler 不会立即执行更新,通过nexttick异步更新

8.vue3响应式原理

通过Proxy(代理): 拦截对象中任意属性的变化,包括:属性值的读写,属性的增加,属性的删除等。

通过Reffect(反射): 对源对象的属性进行操作, Reflect不是一个函数对象,因此它是不可构造的。

9.刷新浏览器后,Vuex的数据是否存在?如何解决?

不存在

原因: 因为 store 里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值初始化。

我们有两种方法解决该问题:

  1. 使用 vuex-along
  2. 使用 localStorage 或者 sessionStroage

10.vue和react共同点?区别

共同点:

  • 数据驱动视图
  • 组件化
  • 都使用 Virtual DOM

不同点

  • 核心思想不同
    • vue定位就是尽可能的降低前端开发的门槛,让更多的人能够更快地上手开发。这就有了vue的主要特点:灵活易用的渐进式框架,进行数据拦截/代理,它对侦测数据的变化更敏感、更精确
    • react 定位就是提出 UI 开发的新思路 React推崇函数式编程(纯组件),数据不可变以及单向数据流,当然需要双向的地方也可以手动实现, 比如借助onChangesetState来实现。
  • 组件写法
    • React推荐的做法是JSX + inline style, 也就是把 HTML 和 CSS 全都写进 JavaScript 中
    • Vue 推荐的做法是 template 的单文件组件格式(简单易懂,从传统前端转过来易于理解),即 html,css,JS 写在同一个文件(vue也支持JSX写法)
  • diff算法
  • 响应式原理
    • vue2采用object.defineProperty ,vue3采用proxy,reflect
    • React基于状态机,手动优化,数据不可变,需要setState驱动新的state替换老的state。

11.vue双向数据绑定原理

简易实现:v-model分为两部分,通过v-bind绑定值,再通过v-on:input来通步修改值

原理

  • 需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
  • 通过dep来理清依赖关系,watcher在依赖中添加自身
  • compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
  • 待属性变动dep.notice()通知时,能调动watcher自身的update方法,并处罚compile回调渲染视图

12.computed和watch区别

computed计算属性,watch监听属性

  • 计算属性不在 data 中,它是基于data 或 props 中的数据通过计算得到的一个新值。watch 可以监听的数据来源:data,props,computed内的数据
  • component中有get和set方法,会默认缓存计算结果。watch不支持缓存,支持异步, immediate监听属性立即执行一次,deep开启深度监听

13.Vuex

Vuex是一种状态管理模式,存在的目的是共享可复用的组件状态。

主要包括以下几个模块:

  • State => 基本数据,定义了应用状态的数据结构,可以在这里设置默认的初始状态。
  • Getter => 从基本数据派生的数据,允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
  • Mutation => 是唯一更改 store 中状态的方法,且必须是同步函数。
  • Action => 像一个装饰器,包裹mutations,使之可以异步。用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
  • Module => 模块化Vuex,允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。

14.vuex辅助函数

mapState, mapMutations, mapActions, mapGetters

mapState和mapGetters:

  • 两者都放在 computed中,以mapState举例
import { mapState } from 'vuex'

computed中
computed:{
	...mapState(['data'])  //data是vuex存放的state中的属性,此时{{data}}可使用
}

mapMutations, mapActions:

  • 放在组件的methods属性中 。使用与上类似

15.vuex模块化使用

当我们开发的项目比较大时,store中的数据就可能比较多,这时我们store中的数据就可能变得臃肿,为了解决这一问题,我们就需要将store模块化(module)

前提:创建两份js文件,含有属性与vuex写法相同,需要通过 namespaced:true开启命名空间store/index.js:在modules中引入文件

使用:

  • 访问state数据:
    • 第一种方式:this.$store.state.moduleA.sum
    • 第二种方式: ...mapState('moduleA',['sum','number'])
  • action提交mutation
  • 第一种方式:需要传参this.$store.dispatch('moduleB/addZhang',{name:'小明',age:18}) ,无需传参this.$store.dispatch('moduleB/addServer')
  • 第二种方式:...mapActions('moduleB',['addZhang'])
  • getters计算属性
  • 第一种方式: this.$store.getters['moduleB/firstName']
  • 第二种方式:...mapGetters('moduleB',['firstName'])

16.vue中mixin

mixin(混入): 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。

本质其实就是一个js对象,它可以包含我们组件中任意功能选项,如datacomponentsmethods createdcomputed等等

我们只要将共用的功能以对象的方式传入 mixins选项中,当组件使用 mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来

具体使用:

  • 创建mixins.js文件
let mixin = {
    created() {
        console.log('我是mixin中的');
    },
    methods: {
        hellow() {
            console.log('你好');
        },
    },
}
export default mixin
  • 局部使用
import mixin from "./mixins";
export default {
  mixins: [mixin],
  mounted() {
    this.hellow();//你好
  },
};
  • 全局使用main.js
import { createApp } from 'vue'
import App from './App.vue'
import mixins from "./mixins";
const app = createApp(App)
app.mixin(mixins)
app.mount('#app')

17.Vue中给对象添加新属性时,界面不刷新怎么办?

原因:vue2响应式采用object.defineProperty进行劫持,那个添加新属性时,新的属性不会具有get和set方法,不是一个响应式所以界面不刷新

解决:Vue.set() 向响应式对象中添加一个property,并确保这个新 property 同样是响应式的

vue3通过proxy劫持和reflect映射实现响应式,不会有这个问题

18.vue组件通讯方式

  • 通过 props 传递
    • props校验:name:{type:String,required:true,default:默认值} required是否必要
  • 通过 $emit 触发自定义事件
  • 使用 ref
  • EventBus
  • Provide 与 Inject
  • Vuex

19.vue3setup的父传子怎么去写?

介绍三种方法:

第一种:使用vue2写法通过props和$emit

第二种:setup函数写法

  • setup(props,context),通过props接收数据,通过context.emit(‘调用父组件方法’,传递参数)

第三种:script中setup

  • vue3自带defineProps,defineEmits
const emits = defineEmits(["changeNumber"]);
// 也可以不赋值,取值通过{{num}}获取
const props = defineProps({
  num: {
    type: Number,
    default: () => [],
  },
  list: {
    type: Array,
  },
});
const changeNum = function () {
  emits("changeNumber", 888);
  //   console.log(11111111111);
};

20.setup可不可以直接写async和await?

可以

setup 语法糖中可直接使用 await,不需要写 async , setup 会自动变成 async setup

<script setup>
  import Api from '../api/Api'
  const data = await Api.getData()
  console.log(data)
</script>

21.vue生命周期

vue2

vue面试题汇总_第1张图片

beforeCreate – 首次访问data

created – 首次访问this生命周期

mounted – 页面展示

vue3

vue面试题汇总_第2张图片

区别

  • beforeCreate -> setup() 开始创建组件之前,创建的是data和method
  • created -> setup()
  • beforeMount -> onBeforeMount 组件挂载到节点上之前执行的函数。
  • mounted -> onMounted 组件挂载完成后执行的函数
  • beforeUpdate -> onBeforeUpdate 组件更新之前执行的函数。
  • updated -> onUpdated 组件更新完成之后执行的函数。
  • beforeDestroy -> onBeforeUnmount 组件挂载到节点上之前执行的函数。
  • destroyed -> onUnmounted 组件卸载之前执行的函数。dszhuoyi
  • activated -> onActivated 组件卸载完成后执行的函数
  • deactivated -> onDeactivated

22.说说 Vue 中 CSS scoped 的原理

添加scoped标签后会给组件中所有标签元素,添加一个唯一标识,这个唯一标识就是自定义属性,data-v-xxxxxxxx这样的字眼,同时对应的样式选择器也会添加这个唯一的属性选择器

23.$nextTick原理

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM

nextTick原理

24.data是函数不是对象

vue是一个单页面应用最终所有的实例都会挂载到app.vue文件,如果data是一个对象那么会导致数据污染。通过函数返回对象的方式,利用函数作用域的限制避免数据污染

25.路由守卫

vue路由守卫分为三种:全局路由守卫,独享路由守卫,组件路由守卫

to: 进入到哪个路由去

from: 来自哪个路由

next:是否跳转

  • 全局守卫: router.beforeEach((to,from,next)=>{})
  • 独享路由守卫: beforeEnter:(to,from,next)=>{}
  • 组件路由守卫: beforeRouteEnter:(to,from,next)=>{}, beforeRouteUpdate , beforeRouteLeave

26.vue设置全局变量

方法一:

  • vue2.x挂载全局是使用 Vue.prototype.$xxxx=xxx 的形式来挂载,然后通过 this.$xxx来获取挂载到全局的变量或者方法。
  • Vue 3 中,使用 config.globalProperties 、app.config.globalProperties.$data = ‘111’
 const {proxy} = getCurrentInstance()
 console.log(proxy.$data)

方法二:

  • provide/inject

27.vue中keep-alive

属性:includeexclude

语法:

// 指定home组件和about组件被缓存
<keep-alive include="home,about" >
    <router-view></router-view>
</keep-alive>

// 除了home组件和about组件别的都缓存
<keep-alive exclude="home,about" >
    <router-view></router-view>
</keep-alive>

钩子函数:

  • activated 当组件被激活(使用)的时候触发 可以简单理解为进入这个页面的时候触发
  • deactivated 当组件不被使用(inactive状态)的时候触发 可以简单理解为离开这个页面的时候触发

进入开启缓存的组件

初始进入和离开 created ---> mounted ---> activated --> deactivated
后续进入和离开 activated --> deactivated

28.vue插槽

slot又名插槽,是Vue的内容分发机制,组件内部的模板引擎使用slot元素作为承载分发内容的出口。插槽slot是子组件的一个模板标签元素,而这一个标签元素是否显示,以及怎么显示是由父组件决定的。slot又分三类,默认插槽,具名插槽和作用域插槽。

默认插槽:又名匿名插槽,当slot没有指定name属性值的时候一个默认显示插槽,一个组件内只有有一个匿名插槽。

具名插槽:带有具体名字的插槽,也就是带有name属性的slot,一个组件可以出现多个具名插槽。

作用域插槽:默认插槽、具名插槽的一个变体,可以是匿名插槽,也可以是具名插槽,该插槽的不同点是在子组件渲染作用域插槽时,可以将子组件内部的数据传递给父组件,让父组件根据子组件的传递过来的数据决定如何渲染该插槽。

实现原理:当子组件vm实例化时,获取到父组件传入的slot标签的内容,存放在vm. s l o t 中,默认插槽为 v m . slot中,默认插槽为vm. slot中,默认插槽为vm.slot.default,具名插槽为vm. s l o t . x x x , x x x 为插槽名,当组件执行渲染函数时候,遇到 s l o t 标签,使用 slot.xxx,xxx 为插槽名,当组件执行渲染函数时候,遇到slot标签,使用 slot.xxxxxx为插槽名,当组件执行渲染函数时候,遇到slot标签,使用slot中的内容进行替换,此时可以为插槽传递数据,若存在数据,则可称该插槽为作用域插槽。

29.vue2和vue3区别

双向绑定更新

vue2 的双向数据绑定是利⽤ES5 的⼀个 API ,Object.defineProperty()对数据进⾏劫持 结合 发布订阅模式的⽅式来实现的。

vue3 中使⽤了 ES6 的 ProxyAPI 对数据代理,通过 reactive() 函数给每⼀个对象都包⼀层 Proxy,通过 Proxy 监听属性的变化,从⽽ 实现对数据的监控。

这⾥是相⽐于vue2版本,使⽤proxy的优势如下

1.defineProperty只能监听某个属性,不能对全对象监听 可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)

2.可以监听数组,不⽤再去单独的对数组做特异性操作,通过Proxy可以直接拦截所有对象类型数据的操作,完美⽀持对数组的监听。

获取props

vue2在script代码块可以直接获取props,vue3通过setup指令传递

API不同

Vue2使⽤的是选项类型API(Options API),Vue3使⽤的是合成型API(Composition API)

建立数据data

vue2是把数据放入data中,vue3就需要使用一个新的setup()方法,此方法在组件初始化构造得时候触发。

生命周期不同

vue2 -------- vue3

beforeCreate -> setup() 开始创建组件之前,创建的是data和method

created -> setup()

beforeMount -> onBeforeMount 组件挂载到节点上之前执行的函数。

mounted -> onMounted 组件挂载完成后执行的函数

beforeUpdate -> onBeforeUpdate 组件更新之前执行的函数。

updated -> onUpdated 组件更新完成之后执行的函数。

beforeDestroy -> onBeforeUnmount 组件挂载到节点上之前执行的函数。

destroyed -> onUnmounted 组件卸载之前执行的函数。dszhuoyi

activated -> onActivated 组件卸载完成后执行的函数

deactivated -> onDeactivated

是否支持碎片:vue2.0 只允许有一个根标签,vue3.0支持碎片化,可以拥有多个根节点

main.js文件不同:vue2中我们可以使用pototype(原型)的形式去进行操作,引入的是构造函数 vue3中需要使用结构的形式进行操作,引入的是工厂函数

diff算法不同

更好的支持ts

30.Vue3.0 所采用的 Composition Api (组合式)与 Vue2.x 使用的 Options Api(选项式) 有什么不同?

  • options Api 当组件变得复杂,导致对应属性的列表也会增长,这可能会导致组件难以阅读和理解 。composition Api它将功能定义在一起,利于查找和理解
  • Composition API tree-shaking 友好,代码也更容易压缩
  • Composition API中见不到this的使用,减少了this指向不明的情况
  • 如果是小型组件,可以继续使用Options API,也是十分友好的

31.vue3中hook

本质是一个函数,把setup函数中使用的Composition API(组合式api)进行了封装,类似于vue2中的mixin

自定义hook优势:复用代码,让setup中的逻辑更清楚易懂

32.vue组件和插件的区别

组件: Vue 组件是一个可复用的 Vue 实例,可以带有自己的状态和方法。组件可以包含其他组件,从而形成一个复杂的 UI 列表。

优点

  • 可以将代码封装成一个可复用的组件,提高开发效率。
  • 组件具有良好的可维护性,易于修改和更新。

缺点

  • 组件的功能和作用比较独立,不太适用于全局功能的扩展。
  • 组件的管理和组织需要一定的规范,否则可能会导致混乱和不易维护。

插件: Vue 插件可以扩展 Vue 的全局功能,在应用程序中可以重复使用。常见的插件如 vue-routervuexaxios 等。

优点

  • 插件可以方便地扩展 Vue 的全局功能。
  • 插件可以使代码重复利用,提高开发效率。
  • 开源社区中已经有大量的插件可以用于解决常见的问题。

缺点

  • 插件具有一定的复杂性,需要更多的学习成本。
  • 插件功能可能比较复杂,可能会导致性能下降。

33.vue修饰符

Vue中,修饰符处理了许多DOM事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理

  • 表单修饰符
    • .lazy 懒加载,光标离开标签时,才赋值给value
    • .trim 过滤首位空格
    • .number 限制输入类型为数字或转为数字
  • 事件修饰符
    • .stop 阻止事件冒泡
    • .prevent 组织事件默认行为
    • .once 事件只触发一次
    • .capture 开启事件捕获
    • .self 事件只在自身触发
  • 鼠标按键修饰符
    • left 左键点击
    • right 右键点击
    • middle 中键点击
  • 键值修饰符
    • 普通键(enter、tab、delete、space、esc、up…)
    • 系统修饰键(ctrl、alt、meta、shift…)
  • v-bind修饰符
    • .async 对props进行双向绑定
    • .prop 设置自定义标签属性,避免暴露数据,防止污染html结构
    • .camel 将命名为驼峰命名法

34.Vue路由中,history和hash两种模式有什么区别?

hash: hash 模式是一种把前端路由的路径用井号 # 拼接在真实 URL 后面的模式。当井号 # 后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发 hashchange 事件。

  • 优点:浏览器兼容性较好,连 IE8 都支持
  • 缺点:路径在井号 # 的后面,比较丑

history: history API 是 H5 提供的新特性,允许开发者直接更改前端路由,即更新浏览器 URL 地址而不重新发起请求

  • 优点:路径比较正规,没有井号 #
  • 缺点:兼容性不如 hash,且需要服务端支持,否则一刷新页面就404了

35.params和query区别

paramsquery 都是用于传递参数的,但它们的传参方式和使用场景是不同的。

params 通过路由路径传递参数,在路由配置中使用 :paramName 的形式进行声明

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
    },
  ],
})

query 通过 URL 查询字符串(即问号后面的部分)传递参数,在路由地址后面使用 ? 连接多个参数键值对

不需要在router中配置 /search?q=vue 会自动匹配到search组件

区别:

  • params 适合用于必须存在的参数传递,例如用户详情页或文章详情页的访问。
  • query 适合用于可选的参数传递,例如搜索功能中关键词的传递。

36.vue2中assets和vue3中public区别 ?

在 Vue 2 中,assets 目录是默认存在的,可以直接在项目的根目录下创建,它通常用来存放组件需要的图片、样式等静态资源文件。这些文件会被打包到 JavaScript 文件中,在代码中使用相对路径引用。

在 Vue 3 中,可以通过配置 vue.config.js 文件来设置 public 目录,它的作用与 assets 目录类似,用来存放静态资源文件。但是,与 Vue 2 不同的是,public 目录下的文件不会被打包,而是会直接复制到输出目录下

37.单页应用如何提高加载速度?

  • 使用代码分割:将代码拆分成小块并按需加载(懒加载),以避免不必要的网络请求和减少加载时间。
  • 缓存资源:利用浏览器缓存来存储重复使用的文件,例如 CSS 和 JS 文件、图片等。
  • 预加载关键资源:在首次渲染之前,先提前加载关键资源,例如首页所需的 JS、CSS 或数据,以保证关键内容的快速呈现。
  • 使用合适的图片格式:选择合适的图片格式(例如 JPEG、PNG、WebP 等),并根据需要进行压缩以减少文件大小。对于一些小图标,可以使用 iconfont 等字体文件来代替。
  • 启用 Gzip 压缩:使用服务器端的 Gzip 压缩算法对文件进行压缩,以减少传输时间和带宽消耗。
  • 使用 CDN:使用内容分发网络(CDN)来缓存和传递文件,以提高文件的下载速度和可靠性。
  • 优化 API 请求:尽可能地减少 API 调用的数量,并使用缓存和延迟加载等技术来优化 API 请求的效率。
  • 使用服务器端渲染:使用服务器端渲染(SSR)来生成 HTML,以减少客户端渲染所需的时间和资源。但需要注意,SSR 也可能增加了服务器的负担并使网站更复杂。

38.Vue父组件调用子组件的方法

vue中如果父组件想调用子组件的方法,可以在子组件中加上ref,然后通过this.$refs.ref.method调用


调用:this.$refs.child.子组件方法

39.vue3中dom获取,ref在组件上使用

<template>
  <div class="ref">
    <h3>ref使用:</h3>
    <input type="text" ref="input" /> //  ref="input" 需要和 const input = ref(null); 相对应
  </div>
</template>

<script setup>
import { reactive, ref, createApp, onMounted } from "vue";

let state = reactive({ text: "信息按钮" });
// 同名的 input来进行获取节点
const input = ref(null);
onMounted(() => {
  if (input.value) {
    input.value.focus();
  }
});
</script>
<style scoped></style>

40.渐进式框架理解

渐进式: 可以理解为没有多做职责之外的事

个人理解:主张最少的,一开始仅基于基础框架构建,随着需求不断扩充

41.页面初始化闪烁

产生原因:当网速较慢,vue.js文件还没有加载完时,在页面上会显示{{message}}的字样,知道vue创建实例,编译模板时,dom才会被替换,所以这个过程屏幕是闪动的。

所以解决这个问题,需要在style样式中设置【v-cloak】{display:none}。在一般情况下,v-clock是一个解决初始化慢导致页面闪动的最佳实践,对于简单的项目很实用。

但是在具有工程化的项目里,比如使用了webpack和vue-router的项目中,html结构只是一个空的div元素,剩余的内容都是由路由去挂载不同的组件完成的,所以不需要v-cloak。

42.vue属性名和method名称一致出现什么问题

vue2中, 这个属性会覆盖掉 methods 中的方法。也就是说,这个方法将无法被正确调用。

vue3中,报错

43.class和style如何动态绑定

class 与 style 动态绑定一般通过对象或者数组来实现

对象写法:适用于要绑定的样式名字样式确定,但动态决定用不用。

数组写法:适用于要绑定的样式名字样式不确定。

<div v-bind:class="{ active: isActive }"></div> //对象写法
<div v-bind:class="[activeClass, errorClass]"></div> //数组写法

44.vue遇到的坑

  • data必须是一个函数,而不是一个对象
  • vue管理的函数不要写成箭头函数
  • 添加属性页面不刷新
  • 子路由path不需要添加**/**,path=‘new’

45.v-if和v-for 优先级

实践中不管是vue2或者vue3都不应该把v-if和v-for放在一起使用。

在 vue 2.x 中,在一个元素上同时使用 v-if 和 v-for 时, v-for 会优先作用。

在 vue 3.x 中, v-if 总是优先于 v-for 生效。

vue2中v-for的优先级是高于v-if的,放在一起,会先执行循环在判断条件,并且如果值渲染列表中一小部分元素,也得再每次重渲染的时候遍历整个列表,比较浪费资源。

vue3中v-if的优先级是高于v-for的,所以v-if执行时,它调用相应的变量如果不存在,就会导致异常

46.vue核心原理

数据驱动,组建系统

47.vue自带动画组件, transition

组件是 Vue 提供的用于包裹需要动画效果的元素组件。使用组件可以方便地实现元素的进入和离开动画效果。

<template>
  <div>
    <button @click="visible = !visible">Toggle</button>
    <transition name="fade">
      <p v-if="visible">Hello, World!</p>
    </transition>
  </div>
</template>

<script>
export default {
  data() {
    return {
      visible: false
    }
  },
}
</script>

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
</style>

48.vue-loader工作原理

  1. 将一个 .vue 文件 切割成 templatescriptstyles 三个部分。
  2. template 部分 通过 compile 生成 renderstaticRenderFns
  3. 获取 script 部分 返回的配置项对象 scriptExports
  4. styles 部分,会通过 css-loadervue-style-loader, 添加到 head 中, 或者通过 css-loaderMiniCssExtractPlugin 提取到一个 公共的css文件 中。
  5. 使用 vue-loader 提供的 normalizeComponent 方法, 合并 scriptExports、render、staticRenderFns, 返回 构建vue组件需要的配置项对象 - options, 即 {data, props, methods, render, staticRenderFns…}

49.vue的diff算法

diff整体策略为:深度优先,同层比较

  • 当数据发生改变时,订阅者watcher就会调用patch给真实的DOM打补丁

  • 通过isSameVnode进行判断,相同则调用patchVnode方法

  • patchVnode

    做了以下操作:

    • 找到对应的真实dom,称为el
    • 如果都有都有文本节点且不相等,将el文本节点设置为Vnode的文本节点
    • 如果oldVnode有子节点而VNode没有,则删除el子节点
    • 如果oldVnode没有子节点而VNode有,则将VNode的子节点真实化后添加到el
    • 如果两者都有子节点,则执行updateChildren函数比较子节点
  • updateChildren

    主要做了以下操作:

    • 设置新旧VNode的头尾指针
    • 新旧头尾指针进行比较,循环向中间靠拢,根据情况调用patchVnode进行patch重复流程、调用createElem创建一个新节点,从哈希表寻找 key一致的VNode 节点再分情况操作

50.vue和jquery区别

设计理念

Vue.js 是一个现代化的JavaScript框架,专注于构建大型的、可维护的Web应用程序。Vue.js 的核心是组件化,它提供了一种将页面分解成独立、可重用的组件的方式,并且能够非常容易地管理这些组件之间的依赖关系。同时,Vue.js 还内置了状态管理、路由、构建工具等功能,使得构建复杂的 Web 应用程序更加容易。

而 jQuery 则是一个早期的 JavaScript 库,主要关注的是 DOM 操作和处理事件。它的设计理念是将 JavaScript 代码尽可能地简单化,使得使用者可以很容易地完成一些常见的操作(如选择元素、修改样式、处理事件等)。在 jQuery 中,通过链式调用和函数式变成的设计,可以使得代码变得非常简洁易读。

用途

Vue.js 主要用于构建大型的、复杂的 Web 应用程序,它提供了诸如组件化、状态管理、路由等功能,非常适合构建单页面应用(SPA)。

而 jQuery 则更多地用于简化 DOM 操作和事件处理,它适用于编写小型的 Web 应用程序或较为简单的交互效果。同时,由于 jQuery 在浏览器兼容性、性能等方面的优势,它也被广泛应用于一些成熟的网站和CMS系统中。

51.说说你对 SPA 单页面的理解,它的优缺点分别是什么?

SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。

  • 优点:
    用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
    基于上面一点,SPA 相对对服务器压力小;
    前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
  • 缺点:
    初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统加载,部分页面按需加载;
    前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
    SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。

52. 怎样理解 Vue 的单向数据流?

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。
这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。

53. 父组件可以监听到子组件的生命周期吗?

比如有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑处理,可以通过以下写法实现:

// Parent.vue


// Child.vue
mounted() {
  this.$emit("mounted");
}

以上需要手动通过 $emit 触发父组件的事件,更简单的方式可以在父组件引用子组件时通过 @hook 来监听即可,如下所示:

//  Parent.vue


doSomething() {
   console.log('父组件监听到 mounted 钩子函数 ...');
},

//  Child.vue
mounted(){
   console.log('子组件触发 mounted 钩子函数 ...');
},    

// 以上输出顺序为:
// 子组件触发 mounted 钩子函数 ...
// 父组件监听到 mounted 钩子函数 ...

当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以监听。

54.Vue3.0 性能提升主要是通过哪几方面体现的

  • diff算法优化
  • 静态提升: Vue3中对不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用
  • 移除一些不常用的API,再重要的是Tree shanking
  • 响应式系统

55.什么是 MVVM?比之 MVC 有什么区别?什么又是 MVP ?

MVC 通过分离 Model、View 和 Controller 的方式来组织代码结构。 用户与页面产生交互时Controller 中的事件触发器就开始工作了,通过调用 Model 层,来完成对 Model 的修改,然后 Model 层再去通知 View 层更新。

MVVM 模式中的 VM,指的是 ViewModel, 它通过双向的数据绑定,将 View 和 Model 的同步更新给自动化了。当 Model 发生变化的时候,ViewModel 就会自动更新;ViewModel 变化了,View 也会更新。

MVP 模式 ,View 层的接口暴露给了 Presenter 因此我们可以在 Presenter 中将 Model 的变化和 View 的变化绑定在一起,以此来实现 View 和 Model 的同步更新

56.vue中hook和react中hook区别

在React中,hook是一种函数,它可以让你在函数组件中添加state、effect等功能。 React 中的hook有useState、useEffect、useContext等。使用hook可以避免使用类组件时可能会出现的繁琐的生命周期方法、this等问题。

在Vue中,hook被称为生命周期钩子函数,它们是在组件实例化过程中自动调用的回调函数。 Vue中的生命周期钩子函数包括beforeCreate、created、beforeMount、mounted等。它们可以用于控制组件的生命周期,以及在组件生命周期特定阶段执行特定的操作。

57.Redux和Vuex的区别

redux是一个范用的js库,vuex是专门服务vue的

相同点:

  1. state共享数据
  2. 流程一致:定义全局state,触发,修改state
  3. 原理相似,通过全局注入store。

不同点:

  1. Vuex定义了state,getter、mutation、action,module五个对象;redux定义了state、reducer、action;
  2. Vuex触发方式有两种commit同步和dispatch异步;redux同步和异步都使用dispatch;
  3. Vuex中action有较为复杂的异步ajax请求;redux中action中可简单可复杂,简单就直接发送数据对象({type:xxx, your-data}),复杂需要调用异步ajax(依赖redux-thunk插件)。
  4. Redux使用的是不可变数据,而Vuex的数据是可变的。Redux每次都是用新的state替换旧的state,而Vuex是直接修改;
  5. Redux在检测数据变化的时候,是通过diff的方式比较差异的,而Vuex其实和Vue的原理一样,是通过getter/setter来比较的。

58.vue服务端渲染(SSR),解决了哪些问题?

Vue服务端渲染(SSR)通过在服务器上预先生成Vue组件的HTML字符串,并将其发送到客户端,以实现更快的页面加载速度、更好的搜索引擎优化和更好的用户体验。服务端渲染解决了许多SPA(Single Page Application)应用程序中存在的问题,例如:

  1. SEO(搜索引擎优化)问题:由于传统的SPA应用程序是在浏览器中构建的,因此搜索引擎无法正确地索引它们的内容。使用Vue SSR,可以在服务器上呈现HTML字符串并向搜索引擎提供更好的友好的页面。
  2. 性能问题:SPA应用程序需要大量的JavaScript代码来初始化应用程序并交互。这可能导致页面加载时间缓慢,用户体验较差。使用Vue SSR,可以在浏览器中更快地呈现初始HTML的完整标志,并在其中嵌入必要的JavaScript。这样可以加快页面加载速度,并提高用户体验。
  3. 首屏渲染问题:传统的SPA应用程序在首次加载时可能会需要大量时间才能呈现第一个屏幕,直到JavaScript代码完成下载并执行。使用Vue SSR,可以在服务器上呈现组件,并将其作为HTML字符串发送到客户端,从而实现快速呈现首屏的目标。

59.Vue 3.0中Treeshaking特性是什么,并举例进行说明?

Tree shaking 是一种通过清除多余代码方式来优化项目打包体积的技术

Tree shaking是基于ES6模板语法(importexport),主要是借助ES6模块的静态编译思想,在编译时就能确定模块的依赖关系,以及输入和输出的变量

Tree shaking无非就是做了两件事:

  • 编译阶段利用ES6 Module判断哪些模块已经加载
  • 判断那些模块和变量未被使用或者引用,进而删除对应代码

作用:

  • 减少程序体积(更小)
  • 减少程序执行时间(更快)
  • 便于将来对程序架构进行优化(更友好)

60. 虚拟 DOM 的优缺点?

优点:

  • 保证性能下限: 框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;
  • 无需手动操作 DOM: 我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;
  • 跨平台: 虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。

缺点:

  • 无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。

61. 虚拟 DOM 实现原理?

虚拟 DOM 的实现原理主要包括以下 3 部分:

  • 用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
  • diff 算法 — 比较两棵虚拟 DOM 树的差异;
  • pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。

62. Vue 中的 key 有什么作用?

key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速。
Vue 的 diff 过程可以概括为:oldCh 和 newCh 各有两个头尾的变量 oldStartIndex、oldEndIndex 和 newStartIndex、newEndIndex,它们会新节点和旧节点会进行两两对比,即一共有4种比较方式:newStartIndex 和oldStartIndex 、newEndIndex 和 oldEndIndex 、newStartIndex 和 oldEndIndex 、newEndIndex 和 oldStartIndex,如果以上 4 种比较都没匹配,如果设置了key,就会用 key 再进行比较,在比较的过程中,遍历会往中间靠,一旦 StartIdx > EndIdx 表明 oldCh 和 newCh 至少有一个已经遍历完了,就会结束比较。
所以 Vue 中 key 的作用是:key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速!

  • 更准确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。
  • 更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快,源码如下:
function createKeyToOldIdx (children, beginIdx, endIdx) {
  let i, key
  const map = {}
  for (i = beginIdx; i <= endIdx; ++i) {
    key = children[i].key
    if (isDef(key)) map[key] = i
  }
  return map
}

62. Object.defineProperty怎么用, 三个参数?,有什么作用啊?

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

     obj:需要定义属性的对象
     prop:需要定义的属性
     {}:要定义或修改的属性描述符。
	     value: "18",         // 设置默认值 (与 get() 互斥)
	     enumerable: true,    //这一句控制属性可以枚举 enumerable 改为true 就可以参与遍历了   默认值false
	     writable: true,      // 该属性是否可写   默认值false (与 set() 互斥)
	     configurable: true,  // 该属性是否可被删除   默认值false
	      get // 当有人读取 prop 的时候  get函数就会调用,并且返回就是 sss 的值
	      set // 当有人修改 prop 的时候  set函数就会调用, 有个参数这个参数就是修改后的值

63.reactive与ref的区别?

从定义数据角度对比:

  • ref用来定义:基本类型数据

  • reactive用来定义对象(或数组)类型数据

备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过reactive转为代理对象。

从原理角度对比:

  • ref通过Object.defineProperty()的get与set来实现响应式(数据劫持)。
  • reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。

从使用角度对比:

  • ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
  • reactive定义的数据:操作数据与读取数据:均不需要.value。

64.v-on可以监听多个方法吗?

可以一个元素绑定多个事件的两种写法

<a v-on='{click:DoSomething,mouseleave:MouseLeave}'>doSomething</a>
<button @click="a(),b()">点我ab</button>

65.vue3中如何获取refs,dom对象的方式?vue2中如何使用?

vue3:

(1) setup函数方法内,获取单个ref属性绑定的dom元素:先定义一个空的响应式数据ref定义的,你想获取哪个dom元素,在该元素上使用ref属性绑定该数据即可,通过ref.value即可获取到dom节点

(2) 获取多个ref属性绑定的dom元素。使用ref绑定一个函数,在函数里把dom添加到数组里面

//vue2
<h3 ref="myref">myref</h3>

//获取
this.$refs.myref

66.shallowReactive和shallowRef的区别

(1) shallowReactive:只处理对象最外层的响应式(浅响应式)

(2) shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理。

(3) 应用场景:

​ ① 如果有一个对象数据,结构比较深,但变化时候,只是外层属性变化,使用shallowReactive。

​ ② 如果有一个对象数据,后续功能不会修改改对象中的属性,而是生成新的对象来替换,使用shallowRef。

67.provide与inject如何使用

(1) 父子组件传参可以通过props和emit来实现,但是当组件的层次结构比较深时,props和emit就没什么作用了。vue为了解决这个提出了Provide / Inject;provider/inject:简单的来说就是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量

(2) provide需要先引入,我们将需要传递给下级组件的变量通过provider(‘传输key’,变量)

(3) Inject,下级组件通过变量方式接收,person= inject(‘传输key’)

68.toRaw 与 markRaw是什么作用?

(1) toRaw :将一个由reactive生成的响应式对象转化为普通对象

使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新.

(2) markRaw:标记一个对象,使其永远不会再成为响应式对象。

应用场景:有些值不应被设置为响应式的,例如复杂的第三方类的库,当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能

vue面试题汇总_第3张图片

69.Readonly和shallowReadonly理解

readonly:让一个响应式数据变为只读的(深只读),readonly是一个函数,他会接收一个响应式的数据

shallowReadonly:让一个响应式数据变为只读的(浅只读),shallowReadonly只限制对象中的第一层数据(不能改动,如:salary),但是嵌套的深层次的value属性值 是可以更改的,我们点击更改按钮测试就能发现,被shallowReadonly包裹的对象的深层次值改变了。

70.toref和torefs区别

toReftoRefs 可以用来复制 reactive 里面的属性然后转成 ref,而且它既保留了响应式,也保留了引用

toref(变量,属性),torefs(整个变量)

区别:

  • 在插值表达式中{{}}:
    • 访问 toRefs 的值,需要带上 .value 如果不带上,就会出现双引号 {{user.name.value}}
    • 访问 toRef 的值,不需要带上 .value {{user.name}}
  • 转换属性:
    • toRef: 复制 reactive 里的单个属性并转成 ref
    • toRefs: 复制 reactive 里的所有属性并转成 ref

71.学习 EventBus

首先,在你的项目中创建一个 eventBus.js 文件,并定义一个空的 EventBus 对象:

import Vue from 'vue';
export const EventBus = new Vue();

发送事件

import { EventBus } from './eventBus.js';

// 发送名为 'myEvent' 的事件
EventBus.$emit('myEvent', data);

接收事件

import { EventBus } from './eventBus.js';

EventBus.$on('myEvent', (data)=>{});

取消监听

EventBus.$off('myEvent');

72.vue2过滤器(vue3取消)

filter 过滤器是一种很常用的功能,它可以用于对数据进行格式化、排序、筛选等操作。在使用过程中,我们只需要在模板表达式中使用管道符 |,并将要使用的过滤器的名称作为参数传递进去即可。

全局过滤器:Vue.filter(‘过滤器名称’,function(){})

局部过滤器:filter选项

filters: {
    //filterName过滤器名,value是'|'之前的数据
    filterName(value) {
      if (!value) return '';
      return '你好'+value.toString()
    }
  }

73. vue可以通过计算属性监听计算属性吗

答案:不可以

计算属性依赖于其他属性值,所以我们可以在计算属性中监听这些属性值的变化,并执行一些相关的操作 。 但是,计算属性无法直接监听另一个计算属性的变化,因为一个计算属性的值不是响应式的,它依赖的属性值发生变化时只有它自己才会重新计算,而不会触发其他计算属性的更新


你可能感兴趣的:(vue.js,前端,javascript)