【Vue面试题八】、为什么data属性是一个函数而不是一个对象?

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。

面试官:为什么data属性是一个函数而不是一个对象?

在这里插入图片描述

一、实例和组件定义data的区别

vue实例的时候定义data属性既可以是一个对象,也可以是一个函数

const app = new Vue({el:"#app",// 对象格式data:{foo:"foo"},// 函数格式data(){return {foo:"foo"}}
})

组件中定义data属性,只能是一个函数

如果为组件data直接定义为一个对象

Vue.component('component1',{template:`<div>组件</div>`,data:{foo:"foo"}
})

则会得到警告信息

在这里插入图片描述

警告说明:返回的data应该是一个函数在每一个组件实例中

二、组件data定义函数与对象的区别

上面讲到组件data必须是一个函数,不知道大家有没有思考过这是为什么呢?

在我们定义好一个组件的时候,vue最终都会通过Vue.extend()构成组件实例

这里我们模仿组件构造函数,定义data属性,采用对象的形式

function Component(){}
Component.prototype.data = {count : 0
}

创建两个组件实例

const componentA = new Component()
const componentB = new Component()

修改componentA组件data属性的值,componentB中的值也发生了改变

console.log(componentB.data.count)  // 0
componentA.data.count = 1
console.log(componentB.data.count)  // 1

产生这样的原因这是两者共用了同一个内存地址,componentA 修改的内容,同样对componentB 产生了影响

如果我们采用函数的形式,则不会出现这种情况(函数返回的对象内存地址并不相同)

function Component(){this.data = this.data()
}
Component.prototype.data = function (){return {count : 0}
}

修改componentA组件data属性的值,componentB中的值不受影响

console.log(componentB.data.count)  // 0
componentA.data.count = 1
console.log(componentB.data.count)  // 0

vue组件可能会有很多个实例,采用函数返回一个全新data形式,使每个实例对象的数据不会受到其他实例对象数据的污染

三、原理分析

首先可以看看vue初始化data的代码,data的定义可以是函数也可以是对象

源码位置:/vue-dev/src/core/instance/state.js

function initData (vm: Component) {let data = vm.$options.datadata = vm._data = typeof data === 'function'? getData(data, vm): data || {}...
}

data既能是object也能是function,那为什么还会出现上文警告呢?

别急,继续看下文

组件在创建的时候,会进行选项的合并

源码位置:/vue-dev/src/core/util/options.js

自定义组件会进入mergeOptions进行选项合并

