Vue2023 面试归纳及复习

目录

1. Vue 3中的Composition API(Hooks)是什么?它与Options API有何不同?`

Composition API 的优势

2    Options API 语法格式 

3 setup 语法糖

 4  Vue3的生命周期

5. 请解释一下Vue 3中的Teleport(传送)和Suspense(异步组件)是什么,以及它们的作用。

6. Vue 3中的响应式系统是如何工作的?请解释一下Reactive和Ref的区别。

7. 请描述一下Vue 3中的虚拟DOM(Virtual DOM)和Diff算法的工作原理。

8  Vue 3中的响应式数据如何实现异步更新?请解释一下setup()函数中的异步处理。

 9 Vue 3中的动态组件是什么?如何在Vue 3中使用动态组件?

10  请解释一下Vue 3中的 静态提升和Patch Flag  (补丁标记) 的优化策略。

11. Vue 3中的Fragment(片段)是什么?它有什么作用?

12 请解释一下Vue 3中的全局API和实例API的区别。

13. Vue3和Vue2最大区别。

14 Vue2.0 的响应式原理

15 Vue3.0 的响应式原理

16   Vue3.0中的响应式原理是什么?vue2的响应式原理是什么?

17  有哪些vue3响应性判断函数?

18 介绍一下   ref    reactive       toRef    toRefs  函数 

19  setup函数怎么用?

20  watch 和 watchEffect 区别

21  什么是SSR(服务端渲染),原理是什么? 好处有哪些?

22 Pinia 与 VueX的区别与优缺点:

22  什么是 Reflect ?


1. Vue 3中的Composition API(Hooks)是什么?它与Options API有何不同?`


答:Composition API是Vue 3中引入的一种新的API风格,

用于组织和重用组件逻辑。它与Options API相比,

提供了更灵活和可组合的方式来编写组件逻辑。

Composition API使用函数式的API,将相关的逻辑组合在一起,而不是将逻辑分散在不同的选项中。

composition API的好处(带来了什么):

  1. 更好的代码组织(相关逻辑代码可以集中放在一块,而不是分散存在);
  2. 更好的逻辑复用;我们可以将一些常用的逻辑封装成自定义的函数,然后在多个组件中进行重用
  3. 更好的类型推导(比如:optons api中,方法被定义在methods中,但是调用时直接使用this来调用,不符合js语法规范,也不利于我们使用语法的方式来推导类型及属性);
  4. 适用于大型的复杂项目;

不要说setup  跟 composition没啥关系 

1 Composition API 的出现解决了这个问题。它允许我们通过函数的方式组织组件的逻辑,将相关的代码放在一起,使得代码更加清晰、可读性更高。

2. 更好的类型推导和编辑器支持
Composition API 的另一个优势是更好的类型推导和编辑器支持。由于 Composition API 使用了函数的方式来组织代码,编辑器可以更准确地推断变量的类型和提供代码补全。

在 Vue 3 中,通过使用 TypeScript,我们可以为 Composition API 提供类型声明,使得编辑器能够提供更好的代码提示和错误检查。

3. 更好的逻辑复用
Composition API 使得逻辑复用变得更加容易。我们可以将一些常用的逻辑封装成自定义的函数,然后在多个组件中进行重用。

在 Vue 2 中,我们使用 Options API 来编写组件。Options API 是一种基于选项的编程模式,将组件的各种选项(如数据、计算属性、方法等)放在一个对象中。这种方式在小型项目中运作良好,但随着项目规模的增长,组件变得越来越复杂,代码逻辑难以维护和重用。

composition API和Options API如何选择?

  1. 不建议共用,容易引起混乱;

  2. 小型项目、业务逻辑简单用Options AP,因为使用起来简单,门槛更低;

  3. 中大型项目,逻辑复杂,使用composition API

Vue 3 中的 Composition API 是什么?它的优势是什么?_程序员徐师兄的博客-CSDN博客

传统 Options API 中,新增或者修改一个需求,需要分别在 datamethodscomputed,… 里进行修改 。

Composition API 的优势

可以更加优雅的组织我们的代码,函数。能够让相关功能的代码更加有序的组织在一起。

  • 能够将代码按照功能进行封装,降低开发成本与后期维护成本,且让setup中的逻辑更清晰易读。
  • 能够方便的实现代码逻辑复用。

2    Options API 语法格式 

atamethodscomputed

Vue2采用选项式API(Options API)格式,该格式会导致对相同数据进行操作使用的代码被分割到不同属性内,很不利于代码的阅读。

<template>
    <h1>{{helloText}}</h1>
</template>
<script>
     export default{
        props:['msg'],
        data(){
            return {
                count:0, //逻辑1的数据
                name:'HelloWorld' //逻辑2的数据
            }
        },
        methods:{
            onAdd(){  //逻辑1的方法
                this.count++;
            },
            getCount(){ //逻辑2的方法
                this.count=Math.floor(Math.random()*100);
            }
        },
        computed:{
            helloText(){  //逻辑2的计算属性
               return this.msg+' '+this.name;
            }
        },
        watch:{     
            count(){  //逻辑1的watch
                console.log('count 变了');
            }
        },
        mounted(){
            this.getCount() //逻辑1的初始化操作
        }
     }
</script>
<style scoped>
  a{
    color:#42b983
  }
</style>

Vue:对比于 Options API,为什么 Composition API 很香?_shangdong2023的博客-CSDN博客

3 setup 语法糖

<script setup>是在单文件组件中使用Composition API的编译时语法糖。相比于普通的<script>语法,它具有更多优势

  1. 不用写setup函数
  2. 组件只需要引入不需要注册
  3. 属性和方法也不需要再返回,可以直接在template模板中使用。

