【Vue面试题系列】四

news2024/12/1 10:35:41

VNode有哪些属性?

Vue内部定义的Vnode对象包含了以下属性:
__v_isVNode: true,内部属性,有该属性表示为Vnode
__v_skip: true,内部属性,表示跳过响应式转换,reactive转换时会根据此属性进行判断
isCompatRoot?: true,用于是否做了兼容处理的判断
type: VNodeTypes,虚拟节点的类型
props: (VNodeProps & ExtraProps) | null,虚拟节点的props
key: string | number | null,虚拟阶段的key,可用于diff
ref: VNodeNormalizedRef | null,虚拟阶段的引用
scopeId: string | null,仅限于SFC(单文件组件),在设置currentRenderingInstance当前渲染实例时,一期设置
slotScopeIds: string[] | null,仅限于单文件组件,与单文件组件的插槽有关
children: VNodeNormalizedChildren,子节点
component: ComponentInternalInstance | null,组件实例
dirs: DirectiveBinding[] | null,当前Vnode绑定的指令
transition: TransitionHooks | null,TransitionHooks

Vue2.0为什么不能检查数组的变化,该怎么解决?

我们都知道Vue2.0对于响应式数据的实现有一些不足:

  • 无法检测数组/对象的新增
  • 无法检测通过索引改变数组的操作

无法检测数组/对象的新增?
Vue检测数据的变动是通过Object.defineProperty实现的,所以无法监听数组的操作时可以理解的,因为是在构造函数中就已经为所有属性做了这个检测绑定操作。
无法检测通过索引改变数组的操作。即vm.items[indexOfItem] = newValue?
官方文档中对应这两点都是简要的概括为:由于JavaScript的限制无法实现,而Object.defineProperty是实现检测数据改变的方案,这个限制是指Object.defineProperty

小结:是出于对性能原因的考虑,没有去实现它。而不是不能实现。
对于对象而言,每一次的数据变更都会对对象的属性进行一次枚举,一般对象本身的属性数量有限,所以对于遍历枚举等方式产生的性能损耗可以忽略不计,但是对于数组而言,数组包含的元素是可能达到成千上万,假设对于每一次数组元素的更新都触发了枚举/遍历,其带来的性能损耗将与获得的用户体验不成正比,故vue无法检测数组的变动。

不过Vue3.0用proxy代替了defineProperty之后就解决了这个问题。

解决方案
数组:
this.$set(array, index, data)

//这是个深度的修改,某些情况下可能导致你不希望的结果,因此最好还是慎用
this.dataArr = this.originArr
this.$set(this.dataArr, 0, {data: '修改第一个元素'})
console.log(this.dataArr)        
console.log(this.originArr)  //同样的 源数组也会被修改 在某些情况下会导致你不希望的结果 

splice

//因为splice会被监听有响应式,而splice又可以做到增删改。

利用临时变量进行中转

let tempArr = [...this.targetArr]
tempArr[0] = {data: 'test'}
this.targetArr = tempArr

对象:
1、this.$set(obj, key ,value) - 可实现增、改
2、watch时添加deep:true深度监听,只能监听到属性值的变化,新增、删除属性无法监听

this.$watch('blog', this.getCatalog, {
    deep: true
    // immediate: true // 是否第一次触发
  });

3、watch时直接监听某个key

watch: {
  'obj.name'(curVal, oldVal) {
    // TODO
  }
}

说说Vue页面的渲染流程?

在Vue核心中除了响应式原理外,视图渲染也是重中之重。我们都知道每次更新数据,都会走视图渲染的逻辑,而这当中牵扯的逻辑也是十分繁琐。
本题主要解析的是初始化视图渲染流程,将会了解到从挂载组件开始,Vue是如何构建VNode,又是如何将VNode转为真实节点并挂载到页面。

初始化调用$mount挂载组件。
在这里插入图片描述

