【Vue面试题系列】四

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()方法获取新的值。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django实现接口自动化平台(十四)测试用例模块Testcases序列化器及视图【持续更新中】

相关文章: Django实现接口自动化平台(十三)接口模块Interfaces序列化器及视图【持续更新中】_做测试的喵酱的博客-CSDN博客 本章是项目的一个分解,查看本章内容时,要结合整体项目代码来看: python django…

一条命令解决端口占用,开启mysql

注:最后有面试挑战,看看自己掌握了吗 文章目录 端口占用开启mysql 端口占用 如果发现 8080 端口被占用可以使用命令 sudo lsof -t -i:8080 | sudo xargs kill -9 查找并杀死相应的进程。 开启mysql 打开命令提示符或终端。如果您已经安装了MySQL&…

Cesium Terrain Builder (CTB) 简单使用_地形切片

Cesium Terrain Builder (CTB) 简单使用_地形切片 目录 Cesium Terrain Builder (CTB) 简单使用_地形切片 官网地址: winr(cmd)打开命令提示符工具运行: Create a GDAL Virtual Dataset (optional) Create Cesium Terrain fi…

EasyCVR视频融合平台能正常播放其他协议流,但无法播放HLS流的原因排查

EasyCVR基于云边端一体化架构,支持海量视频汇聚管理,平台支持多协议与多类型设备接入,具体包括国标GB28181、RTMP、RTSP/Onvif、海康Ehome、海康SDK、大华SDK、宇视SDK等,能对外分发RTMP、RTSP、HTTP-FLV、WS-FLV、HLS、WebRTC等。…

部署langchain+chatglm

先参考:window零基础部署langchain-ChatGLM_飞奔的屎壳郎的博客-CSDN博客 安装一部分, 1.GCC安装 gcc64位下载 一定要装64位的gcc,因为我的电脑是w10 64位的,装32位运行langchain报错并配置环境变量 可直接用压缩包中的文件&am…

八股文(消息队列)

文章目录 1. RabbitMQ特点2. 如何保证消息的可靠性3. RabbitMQ消息的顺序性4. 实现RabbitMQ的高可用性5. 如何解决消息队列的延时以及过期失效问题?6. RabbitMQ死信队列7. RabbitMQ延迟队列8.RabbitMQ的工作模式9. RabbitMQ消息如何传输10. 核心概念10.1 生产者和消…

python接口自动化(三十六)-封装与调用--流程类接口关联续集(详解)

简介 上一篇已经给大家都介绍过了流程类接口关联,但是由于博客的登录机制改变,所以没有办法给小伙伴们实战演练一下,那么这篇就按照上一篇计划的用jenkins来给小伙伴们演示一下流程类接口的封装和调用,其实很简单,就是…

python_day11_pymysql

SQL基础语法回忆 show DATABASES;use world;-- SELECT DATABASES();show TABLES;CREATE TABLE Student(id int,name VARCHAR(10),age int,gender VARCHAR(5) );删除表 # 删除表 DROP TABLE Student;插入操作 insert into student(id) VALUES(1),(2),(3);insert i…

HTML+CSS+JavaScript:渲染柱形统计图

一、需求 用户输入四个季度的数据&#xff0c;根据数据生成柱形统计图&#xff0c;浏览器预览效果如下 二、完整代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content&q…

vue-sticky简单使用(实现吸顶效果)

参考链接 vue-sticky&#xff1a;在页面滚动时将指定元素固定在窗口上的某个位置 生效条件如下&#xff1a; 1、父元素不能设置 overflow:hidden 或者 overflow:auto 属性 2、至少指定 top 、bottom 、left 、right 4 个值中的一个&#xff0c;否则只会处于相对定位 3、父元素…

云曦期末复现

serialize 代码审计&#xff0c;给1传参&#xff0c;满足password的值为yunxi&#xff0c;那么反序列化前就会执行__wakeup函数&#xff0c;从而得到flag.php&#xff0c;但是password的值被定死为1&#xff0c;利用PHP反序列化的字符逃逸: <?php error_reporting(0); hig…

android studio 离线打包配置push模块

1.依赖引入 SDK\libs aps-release.aar, aps-unipush-release.aar, gtc.aar, gtsdk-3.2.11.0.aar, 从android studio的sdk中找到对应的包放到HBuilder-Integrate-AS\simpleDemo\libs下面 2.打开build.gradle&#xff0c;在defaultConfig添加manifestPlaceholders节点&#xff0c…

【数据结构导论】第 7 章:排序

目录 一、概述 &#xff08;1&#xff09;基本概念 &#xff08;2&#xff09;排序分类 &#xff08;3&#xff09;排序文件的物理表示 —— 数组表示 二、插入排序&#xff08;通过比较插入实现排序&#xff09; &#xff08;1&#xff09;直接插入排序 ① 过程 ② 算…

SqlServer数据库【基础-更删改查】

一、创建语句 &#xff08;1&#xff09;创建数据库 1.检查系统中是否存在这个数据库&#xff0c;存在则删除 格式&#xff1a; if exists(select * from sysdatabases where name数据库名) drop database 数据库名 go例子&#xff1a; if exists(select * from sysdataba…

C 知识积累 替换gets函数 Linux C 语法分析 switch和if else的比较

目录 替换gets函数gets()用处gets()的危险之处gets()的几种替代方法一、用%c循环输入直到遇到换行结束二、用getchar()循环输入直到遇到换行结束三、scanf的另一种用法四、c中的getline()方法五、解决方案使用fgets代替 回车与换行一.知其然二.知其所以然 关键字&#xff0c;操…

BI-SQL丨XML

XML SQL Server中&#xff0c;存在一种特殊类型的数据&#xff0c;就是XML数据类型。 可能看到这里&#xff0c;小伙伴都会产生疑惑&#xff0c;XML不是Web语言么&#xff1f;为什么在SQL Server里面也会有XML数据类型&#xff1f; 这个就要从SQL Server的应用开始说起了&am…

JavaSwing+MySQL的酒店管理系统

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88063706?spm1001.2014.3001.5503 JDK1.8、MySQL5.7 功能&#xff1a;散客开单&#xff1a;完成散客的开单&#xff0c;可一次最多开5间相同类型的房间。 2、团体开单&#xff1a;完成团体…

photoshop制作法线和凹凸贴图

做个选区 Ctrlj 法线贴图 生成凹凸贴图

如何避免在C#中出现混乱代码

文章目录 一、溯源&#xff1a;混乱代码出现的原因 二、陷阱&#xff1a;混乱代码会使你焦头烂额 三、10招&#xff1a;避免出现混乱代码 四、写在最后&#xff1a;不与混乱代码纠缠 意大利面是一种很好吃的食物&#xff0c;但是&#xff0c;如果用它来形容代码意味着这种程…

伙伴云CEO戴志康:我们为什么要做伙伴云?

分享嘉宾&#xff1a;戴志康&#xff0c;伙伴云CEO 以下为演讲实录⬇⬇⬇ 01选择人更少的一条路&#xff0c;从B级走向A级 我一直想和大家交流一个话题&#xff0c;关于我们为什么要做伙伴云。既代表我自己&#xff0c;同时也代表我们团队的一些想法。 我是一个怀疑论者。大…