在 Vue 3 当中我自己感觉最鲜明的变化就是 Vue 3 中引入了组合式 Api (composition API)
但是使用 Vue3 组合式 API 的时候感觉整个过程比较繁琐

  • 在 setup () 当中定义 ⇒ setup() 中 return ⇒ 模板中使用

如果需要定义一个方法的话,模板中使用这个方法的时候,需要在 setup 函数中将它返回,模板中需要用到的大量的方法和属性都需要一 一返回 , 这个过程有点难受,时不时的就会漏掉返回这一步导致变量未定义或者 xx not a function 的错误

<script>
import {defineComponent , reactive, ref} from 'vue'
export default defineComponent({
  setup(){
    // 基本类型变量
    const name = ref("你好")
    const age = ref(2023)
    // 引用类型变量
    const book = reactive({name:"月亮",age:"1919"})

    // 将变量返回
    return{
      name,
      age,
      book
    }
  }
})
</script>

因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。

可以通过在生命周期钩子前面加上 “on” 来访问组件的生命周期钩子。官网:生命周期钩子

Vue3.0 也提供了 Composition AP I形式的生命周期钩子,与 Vue2.x 中钩子对应关系如下:

obeforeCreate===>setup()
created =======> setup()
beforeMount ===> onBeforeMount
mounted =======> onMounted
beforeUpdate ===> onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==> onBeforeUnmount
unmounted =====> onUnmounted
 

 4  Vue3的生命周期

组合式API形式使用
Vue3.0 中可以继续使用 Vue2.x中 的生命周期钩子,但有有两个被更名:
。beforeDestroy改名为beforeUnmount
。destroyed改名为unmounted

vue2                  -> vue3
beforeCreate     -> 使用 setup()     创建
created               -> 使用 setup()
beforeMount       -> onBeforeMount    挂载
mounted             -> onMounted

beforeUpdate     -> onBeforeUpdate  更新
updated              -> onUpdated
beforeDestroy      -> onBeforeUnmount   卸载
destroyed              -> onUnmounted
errorCaptured       -> onErrorCaptured 

Vue3.0 也提供了 Composition AP I形式的生命周期钩子,与 Vue2.x 中钩子对应关系如下:

obeforeCreate===>setup()
created =======> setup()
beforeMount ===> onBeforeMount
mounted =======> onMounted
beforeUpdate ===> onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==> onBeforeUnmount
unmounted =====> onUnmounted

①onBeforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。

②onMounted: 组件挂载时调用

③onBeforeUpdate:  数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

④onUpdated

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

⑤onBeforeUnmount
在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。

⑥onUnmounted
卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。

⑦onActivated 【了解】
被 keep-alive 缓存的组件激活时调用。

⑧onDeactivated 【了解】
被 keep-alive 缓存的组件停用时调用。

⑨onErrorCaptured【了解】
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回
false 以阻止该错误继续向上传播。

 Vue3 调试钩子:

onRenderTracked

跟踪虚拟 DOM 重新渲染时调用。钩子接收 debugger event 作为参数。此事件告诉你哪个操作跟踪了组件以及该操作的目标对象和键。

renderTracked

当虚拟 DOM 重新渲染为 triggered.Similarly 为renderTracked,接收 debugger event 作为参数。此事件告诉你是什么操作触发了重新渲染,以及该操作的目标对象和键。

5. 请解释一下Vue 3中的Teleport(传送)和Suspense(异步组件)是什么,以及它们的作用。

答:Teleport是Vue 3中引入的一个新组件,用于将组件的内容渲染到DOM树中的指定位置。

它可以在组件的模板中指定一个目标,使得组件的内容可以被渲染到目标的位置,而不是直接渲染在组件所在的位置。

Suspense是Vue 3中引入的另一个新组件,用于处理异步组件的加载过程。通过在Suspense组件中包裹异步组件,并提供一个fallback选项,可以在异步组件加载过程中展示一个占位符,直到异步组件加载完成后才显示真正的内容。

<template>
  <div class="main">
    <Suspense>
      <template #default>
        <A />
      </template>
      <template #fallback>
        <h3>加载中.....</h3>
      </template>
    </Suspense>
  </div>
</template>
<script setup lang="ts">
import A from "./A.vue";
</script>
<style scoped>
.main {
  width: 100%;
  height: 100%;
}
</style>

<Suspense> 是一个内置组件,用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态。

Vue3 新特性 内置组件 <Teleport>_织_网的博客-CSDN博客

Vue3中 内置组件 Teleport 详解_vue3 teleport_明天也要努力的博客-CSDN博客

Suspense组件_会说法语的猪的博客-CSDN博客

6. Vue 3中的响应式系统是如何工作的?请解释一下Reactive和Ref的区别。

答:Vue 3中的响应式系统使用Proxy对象来追踪数据的变化。当数据被访问时,Proxy会收集依赖关系,并在数据变化时触发更新。


Reactive函数是Vue 3中提供的一个全局函数,用于将一个对象转换为响应式对象。它接收一个普通对象作为参数,并返回一个响应式代理对象,可以通过该代理对象访问和修改原始对象的属性。

Ref是Vue 3中提供的一个函数,用于创建一个包装器对象,将一个普通的JavaScript值转换为响应式对象。Ref对象可以通过.value属性访问和修改其包装的值。

7. 请描述一下Vue 3中的虚拟DOM(Virtual DOM)和Diff算法的工作原理。