初始化调用$mount挂载组件。
_render开始构建VNode,核心方法为createElement,一般会创建普通的VNode,遇到组件就创建组件类型的VNode,否则就是未知标签的VNode,构建完成传递给_update。

patch阶段根据VNode创建真实节点树,核心方法为createElm,首先遇到组件类型的VNode,内部会执行$mount,再走一遍相同的流程。普通节点类型则创建一个真实节点,如果他有子节点开始递归调用createElm,使用insert插入子节点,直到没有子节点就填充内容节点。最后递归完成后,同样也是使用insert将整个节点树插入到页面中,再将旧的根节点移除。

react和vue有什么区别?

React是由Facebook创建的JavaScript UI框架,React推广了Virtual DOM(虚拟DOM)并创造了JSX语法。JSX语法的出现允许我们在JavaScript中书写html代码。
Vue是尤雨溪开发的,Vue使用了模版系统而不是JSX,因其实模版系统都是使用普通的HTML,所以对应用的升级更方便、容易,而不需要整体重构。
Vue相较于React更容易上手,如果是一个有一定开发经验的开发者,甚至都不需要花额外的时间去学习,直接一遍开发一遍查文档即可。

VUE 与 React 区别
React的思路是HTML in JavaScript也可以说是All in JavaScript,通过JavaScript来生成HTML,所以设计了JSX语法,还有通过JS来操作CSS,社区的styled-component、JSS等。

Vue是把HTML,CSS,JavaScript组合到一起,用各自的处理方式,Vue有单文件组件,可以把HTML、CSS、JS写到一个文件中,HTML提供了模版引擎来处理。

React整体是函数式的思想,在React中是单向数据流,推崇结合immutable来实现数据不可变。

而Vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟DOM。

如上,所以React的性能优化需要手动去做,而Vue的性能优化是自动的,但是Vue的响应式机制也有问题,就是当state特别多的时候,Watcher会很多,会导致卡顿。

React 与 VUE 共同点
React 与 VUE 存在很多共同点,例如他们都是JavaScript的UI框架,专注于创造前端的富应用。不同于早期的JavaScript框架功能齐全,React与Vue只有框架的骨架,其他的功能如路由、状态管理等是框架分离的组件。

优势
React

  • 灵活性和响应性:它提供最大的灵活性和响应能力。
  • 丰富的JavaScript库:来自世界各地的贡献者正在努力添加更多功能。
  • 可扩展性:由于其灵活的结果和可扩展性,React已被证明对大型应用程序更好。
  • 不断发展:React得到了Facebook专业开发人员的支持,他们不断寻求改进方法。
  • Web或移动平台:React提供React Native平台,可通过相同的React组件模型为IOS和Android开发本机呈现的应用程序。

Vue

  • 易于使用:Vue.js包含基于HTML的标准模版,可以更轻松的使用和修改现有程序。
  • 更顺畅的集成:无论是单页应用程序还是复杂的Web界面,Vue.js都可以更平滑地集成更小的部件,而不会对整个系统产生任何影响。
  • 更好的性能,更小的尺寸:它占用更少的空间,并且往往比其他框架提供更好的性能。
  • 精心编写的文档:通过详细的文档提供简单的学习曲线,无需额外的知识;HTML和JavaScript将完成工作。
  • 适应性:整体声音设计和架构使其成为一种流行的JavaScript框架。
  • 他提供无障碍的迁移,简单有效的结构和可重用的模版。

vue中computed和watch的区别

computed 计算属性依赖其他属性,由其他属性计算而来的。
在官方文档中,还强调了 computed 一个重要的特点,就是 computed 带有缓存功能。
computed 内定义的 function 只执行一次,仅当初始化显示或者相关的 data、props 等属性数据发生变化的时候调用;
而 computed 属性值默认会缓存计算结果,计算属性是基于它们的响应式依赖进行缓存的;
只有当 computed 属性被使用后,才会执行 computed 的代码,在重复的调用中,只要依赖数据不变,直接取缓存中的计算结果。只有依赖型数据发生改变,computed 才会重新计算。