Vue.prototype._init = function (options?: Object) {...// merge optionsif (options && options._isComponent) {// optimize internal component instantiation// since dynamic options merging is pretty slow, and none of the// internal component options needs special treatment.initInternalComponent(vm, options)} else {vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor),options || {},vm)}...}

定义data会进行数据校验

源码位置:/vue-dev/src/core/instance/init.js

这时候vm实例为undefined,进入if判断,若data类型不是function,则出现警告提示

strats.data = function (parentVal: any,childVal: any,vm?: Component
): ?Function {if (!vm) {if (childVal && typeof childVal !== "function") {process.env.NODE_ENV !== "production" &&warn('The "data" option should be a function ' +"that returns a per-instance value in component " +"definitions.",vm);return parentVal;}return mergeDataOrFn(parentVal, childVal);}return mergeDataOrFn(parentVal, childVal, vm);
};

四、结论

  • 根实例对象data可以是对象也可以是函数(根实例是单例),不会产生数据污染情况
  • 组件实例对象data必须为函数,目的是为了防止多个组件实例对象之间共用一个data,产生数据污染。采用函数的形式,initData时会将其作为工厂函数都会返回全新data对象

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

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

相关文章

Spring实例化源码解析之Custom Events上集(八)

Events使用介绍 在ApplicationContext中&#xff0c;事件处理通过ApplicationEvent类和ApplicationListener接口提供。如果将实现ApplicationListener接口的bean部署到上下文中&#xff0c;每当一个ApplicationEvent被发布到ApplicationContext时&#xff0c;该bean将被通知。…

使用企业订货系统后的效果|软件定制开发|APP小程序搭建

使用企业订货系统后的效果|软件定制开发|APP小程序搭建 企业订货系统是一种高效的采购管理系统&#xff0c;它可以帮助企业更好地管理采购流程&#xff0c;降低采购成本&#xff0c;提高采购效率。 可以帮助企业提高销售效率和降低成本的软件工具。使用该系统后&#xff0c;企业…

如何使用 Tensor.art 实现文生图

摘要&#xff1a;Tensor.art 是一个基于 AI 的文本生成图像工具。本文介绍了如何使用 Tensor.art 来实现文生图的功能。 正文&#xff1a; 文生图是指将文本转换为图像的技术。它具有广泛的应用&#xff0c;例如在广告、教育和娱乐等领域。 Tensor.art 是一个基于 AI 的文本…

【SA8295P 源码分析】103 - QNX DDR RAM 内存布局分析

【SA8295P 源码分析】103 - QNX DDR RAM 内存布局分析 一、SA8295P QNX RAM 内存布局 (16G DDR)1.1 DDR 汇总描述1.2 QNX Meta reserved memory, DDR Rank01.3 Reserved for qnx1.4 Android GVM SysRam 相关内存(可修改)1.5 Reserved for qnx(不要修改)1.6 QNX SysRam 相关内…

强制删除文件?正确操作方法分享!

“我昨天在删除文件时有个文件一直删除不掉。想用强制删除的方法来把它删掉&#xff0c;应该怎么操作呢&#xff1f;谁能教教我呀&#xff1f;” 在使用电脑的过程中&#xff0c;我们有时候可能会发现文件无论怎么删除都无法删掉&#xff0c;如果我们想要强制删除文件但不知道怎…

Leetcode hot 100之回溯O(N!):选择/DFS

目录 框架&#xff1a;排列/组合/子集 元素无重不可复选 全排列 子集 组合&#xff1a;[1, n] 中的 k 个数 分割成回文串 元素无重不可复选&#xff1a;排序&#xff0c;多条值相同的只遍历第一条 子集/组合 先进行排序&#xff0c;让相同的元素靠在一起&#xff0c;如…

前端代码格式化规范总结

在日常开发过程中&#xff0c;经常会碰到代码格式化不一致的问题&#xff0c;还要就是 js 代码语法错误等没有及时发行改正&#xff0c;下面就介绍一下如何使用eslint、prettier、husky、lint-staged、commitizen来规范代码格式和提高代码质量的方法。 目录 准备工作代码检测代…

VMProtect使用教程(VC++MFC中使用)

VMProtect使用教程(VCMFC中使用) VMProtect是一种商业级别的代码保护工具&#xff0c;可以用于保护VC MFC程序。以下是使用VMProtect保护VC MFC程序的步骤&#xff1a; 1. 下载并安装VMProtect,C包含库及目录。 2. 在VC MFC项目中添加VMProtectSDK.h头文件&#xff0c;并在需…

Photoshop 笔记

目录 1. Photoshop 笔记1.1. 创建 A4 大小图片 1. Photoshop 笔记 1.1. 创建 A4 大小图片 Photoshop 的高版本自带了 A4、A5、A3、B5、B4、B3、C4、C5 等, 也可以直接制作打印美国信纸尺寸、法律文件用低、小报用纸等。 方法是: 新建 > 打印, 然后选择就可以了。 如果使…

Android ncnn-android-yolov8-seg源码解析 : 实现人像分割

1. 前言 上篇文章&#xff0c;我们已经将人像分割的ncnn-android-yolov8-seg项目运行起来了&#xff0c;后续文章我们会抽取出Demo中的核心代码&#xff0c;在自己的项目中&#xff0c;来接入人体识别和人像分割功能。 先来看下效果&#xff0c;整个图像的是相机的原图&#…

番外--Task2:

任务&#xff1a;root与普通用户的互切&#xff08;区别&#xff09;&#xff0c;启动的多用户文本见面与图形界面的互切命令&#xff08;区别&#xff09;。 输入图示命令&#xff0c;重启后就由图形界面转成文本登录界面&#xff1b; 输入图示命令&#xff0c;重启后就由文本…

java实验(头歌)--类的继承以及抽象类的定义和使用

文章目录 第一题第二题第三题 第一题 import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.Scanner;//把main 函数的给替换了 public static vo…

MybatisPlus01

MybatisPlus01 1.MybatisPlus初体验 1.1首先要引入MybatisPlus的依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency>1.2定义Mapp…

es官方为我们提供的堆内存保护机制-熔断器( breaker )

总熔断器&#xff08;相当于似乎总闸&#xff09; 参数&#xff1a; indices.breaker.total.use_real_memory 默认值&#xff1a;true 在 elasticsearch.yml中配置。 参数&#xff1a; indices.breaker.total.limit 如果 indices.breaker.total.use_real_memory : true, in…

Java网络编程入门指南:实现一个多人聊天室

java网络&#xff1a;实现一个多人聊天室 Socket编程Socket基础TCP和UDP 服务器-客户端通信创建服务器创建客户端 HTTP通信HTTP请求HTTP响应 RMI远程方法调用创建RMI服务创建RMI客户端 多人聊天室 简介 Java网络编程是一种通过网络连接和通信来实现应用程序之间数据传输的技术。…

【JavaEE初阶】 Thread类及常见方法

文章目录 &#x1f334;Thread类的概念&#x1f333;Thread 的常见构造方法&#x1f384;Thread 的几个常见属性&#x1f340;start()-启动一个线程&#x1f332;中断一个线程&#x1f6a9;实例一&#x1f6a9;实例二&#x1f6a9;实例三 &#x1f38d;join()-等待一个线程&…

想要开发一款游戏, 需要注意什么?

开发一款游戏是一个复杂而令人兴奋的过程。游戏开发是指创建、设计、制作和发布电子游戏的过程。它涵盖了从最初的概念和创意阶段到最终的游戏发布和维护阶段的各个方面。 以下是一些需要注意的关键事项&#xff1a; 游戏概念和目标&#xff1a; 确定游戏开发的核心概念和目标…

【SpringBoot】| Thymeleaf 模板引擎

目录 Thymeleaf 模板引擎 1. 第一个例子 2. 表达式 ①标准变量表达式 ②选择变量表达式&#xff08;星号变量表达式&#xff09; ③链接表达式&#xff08;URL表达式&#xff09; 3. Thymeleaf的属性 ①th:action ②th:method ③th:href ④th:src ⑤th:text ⑥th:…

TCP相关面试题

TCP相关面试题 题目1 介绍一下TCP三次握手的过程 介绍TCP三次握手应该从3个方面进行回答&#xff0c;分别是数据包名称&#xff0c;客户端与服务端的状态变化&#xff0c;数据包的序号变化。而不能只是简单回答发送的数据包名称。 TCP三次握手的过程如下&#xff1a; 从数据…

vue3通过ref获取子组件defineExpose的数据和方法

1. 父组件: <script setup> import { defineAsyncComponent, watchEffect, toRefs, reactive } from vue;// 异步组件 const Test defineAsyncComponent(()>import(./xx/Test.vue))const child1Ref ref(null) const state reactive({age: 1,name: 2,sayHello: nul…