答:Vue 3中的虚拟DOM是一个内存中的表示,类似于真实DOM结构的JavaScript对象。当数据发生变化时,Vue 3会通过对比新旧虚拟DOM的差异,找出需要更新的部分,然后仅更新那些需要变化的部分,而不是直接操作真实的DOM。
Diff算法是用于比较新旧虚拟DOM树的算法。它会逐层对比两棵树的节点,找出差异,并生成一系列需要进行更新的操作。Diff算法通过一些优化策略,如同级比较、Key的使用等,来尽量减少更新的操作次数,提高性能。

8  Vue 3中的响应式数据如何实现异步更新?请解释一下setup()函数中的异步处理。

Vue 3中的响应式数据可以通过reactive()函数或ref()函数进行定义。

当响应式数据发生变化时,Vue 3会将更新操作推迟到下一个事件循环中执行,以保证多个更新操作的批处理。
在setup()函数中,可以返回一个Promise对象来实现异步处理。当Promise对象解析时,组件会重新渲染,以反映最新的数据状态。

 9 Vue 3中的动态组件是什么?如何在Vue 3中使用动态组件?

答:动态组件是指在运行时根据条件来动态选择渲染不同的组件。在Vue 3中,可以使用元素和:is属性来实现动态组件的渲染。
在模板中使用元素,并将要渲染的组件的名称或组件对象赋给:is属性。根据条件的变化,Vue 3会动态地选择渲染不同的组件。

10  请解释一下Vue 3中的 静态提升和Patch Flag  (补丁标记) 的优化策略。

答:

静态提升是Vue 3中的一项优化策略,用于减少渲染时的虚拟DOM节点创建和比较的开销。

在编译过程中,Vue 3会分析模板中的静态内容,并将其提升为一个单独的静态节点,减少对比的复杂性。

 在Vue2中,每次更新diff,都是全量对比,Vue3则只对比带有标记的,这样大大减少了非动态内容的对比消耗


Patch Flag是Vue 3中的一种标记,用于标识虚拟DOM节点的属性和状态变化。通过在虚拟DOM节点上设置Patch Flag,Vue 3可以跳过对比不必要的属性和状态,以提高性能。
 

在Vue3中有哪些静态标记?  

export const enum PatchFlags {
  
  TEXT = 1,// 1 动态的文本节点
  CLASS = 1 << 1,  // 2 动态的 class
  STYLE = 1 << 2,  // 4 动态的 style
  PROPS = 1 << 3,  // 8 动态属性,不包括类名和样式
  FULL_PROPS = 1 << 4,  // 16 动态 key,当 key 变化时需要完整的 diff 算法做比较
  HYDRATE_EVENTS = 1 << 5,  // 32 表示带有事件监听器的节点
  STABLE_FRAGMENT = 1 << 6,   // 64 一个不会改变子节点顺序的 Fragment
  KEYED_FRAGMENT = 1 << 7, // 128 带有 key 属性的 Fragment
  UNKEYED_FRAGMENT = 1 << 8, // 256 子节点没有 key 的 Fragment
  NEED_PATCH = 1 << 9,   // 512  表示只需要non-props修补的元素 (non-props不知道怎么翻才恰当~)
  DYNAMIC_SLOTS = 1 << 10,  // 1024 动态的solt
  DEV_ROOT_FRAGMENT = 1 << 11, //2048 表示仅因为用户在模板的根级别放置注释而创建的片段。 这是一个仅用于开发的标志,因为注释在生产中被剥离。
 
  //以下两个是特殊标记
  HOISTED = -1,  // 表示已提升的静态vnode,更新时调过整个子树
  BAIL = -2 // 指示差异算法应该退出优化模式
}

Vue3的编译优化:Block树和PatchFlags_姑老爷呀的博客-CSDN博客

简略介绍Vue3之新特性_vue3 虚拟标签_前端布道人的博客-CSDN博客

11. Vue 3中的Fragment(片段)是什么?它有什么作用?

答:Fragment是Vue 3中引入的一个组件,用于包裹一组连续的节点,并且不会在渲染结果中引入额外的父节点。它可以用来替代使用等标签包裹多个节点的情况,以减少生成的DOM层级。
使用Fragment可以改善渲染性能和DOM结构的简洁性,特别是当需要在循环或条件语句中渲染多个节点时。

在 Vue 3 中,要使用 Fragments,我们可以使用特殊的语法来表示一个 Fragment。这个特殊语法是使用尖括号和 v-if 指令来实现的。

下面是一个示例代码,展示了如何使用 Fragments:

<template>
  <>
    <h1>标题</h1>
    <p>正文内容</p>
    <button>点击我</button>
  </>
</template>

在上面的代码中,我们使用 <> 和 </> 将 <h1>、<p> 和 <button> 包裹起来,形成了一个 Fragment。这样,我们就可以直接将多个子元素组合在一起,而无需引入额外的包裹元素。

需要注意的是,在使用 Fragments 时,我们并不需要指定 key 属性。Vue 3 会自动处理 Fragments 中子元素的渲染和更新,而无需我们手动管理。
 

Fragments 的优势
使用 Fragments 有以下几个优势:

1. 简洁性
Fragments 允许我们在不引入多余包裹元素的情况下,组合和渲染多个子元素。这样可以减少 DOM 结构的嵌套层级,使代码更加简洁易读。

2. 更好的性能
相对于使用包裹元素的方式,Fragments 可以减少不必要的 DOM 元素,从而提高渲染性能。因为在 Fragments 中,不会创建额外的 DOM 节点。

3. 更好的样式控制
使用 Fragments 可以避免引入额外的包裹元素,从而减少对样式的影响。特别是在使用 CSS 布局库或者进行样式复用时,Fragments 可以提供更好的样式控制。