watch 监听属性通过 vm 对象的 $watch() 或 watch 配置来监听 Vue 实例上的属性变化,或某些特定数据的变化,然后执行某些具体的业务逻辑操作。当属性变化时,回调函数自动调用,在函数内部进行计算。其可以监听的数据来源:data,props,computed 内的数据。

注: 监听函数有两个参数,第一个参数是最新的值,第二个参数是输入之前的值,顺序一定是新值,旧值,如果只写一个参数,那就是最新属性值。

在使用时选择 watch 还是 computed,还有一个参考点就是官网说的:当需要在数据变化时执行异步或开销较大的操作时,watch方式是最有用的。所以 watch 一定是支持异步的。

上面仅限监听简单数据类型,监听复杂数据类型就需要用到深度监听 deep。

**deep:**为了发现对象内部值的变化,可以在选项参数中指定 deep: true。注意监听数组的变更不需要这么做。
深度监听虽然可以监听到对象的变化,但是无法监听到对象里面哪个具体属性的变化。这是因为它们的引用指向同一个对象/数组。Vue 不会保留变更之前值的副本。

若果要监听对象的单个属性的变化,有两种方法:
1.直接监听对象的属性

若果要监听对象的单个属性的变化,有两种方法:
1.直接监听对象的属性

2.与 computed 属性配合使用,computed 返回想要监听的属性值,watch 用来监听

computed: {
    firstNameChange() {
    return this.fullName.firstName
    }
},
watch: {
    firstNameChange() {
        console.log(this.fullName)
    }
}

总结:
watch和computed都是以vue的依赖追踪机制为基础的,当某一个依赖型数据(简单理解为放在data等对象下的示例数据)发生变化时,所以依赖这个数据的相关数据会自动发生变化,即自动调用相关的函数,来实现数据的变动。

当依赖的值变化时,在watch中,是可以做一些复杂的操作的,而computed中的依赖,仅仅是一个值依赖于另一个值,是值上的依赖。

应用场景:
computed:用于处理复杂的逻辑运算;一个数据受一个或多个数据影响;用来处理watch和methods无法处理的,或处理起来不方便的情况。例如处理模版中的复杂表达式、购物车里面的商品数量和总金额之间的变化关系等。
watch:用来处理当一个属性发生变化时,需要执行某些具体的业务逻辑操作,或要在数据变化时执行异步或开销较大的操作;一个数据改变影响多个数据。例如用了监控路由、input输入框值的特殊处理等。

区别:
computed

  • 初始化显示或者相关的data、props等属性数据发生变化的时候调用;
  • 计算属性不在data中,它是基于data或者props中的数据通过计算得到的一个新值,这个新值根据已知值的变化而变化。
  • 在computed属性对象中定义计算属性的方法,和取data对象里的数据属性一样,以属性访问的形式调用
  • 如果computed属性值是函数,那么默认会走get方法,必须要有一个返回值,函数的返回值就是属性的属性值
  • computed属性值默认会缓存计算结果,在重复的调用中,只要依赖数据不变,直接取缓存中的计算结果,只有依赖数据发生改变,computed才会重新计算。
  • 在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。

watch

  • 主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,可以看做是computed和methods的结合体
  • 可以监听的数据来源:data、props、computed内的数据
  • watch支持异步
  • 不支持缓存,监听的数据改变,直接会触发相应的操作;
  • 监听函数有两个参数,第一个参数是最新的值,第二个参数是输入之前的值,顺序一定是新值,旧值。