总结
Vue 3 中的 Fragments 是一个非常有用的特性,它允许我们更简洁地组合和渲染多个子元素,而无需引入额外的包裹元素。通过使用 <> 和 </> 将多个子元素包裹起来,我们可以享受到简洁性、更好的性能和更好的样式控制。使用 Fragments 可以避免引入额外的包裹元素,从而减少对样式的影响。特别是在使用 CSS 布局库或者进行样式复用时,Fragments 可以提供更好的样式控制。

12 请解释一下Vue 3中的全局API和实例API的区别。

答:Vue 3中的全局API是指可以在任何组件中直接访问的API,如createApp、directive、

vue2中:有许多的全局API,如:Vue.directive、Vue.component、Vue.config、Vue.mixin等
vue3中:提供的是实例API,通过createApp创建vue实例,原来在Vue原型上的API都被挂载到了vue实例上,如:app.directive、app.component、app.config、app.mixin等

全局API:

1. createApp()  创建一个应用实例。

2. createSSRApp()  以SSR创建一个应用实例,和createApp()用法一样。

3. app.mount(msg)   将一个应用实例挂载到某个元素上。

4. app.unmount()  卸载一个已经挂载的应用实例,会触发这个实例内所有组件的卸载生命周期函数

5. app.provide(key, value) 注入  用来提供一个值,可以让应用所有的后代组件都可以使用。

6. app.component()   定义一个全局组件,或返回一个组件。

7. app.directive()

如果同时传递一个名字和一个指令定义,则会注册一个全局指令;如果只传递一个名字,会返回用该名字注册的指令 (如果存在的话)。

8. app.use()

安装一个插件

第一个参数应是插件本身,第二个参数可选是要传递给插件的选项。

9. app.version

版本号,查询该应用的版本号。可以在插件中使用,比较这个插件满足那个版本才能使用。

实例API :

在Vue3中,使用vue中的createApp方法可以创建一个Vue应用实例。

1、component方法:

注册或检索全局组件。注册还会使用给定的 name 参数自动设置组件的 name。

2、config属性
一个包含应用配置的对象。

3、directive方法
注册或检索全局指令。

4、mount方法
所提供 DOM 元素的 innerHTML 将被替换为应用根组件的模板渲染结果。

5、provide方法
设置一个可以被注入到应用范围内所有组件中的值。组件应该使用 inject 来接收 provide 的值。

6、unmount方法
卸载应用实例的根组件

7、use
安装 Vue.js 插件。如果插件是一个对象,则它必须暴露一个 install 方法。如果插件本身是一个函数,则它将被视为 install 方法。

Vue 实例之全局API,实例属性,全局配置,组件进阶_大可爱学编程ฅ´ω`ฅ的博客-CSDN博客

【Vue3】Vue实例API介绍_vue3获取vue实例_h沐的博客-CSDN博客

13. Vue3和Vue2最大区别。

重要的几个区别: Vue响应式的底层实现不同     语法API不同   

 生命周期     this     Typescript支持

 不太重要的 :  v-if和v-for的优先级    .sync修饰符   key在template和v-if上的使用

一、Vue响应式的底层实现不同

二、生命周期有一定的区别

三、支持碎片化,可以有多个根节点

Vue3 支持多个根节点,也就是 fragment。即以下多根节点的写法是被允许的

四,模板指令

在vue2中,v-for 优先级高于 v-if;

在vue3 中,v-if 优先级高于v-for;

五、语法API不同

Vue2:选项式API,面向对象编程

Vue3:选项式API/组合式API,面向函数编程;

没有this,处处皆函数

3、全局API
vue2中:有许多的全局API,如:Vue.directive、Vue.component、Vue.config、Vue.mixin等
vue3中:提供的是实例API,通过createApp创建vue实例,原来在Vue原型上的API都被挂载到了vue实例上,如:app.directive、app.component、app.config、app.mixin等

1、v-if和v-for的优先级
在vue2中:当v-if和v-for同时使用时,v-for的优先级高于v-if(因此我们通常需要计算属性先对数据进行加工处理,以达到性能优化的目的)
在vue3中:当v-if和v-for同时使用时,v-if的优先级高于v-for


2、.sync修饰符
vue2中:由于vue中是单向数据流,父子组件在传值时想要实现v-model的效果就要用到.sync修饰符来实现“双向绑定”
vue3中:对v-model进行了改造,不再需要 .sync 修饰符即可达到数据双向绑定的效果。在vue3中支持多个 v-model属性,默认使用 modelValue 作为 prop,update:modelValue作为事件,当多个v-model绑定时,书写为例:v-model:title="title",此时 title 作为prop,update:title 作为事件

4、Vue.prototype 替换为 config.globalProperties
vue2中:绑定全局的变量、方法等:Vue.prototype.$ajax = xxxx
vue3中:const app = createApp({}); app.config.globalProperties.$ajax = xxxx


5、生命周期
vue2    vue3
beforeCreate


6、key在template和v-if上的使用
vue2中:在使用v-if、vi-else、v-else-if时,为了保证dom节点渲染的正确性,通常需要在对应的节点添加不同的key,以确保vue在进行虚拟dom对比时是准确的;vue2中template在v-for循环时是不能设置key的,否则会产生警告(需要给子节点设置key)。
vue3中:在使用v-if、vi-else、v-else-if时,不用提供唯一的key对dom节点进行区分,因为vue内部会自动生成唯一的key,如果你提供了key,那你就要保证它的唯一性;vue3中template在v-for循环时,key应该设置在template标签上
7、$listeners被移除
vue2中:使用$attrs访问传递给组件的属性,使用$listeners访问传递给组件的事件(需要结合inheritAttrs:false)。
vue3中:虚拟dom中,事件监听器仅仅是以on为前缀的属性


8、this
vue2中:无时无刻都要使用this
vue3中:因为setup函数的存在,所有的props、data等都不需要用this进行访问(vue3对vue2绝大多数是兼容的,如果你用了vue2相关的东西,那你还是需要像vue2一样书写)
9、typescript支持
vue2中:默认是不支持typescript的。
vue3中:支持使用typescript,使用typescript在构建大型项目时,能够很好的提高项目开发的质量。
 

新特性 区别 

Vue3和Vue2的区别_vue2和vue3区别_你吃香蕉吗?的博客-CSDN博客

14 Vue2.0 的响应式原理

原理:

使用的Object.defineProperty()重新定义对象,给data的每个属性都添加了getter和setter方法。这时候会为对象的每个属性创建一个Dep实例  (依赖)。Dep实例可以订阅 (subs: Array<Watcher>)和通知相关的Watcher实例。,  这一步叫  数据劫持  或者 依赖收集   

在数据发生更新后调用 set 时会通知发布者 notify 通知对应的订阅者做出数据更新,同时将新的数据根性到视图上显示。 这一步叫 派发更新

同时,为了解决对象属性添加和删除的问题,Vue提供了全局的Vue.set和Vue.delete方法,以及实例的vm.$set和vm.$delete方法。

缺陷:只能够监听初始化实例中的 data 数据,动态添加值不能响应,要使用对应的 Vue.set()。

15 Vue3.0 的响应式原理

总结来说就是:Vue3使用了Proxy来劫持数据形成对应的proxy对象, 然后形成一个负责渲染的effect。  通过解析template,替换真实data属性,来触发get。 通过track方法进行依赖收集。 track方法通过当前proxy对象target,和访问的属性名key来找到对应的dep。将负责渲染的effect存入deps。 当我们 this[key] = value 改变属性的时后触发set,通过trigger方法去执行effect,完成页面的响应。

16   Vue3.0中的响应式原理是什么?vue2的响应式原理是什么?

(1)vue2.x版本响应式基于ES5的Object.defineProperty实现

(2)Vue3.x版本响应式基于ES6(es2015)的Proxy实现

总结

在vue2中利用的是原生js下边的Object.defineProperty()进行数据劫持,在通过里面的getter和setter方法,进行查看和数据的修改,通过发布、订阅者模式进行数据与视图的响应式。vue2是对对象的所有属性进行递归, 让每个对象的每个属性都调用Object.defineProperty()为止。

  • vue2使用Object.defineProperty()实现响应式原理,而vue3使用Proxy()实现。
  • 虽然vue2,vue3面对对象嵌套,都需要递归,但vue2是对对象的所有属性进行递归,
  • vue3是按需递归,如果没有使用到内部对象的属性,就不需要递归,性能更好。
  • vue2中,对象不存在的属性是不能被拦截的。而vue3可以。
  • vue2对数组的实现是重写数组的所有方法,并改变,vue2中,数组的原型来实现,而Proxy则可以轻松实现。而且vue2中改变数组的长度是无效的,无法做到响应式,但vue3可以。

Vue3.0的相应式原理:利用Proxy劫持对象,访问对象的时候会触发get方法,此时会进行依赖的收集;当修改对象数据的时候会触发set方法,此时会派发依赖,即调用组件的副作用渲染函数(其实不限于), 这样组件就能重新渲染,DOM更新。

17  有哪些vue3响应性判断函数?

isRef
判断一个值是否为一个 ref 对象
isReactive
判断一个对象是否是由 reactive创建的响应式代理
isReadonly
判断一个对象是否是由 readonly 创建的只读代理
isProxy
判断一个对象是否是由 reactive 或 readonly 创建的代理
 

18 介绍一下   ref    reactive       toRef    toRefs  函数 

ref

ref是Vue3提供的一种用于包装基本数据类型的响应式对象的实现方式。

在Vue3中,使用ref可以将基本数据类型(如字符串、数字、布尔值等)包装为响应式对象。当这些基本数据类型的值发生变化时,Vue3会自动更新视图中相应的内容。

需要注意的是,在使用ref包装基本数据类型时,我们需要通过.value来访问这个值。这是因为ref返回的是一个包含.value属性的响应式对象,而不是一个基本数据类型的值。

reactive

reactive是Vue3提供的一种用于包装对象的响应式对象的实现方式。在Vue3中,使用reactive可以将对象包装为一个响应式对象。当这个对象的属性发生变化时,Vue3会自动更新视图中相应的内容。

和ref不同的是,reactive可以深层代理数据

reactive为传入的数据包装ref,生成value,利用Proxy代理检测数据变化。

注意::一般引用数据类型添加响应式使用reactive, 基本数据类型使用ref

vue3响应式数据的相关函数_let data = ref()_MiMenge的博客-CSDN博客

ref和reactive的区别

在使用ref和reactive时,需要注意它们之间的区别。ref适用于包装基本数据类型,而reactive适用于包装对象。此外,ref返回的是一个包含.value属性的响应式对象,而reactive返回的是一个包装后的响应式对象。

toref   函数

创建一个ref对象,这个响应式对象的value引用了接收的对象的某个响应式属性,且与源数据保持引用关系

let data = { num: 0, o: ["1", 2], },

let dynamicProp = toRef(refData, "o");

 toRefs函数

和toRef功能差不多,只不过toRefs可以创建多个ref对象
因为当有多个响应式对象需要单独提取的时候,toRef就显得过于复杂了,使用toRefs可以简化这个过程

let { o, num, job } = toRefs(refData);

在某些情况下,我们希望将一个响应式对象的属性单独作为响应式属性使用,而不是将整个对象作为一个响应式数据使用。这时就可以使用 toRefs 函数。

Vue 3 中的 toRefs 函数是一个非常有用的工具,它可以将一个响应式对象转换为一组响应式属性。这个函数可以用于将父组件中的响应式对象传递给子组件,并在子组件中以单独的响应式属性的形式使用它们。

shallowRef

特殊的ref,只处理基本数据类型的响应式,无法为引用数据类型添加响应式

shallowReactive

只为对象的第一层属性添加响应式

triggerRef

ref生成的数据强制在页面更新页面

前面在使用shallowRef添加响应对象时,数据不能更新到页面,使用triggerRef便可以强制更新

 readony

让一个响应式数据变为深只读

shallowReadony

让一个响应式数据变为浅只读

toRaw

将响应式数据变更为非响应式数据(基础数据)

11 markRaw

将响应式数据永久变更为非响应式数据

12 customRef

自定义ref, 通过基础ref配置满足自定义要求的ref

vue3响应式数据的相关函数_let data = ref()_MiMenge的博客-CSDN博客

【Vue3响应式】ref、reactive,以及toRefs 函数_m0_71975585的博客-CSDN博客

19  setup函数怎么用?

1、setup函数在beforeCreate和created之前执行

2、在setup函数中定义的变量和方法需要return出去,不然无法在模板中使用

3、setup函数是Composition API的入口。

setup函数里面是没有this对象的,使用它的话会报 undefined。

setup函数那么它讲会有两个参数分别是  props  和  context

 
export default {
  props: {
    item: String
  },
  setup(props,context) { //   setup(props,{ emit } ) 解构赋值
    console.log(props.item) // 这个可以访问到props里面的值
    console.log(context.emit) // 这个可拿到emit方法
  }
}

props 是响应式的,当传入新的 props 时,它将被更新。但是,因为 props 是响应式的,你不能使用 ES6 解构,它会消除 prop 的响应性。

setup第二参数是 Context 

context 是一个普通 Js 对象,

context 是一个普通的 JavaScript 对象,也就是说,它不是响应式的,这意味着你可以安全地对 context 使用 ES6 解构。

export default {
  setup(props, { attrs, slots, emit, expose }) {
    ...
  }
}

20  watch 和 watchEffect 区别

  • watch- 显式指定依赖源,依赖源更新时执行回调函数

  • watchEffect - 自动收集依赖源,依赖源更新时重新执行自身

1.watch是惰性执行,也就是只有监听的值发生变化才会执行,但watchEffect不同,每次代码加载watchEffect都会执行。

注:(忽略watch第三个参数的配置,如果修改配置项,也可以实现立即执行)。

2.watch需要传递监听的对象,watchEffect不需要。   

3.watch只能监听响应式数据:ref定义的属性和reactive定义的对象,如果直接监听reactive定义对象中的属性是不允许的 (会报警告),除非使用函数转换一下,既要指明监视的属性,也要指明监视的回调。

  

4.watchEffect如果监听reactive定义的对象是不起作用的 ,只能监听对象中的属性。
 

Vue3 中 watch 与 watchEffect 有什么区别?_vue3 watcheffect和watch区别_琉璃℡初雪的博客-CSDN博客

21  什么是SSR(服务端渲染),原理是什么? 好处有哪些?

服务端渲染

服务端渲染 SSR (Server-Side Rendering),是指在服务端完成页面的 html 拼接处理, 然后再发送给浏览器,将不具有交互能力的 html 结构绑定事件和状态,在客户端展示为具有完整交互能力的应用程序。

适用场景

以下两种情况 SSR 可以提供很好的场景支持

  • 需更好的支持 SEO

    优势在于同步。搜索引擎爬虫是不会等待异步请求数据结束后再抓取信息的,如果 SEO 对应用程序至关重要,但你的页面又是异步请求数据,那 SSR 可以帮助你很好的解决这个问题。

  • 需更快的到达时间

    优势在于慢网络和运行缓慢的设备场景。传统 SPA 需完整的 JS 下载完成才可执行,而SSR 服务器渲染标记在服务端渲染 html 后即可显示,用户会更快的看到首屏渲染页面。如果首屏渲染时间转化率对应用程序至关重要,那可以使用 SSR 来优化。

开箱即用的SSR脚手架

目前前端流行的三种技术栈 React, Vue 和 Angula,已经孵化出对应的服务端渲染框架,开箱即用,感兴趣的同学可以自主学习使用。

  • React: Next.js

  • Vue:  Nuxt.js

彻底理解服务端渲染 - SSR原理_沛沛老爹的博客-CSDN博客

服务端渲染SSR及实现原理_ssr场景_油墨香^_^的博客-CSDN博客

22 Pinia 与 VueX的区别与优缺点:

pinia和vuex的区别
(1)pinia它没有mutation,他只有state,getters,action【同步、异步】使用他来修改state数据
 (2)pinia他默认也是存入内存中,如果需要使用本地存储,在配置上比vuex麻烦一点

 (3)pinia语法上比vuex更容易理解和使用,灵活。
 (4)pinia没有modules配置,没一个独立的仓库都是definStore生成出来的

 (5)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 项目。

22  什么是 Reflect ?

Reflect 其实和 Proxy 一样都是属于 ES6 的高级API,Reflect 也是属于 window 的一个内置类,可以通过 window.Reflect 访问到,看下图    

     Reflect是JavaScript中的全局对象,提供操作JavaScript对象的方法,类似与Object操作对象的方法。用于解决Object方法过于臃肿的问题,对大多数的Object方法进行了实现,同时对于对象的操作返回操作的结果,如返回对象的set操作结果,在某些场景下可以进行监听操作。  

工具人
 

为什么 Proxy 要配合 Reflect 一起使用

①触发代理对象的劫持时保证正确的 this 上下文指向

function getPrivateProps(obj, filterFunc) {
 
  return new Proxy(obj, {
    get(obj, prop) {
      if (!filterFunc(prop)) {
        let value = Reflect.get(obj, prop);
        // 如果是方法, 将this指向修改原对象
        if (typeof value === 'function') {
          value = value.bind(obj);
        }
        return value;
      }
    },
 
    set(obj, prop, value) {
 
      if (filterFunc(prop)) {
        throw new TypeError(`Can't set property "${prop}"`);
      }
      return Reflect.set(obj, prop, value);
    },
 
    has(obj, prop) {
      return filterFunc(prop) ? false : Reflect.has(obj, prop);
    },
 
    ownKeys(obj) {
      return Reflect.ownKeys(obj).filter(prop => !filterFunc(prop));
    },
 
    getOwnPropertyDescriptor(obj, prop) {
      return filterFunc(prop) ? undefined : Reflect.getOwnPropertyDescriptor(obj, prop);
    }
 
  });
 
}
//因为私有属性 一般以 _开头 这里就简单过滤
function propFilter(prop) {
  return prop.indexOf('_') === 0;
}
 