computed怎么实现的缓存?

  1. 初始化data和computed,分别代理其set及get方法,对data中的所有属性生产唯一的dep实例。
  2. 对computed中的sum生成唯一watcher,并保存在vm._computedWatchers中
  3. 执行render函数时会访问sum属性,从而执行initComputed时定义的getter方法,会将Dep.target指向sum的watcher,并调用该属性具体方法sum
  4. sum方法中访问this.count,即会调用this.count代理的get方法,将this.count的dep加入sum的watcher,同时该dep中的subs添加这个watcher。
  5. 设置vm.count=2,调用count代理的set方法触发dep的notify方法,因为是computed属性,只是将watcher中的dirty设置为true。
  6. 最后一步vm.sum,访问其get方法时,得知sum的watcher.dirty为true,调用其watcher.evaluate()方法获取新的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/768333.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

黑马B站视频JAVA部分的知识范围、学习步骤详解

文章目录 学习资源选择最后选择 JAVA的知识范围JDBCswing与JAVAFX JAVA的学习步骤1.右侧的部分:2 JAVA的高级但是必须要学的3 有一些要学(部分)4力扣 总结作业配套资源 学习资源选择 我从画面(一定要看清代码)声音(清…

金融中的数学:概率分布(上)

概率分布是描述随机变量可能取值的概率的函数。它可以用来描述离散变量和连续变量的概率分布。对于离散变量的概率分布,我们称其为离散概率分布。对于连续变量的概率分布,我们称其为连续概率分布。本文主要介绍离散型概率分布。 1.离散型均匀…

华为ospf路由协议在局域网中的高级应用案例

关键配置: 1、出口为ospf区域0,下联汇聚依次区域1、2…,非骨干全部为完全nssa区域 2、核心(abr)上对非骨干区域进行路由汇总,用于解决出口两台路由的条目数量 3、ospf静默接口配置在汇聚下联接接入交换机的…

ngAfterViewInit( ) to early /// ngFor和异步网络请求导致无法选中目标元素的问题

今天遇到的最无语的问题: angular 8版本以上,我在ngafterViewInit()中选取元素选取不到,加上setTimeOut()之后才可以选中 网上的解释: Angular的ngAfterViewInit生命周期钩子是在组…

uniapp | 查看ios打包后的Info.plist文件

最近在用 uni 开发 ios 的时候给项目添加了自定义的 Info.plist 文件,但是打包后发现并没有生效,才有了查看打包后的 Info.plist 文件想法。 HBuilderX3.6.5起,支持直接在应用项目中配置 iOS 平台的 Info.plist 和 资源文件(Bundl…

使用 uiautomator2+pytest+allure 进行 Android 的 UI 自动化测试

目录 前言: 介绍 pytest uiautomator2 allure 环境搭建 pytest uiautomator2 allure pytest 插件 实例 初始化 driver fixture 机制 数据共享 测试类 参数化 指定顺序 运行指定级别 重试 hook 函数 断言 运行 运行某个文件夹下的用例 运行某…

unity 2019 内置渲染管线 光照与Lighting面板 参数详解

文章目录 前言一 Unity的光照 与 烘焙光照1 unity完整的光照组成2 光的亮度与颜色3 全局光照直接光间接光5 间接光≠光照贴图 二 色彩空间与自动烘焙1 unity的色彩空间2 自动烘焙光照 三 烘焙1 什么是烘焙,烘焙的是什么2 如何进行烘焙3 烘焙的优点和缺点4 查看光照贴…

Redis : zmalloc.h:50:31: 致命错误:jemalloc/jemalloc.h:没有那个文件或目录

In file included from adlist.c:34:0: zmalloc.h:50:31: 致命错误&#xff1a;jemalloc/jemalloc.h&#xff1a;没有那个文件或目录 #include <jemalloc/jemalloc.h> 解决 : 如上图使用命令 make MALLOClibc

2023杭电多校(一)

1002 City Upgrading 类似题及其题解 City Upgrading Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 524288/131072 K (Java/Others) Total Submission(s): 306 Accepted Submission(s): 78 Problem Description The city where crazyzhk resides is stru…

分布式事务几种实现方案

前言 分布式事务&#xff1f; 分布式事务是指涉及多个参与者的事务&#xff0c;这些参与者可能分布在不同的计算机、进程或者网络中。分布式事务需要保证ACID属性&#xff0c;即原子性、一致性、隔离性和持久性 解释 现在我们接触的系统基本上都是分布式系统&#xff0c;并且每…

计算几何(二维),定理及证明(持续更新中..)

注&#xff1a;定理来自这篇博客&#xff0c;本文注重证明 向量基本运算 加法 向量 a ⃗ ( x 1 , y 1 ) , b ⃗ ( x 2 , y 2 ) \vec{a}\left(x_1,y_1\right),\vec{b}\left(x_2,y_2\right) a (x1​,y1​),b (x2​,y2​) 则 a ⃗ b ⃗ ( x 1 x 2 , y 1 y 2 ) \vec{a}\…

P7 第二章 电阻电路的等效变换

1、等效变换应用举例 化简套路&#xff1a; 电压源与其串联的电阻&#xff0c;可以等效为电流源并联电阻&#xff0c;然后电流源就可以拿去合并电路中的&#xff0c;与之并联的电流&#xff0c;电阻则可以拿去合并与之并联的电阻。 公式法&#xff1a; 就是根据端的电压与端的…

第一节 C++ 变量

文章目录 1. Visual Studio Community 安装1.1. Visual Studio 介绍1.2. Visual Studio的安装1.3 Visual Studio创建与使用1.3.1 创建一个工程项目1.3.2 新建一个C文件1.3.3 编写执行文件 2. Dev-C 安装(初学者建议使用)2.1 Dev-C 介绍2.2 Dev-C 安装2.3 Dev-C 快捷键使用 3. 认…

数学建模常用模型(九) :偏最小二乘回归分析

数学建模常用模型&#xff08;九&#xff09; &#xff1a;偏最小二乘回归分析 偏最小二乘回归&#xff08;Partial Least Squares Regression&#xff0c;PLS Regression&#xff09;是一种常用的统计建模方法&#xff0c;用于解决多元线性回归中自变量间高度相关的问题。在偏…

【java】三大容器类(List、Set、Map)的常用实现类的特点

三大容器类&#xff08;List、Set、Map&#xff09;的常用实现类的特点 简介 本文总结三大容器类&#xff08;List、Set、Map&#xff09;的常用实现类&#xff08;ArrayList、Vector、LinkedList、HashSet、HashMap、HashTable&#xff09;的特点 一、List部分 1、ArrayLi…

C# DlibDotNet 人脸识别、人脸68特征点识别、人脸5特征点识别、人脸对齐,三角剖分,人脸特征比对

人脸识别 人脸68特征点识别 人脸5特征点识别 人脸对齐 三角剖分 人脸特征比对 项目 VS2022.net4.8OpenCvSharp4DlibDotNet Demo下载 代码 using DlibDotNet.Extensions; using DlibDotNet; using System; using System.Collections.Generic; using System.ComponentModel; …

学堂在线数据结构(上)(2023春)邓俊辉 课后作业错题整理

The reverse number of a sequence is defined as the total number of reversed pairs in the sequence, and the total number of element comparisons performed by the insertion sort in the list of size n is: 一个序列的逆序数定义为该序列中的逆序对总数&#xff0c;…

transformer Position Embedding

这是最近一段很棒的 Youtube 视频&#xff0c;它深入介绍了位置嵌入&#xff0c;并带有精美的动画&#xff1a; Transformer 神经网络视觉指南 -&#xff08;第 1 部分&#xff09;位置嵌入 让我们尝试理解计算位置嵌入的公式的“sin”部分&#xff1a; 这里“pos”指的是“单词…

自定义view(一)----自定义TextView

自定义view也算是Android的一大难点&#xff0c;里面涉及到很多值得学习的地方&#xff0c;我会在接下来写一系列文章去介绍它&#xff0c;本篇文章以自定义一个TextView为例。 View的构造方法 自定义view之前我们先了解view的四个构造方法&#xff0c;自定义view无非就是新建一…