②框架健壮性

9月2号面试经历   翼辉爱智 锦业路西安中心 

1  你用Vue3 ref 与 reactive 的区别 

为什么 ref 要包一层.value      为什么模板里面不用写  

 从定义数据角度对比:

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

    从原理角度对比:

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

    从使用角度对比:

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

为什么 ref 要包一层.value      为什么模板里面不用写  

ref定义的数据用.value的原因:

在模板中引入ref的值时,Vue会自动帮助我们进行解包操作,所以我们并不需要在模板中通过 ref.value 的方式 来使用;

但是在 setup 函数内部,它依然是一个 ref引用, 所以对其进行操作时,我们依然需要使用 ref.value的方式

RefImpl类:

class RefImpl {
    constructor(value, __v_isShallow) {
        this.__v_isShallow = __v_isShallow;
        this.dep = undefined;
        this.__v_isRef = true;
        this._rawValue = __v_isShallow ? value : toRaw(value);
        this._value = __v_isShallow ? value : toReactive(value);
    }
    get value() {
        trackRefValue(this);
        return this._value;
    }
    set value(newVal) {
        const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal);
        newVal = useDirectValue ? newVal : toRaw(newVal);
        if (shared.hasChanged(newVal, this._rawValue)) {
            this._rawValue = newVal;
            this._value = useDirectValue ? newVal : toReactive(newVal);
            triggerRefValue(this, newVal);
        }
    }
}

Vue 的 ref 什么时候自动解包_文摘资讯的博客-CSDN博客

vue3的ref,reactive的使用和原理解析_vue3 reactive_KinHKin(五年前端)的博客-CSDN博客

2 说一下Ts 基本数据类型   泛型是什么 为什么用泛型

什么是泛型呢?

泛型简单来说就是类型变量,在ts中存在类型,如number、string、boolean等。泛型就是使用一个类型变量来表示一种类型,类型值通常是在使用的时候才会设置。泛型的使用场景非常多,可以在函数、类、interface接口中使用

为什么使用泛型?

TypeScript 中不建议使用 any 类型,不能保证类型安全,调试时缺乏完整的信息。
TypeScript可以使用泛型来创建可重用的组件。支持当前数据类型,同时也能支持未来的数据类型。扩展灵活,可以在编译时发现类型错误,从而保证了类型安全。

相信看到这里一些读者会有疑问,我们在什么时候需要使用泛型呢?通常在决定是否使用泛型时,我们有以下两个参考标准:

  • 当你的函数、接口或类将处理多种数据类型时;
  • 当函数、接口或类在多个地方使用该数据类型时。

TS中的泛型是什么,适合什么应用场景_ts 泛型_weixin_39788999的博客-CSDN博客

一文搞懂 TS 泛型,让你头不再晕_ts泛型_阿宝哥​_的博客-CSDN博客

3 说一下Scope 的原理 为什么会加上 data-id  加上为什么就实现自我组件的样式是生效了 

既:PostCSS给一个组件中的所有dom添加了一个独一无二的动态属性,给css选择器额外添加一个对应的属性选择器,来选择组件中的dom,这种做法使得样式只作用于含有该属性的dom元素(组件内部的dom)。

通过分别给 HTML 标签和 CSS 选择器添加 data-v-xxxx 属性的方式实现。

    

vue css 中 scoped的实现原理_vue 中 css scoped 的原理_大白的博客的博客-CSDN博客


 

4 说一下垂直水平居中 怎么实现  flex 怎么实现的

1 绝对定位配合外边距

.container{
      position: absolute;
       top: 50%;
      left: 50%;
      margin-top: -150px;
      margin-left: -150px;
 }

2. 绝对定位配合外边距二

.container{
   position: absolute;
   top: 0;
   bottom: 0;
   left: 0;
   right: 0;
   margin: auto;
 }
 

 3. 绝对定位配合偏移

.container{
     position: absolute;
     top: 50%;
     left: 50%;
     transform: translate(-50%,-50%);
  }
 

4. 弹性布局

body{
     display: flex;
     justify-content: center;
     align-items: center;
 }
5. 网格布局

 body{
      display: grid;
    align-items: center;
    justify-content: center;
 }
6. 使用类似表格的布局特性

 .container{
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}
 

史上最全概括,十种方法实现水平垂直居中~来自万物之恋_水平垂直居中的几种方法_万物之恋的博客-CSDN博客

详解Reflect:Reflect和Object的异同,Reflect的一些内置方法以及方法注意点_DCodes的博客-CSDN博客

都知道vue3响应式是Proxy实现的,进来把proxy与Reflect吃透_vue3数据响应式过程reflect_前端阿彬的博客-CSDN博客

详解Reflect:Reflect和Object的异同,Reflect的一些内置方法以及方法注意点_DCodes的博客-CSDN博客


【前端vue3面试题】2023最新面试实录vue3.0,高频10问(持续更新...)_wzySan的博客-CSDN博客

9.3号  新康能 

1 uniAPP生命周期 

1.应用生命周期

应用生命周期是指应用程序从启动到关闭的整个过程,包括应用程序的启动、前后台切换、退出等。Uniapp提供了以下生命周期钩子函数

  • onLaunch:应用程序启动时触发,仅在应用程序第一次启动时触发。
  • onShow:应用程序进入前台时触发,可以获取到应用程序被打开的方式和场景值。
  • onHide:应用程序进入后台时触发。
  • onError:应用程序发生错误时触发,可以用来捕获和处理错误信息。
  • onUniNViewMessage:监听来自nvue页面的消息。

2.页面生命周期

页面生命周期是指UniApp应用中单个页面的生命周期,其包括以下几个阶段:

  • onLoad:当页面加载时该函数被调用,开发者可以在该函数中请求数据并刷新页面;
  • onShow:当页面展示时该函数被调用,开发者可以在该函数中更新数据和页面状态;
  • onHide:当页面被隐藏时该函数被调用,开发者可以在该函数中停止播放音乐、释放资源等;
  • onUnload:当页面卸载时该函数被调用,开发者可以在该函数中释放页面占用的资源;
  • onPullDownRefresh:当页面下拉时该函数被调用,开发者可以在该函数中处理下拉刷新事件;
  • onReachBottom:当页面滚动到底部时该函数被调用,开发者可以在该函数中处理加载更多事件;
  • onShareAppMessage:当页面被分享时该函数被调用,开发者可以在该函数中配置分享信息;
  • onPageScroll:当页面滚动时该函数被调用,开发者可以在该函数中处理页面滚动事件。

3.组件生命周期

组件生命周期是指组件从创建到销毁的整个过程,包括组件的创建、更新、销毁等。Uniapp提供了以下生命周期钩子函数:

beforeCreate:组件实例被创建之前触发,此时组件的数据和方法都还没有初始化。
created:组件实例被创建之后触发,此时组件的数据和方法已经初始化。
beforeMount:组件被渲染之前触发,此时组件还没有被渲染到页面上。
mounted:组件被渲染之后触发,此时组件已经被渲染到页面上。
beforeUpdate:组件数据更新之前触发,此时组件的数据还没有被更新。
updated:组件数据更新之后触发,此时组件的数据已经被更新。
beforeDestroy:组件实例被销毁之前触发,此时组件的数据和方法还可以访问。
destroyed:组件实例被销毁之后触发,此时组件的数据和方法已经无法访问。
 

uniapp中的生命周期_uniapp页面生命周期_jieyucx的博客-CSDN博客

【uni-app教程】三、 UniAPP 生命周期_uni.getlaunchoptionssync()_我有满天星辰的博客-CSDN博客

uniapp生命周期-CSDN博客

2 uniapp 跳转方式  以及含有的钩子 

通过配置pages.json里面的tabBar来实现,主要写法请参考官方文档

2  通过官方给的组件navigator来实现跳转(类似a标签),主要样式如下

<navigator url="跳转地址" open-type="跳转方式"></navigator>

open-type的值主要有以下几种:

navigate                      保留当前页面,跳转到应用内的某个页面
redirect                       关闭当前页面,跳转到应用内的某个页面。
switchTab                   跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
reLaunch                    关闭所有页面,打开到应用内的某个页面。
navigateBack             关闭当前页面,返回上一页面或多级页面。


exit                              退出小程序,当navigator标签的target="miniProgram"时生效

navigator的钩子有 : 

beforeEnter在页面进入前执行

beforeLeave在页面离开前执行,

afterLeave在页面离开后执行

通过在这些钩子函数中编写代码,可以实现更加灵活的页面跳转控制和数据处理
 

3 条件编译 :

条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。

写法: 以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾。

#ifdef:if defined 仅在某平台存在
#ifndef:if not defined 除了某平台均存在
%PLATFORM%:平台名称

4 提高微信小程序的应用速度的常见方式有哪些?

  1. 提高页面加载速度
  2. 用户行为预测 onPreload
  3. 减少默认data的大小
  4. 组件化方案
  5. 分包预下载
    小程序与原生App相比优缺点?

5 uni-app 实现全局变量

页面中操做 globalData 的方式

赋值:

getApp().globalData.text = 'test'

取值:

console.log(getApp().globalData.text)

原生App优点:

​​​​​​​1、原生的响应速度快
2、对于有无网络操作时,譬如离线操作基本选用原生开发
3、需要调用系统硬件的功能(摄像头、方向传感器、重力传感器、拨号、GPS、语音、短信、蓝牙等功能)
4、在无网络或者若网的情况下体验好。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值