vue基础知识八:为什么data属性是一个函数而不是一个对象?

2023-11-18

在这里插入图片描述
一、实例和组件定义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.data
  data = 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 options
    if (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对象
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue基础知识八:为什么data属性是一个函数而不是一个对象? 的相关文章

  • 在 Google 表格脚本中设置活动单元格的值

    我想创建一个公式 在某个单元格更改上创建时间戳 下面的代码就可以了 我现在想做的是将公式转换为纯文本 将该时间戳锚定到工作表上 如果您手动执行此操作 您将选择时间戳 复制它们并将它们粘贴为值 我不想手动执行此操作 因此我创建了下面的脚本 它
  • 为什么隐式符号到字符串转换会导致 JavaScript 中出现类型错误?

    有一个 toString on Symbol在 ES6 中 它返回字符串表示形式Symbol 但想知道为什么 Symbol 不起作用 运行这个表达式会抛出TypeError我没想到 后者只是打电话吗 toString 在一个新的Symbol
  • 雅虎 OAuth2 隐式授予流程不适用于新的雅虎应用程序

    我有现有的网络应用程序和专用雅虎应用程序 https developer yahoo com apps 在职的 它用OAuth2 隐式授权流程 https developer yahoo com oauth2 guide flows imp
  • Sonar 中的 javascript 代码覆盖率

    我是使用 Sonar 和插件进行 javascript 代码覆盖的新手 使用 Sonar 分析时 有哪些可能性可以找出 javascript 代码的质量 包括代码覆盖率 目前我正在使用 karma runner 它提供代码覆盖率报告 可以在
  • Angularjs 完整日历不显示事件

    我正在用那个https github com angular ui ui calendar https github com angular ui ui calendar在 Angularjs 中使用 FullCalendar 它显示日历并
  • 如何在php中使用一张图像绘制形状

    我需要使用图像的一部分来创建帧图像 例如 用户将从后端上传图像片段 现在我需要根据前端用户的要求在前端创建一个框架 用户将选择框架的高度和宽度 然后他将选择该图像片段 如下所示 我没有办法做到这一点 我尝试通过 css 和 html can
  • window.open:是否可以打开一个新窗口并修改其 DOM

    我想打开一个新窗口 var my window open iframe html blank height 600 width 600 但当我打开它时 我想修改它的DOM 我尝试过 var div my document createEle
  • setInterval() 在用户离开选项卡时暂停?

    javascript 中是否有任何方法的行为类似于 setInterval 并且当用户离开选项卡时停止并在用户再次进入选项卡时恢复 您可以使用以下方法创建自己的 API可见性API https developer mozilla org e
  • “|”是什么意思(单管道)在 JavaScript 中做什么?

    console log 0 5 0 0 console log 1 0 1 console log 1 0 1 为什么0 5 0返回零 但任何整数 包括负数 都返回输入整数 单管道 有什么作用 这是一个按位或 https developer
  • 窗口大小调整触发的 DOM 事件

    我有一个布局相当复杂的页面 最初打开页面时 某些元素的对齐存在问题 但是 可以通过更改浏览器窗口的大小来 永久 解决此问题 显然 我不希望用户必须调整浏览器窗口的大小才能使页面正确显示 所以我想知道是否有一种方法可以在页面首次加载时以编程方
  • Firebase 身份验证在 iOS 登录时卡住,没有错误

    我已经使用电子邮件和密码设置了 firebase 身份验证登录的最基本实现 firebase auth signInWithEmailAndPassword email password then gt console log Logged
  • Rails:找不到 JavaScript 运行时。有关可用运行时的列表,请参阅 https://github.com/sstephenson/execjs。 (ExecJS::运行时不可用)

    自从几周前 Dreamhost 升级了服务器以来 我的网站就被破坏了 我一直在努力解决它并取得了一些进展 但我仍然坚持希望是最后的问题 我在 Ruby 1 8 7 上使用 Rails 3 1 1 并收到来自 PhusionPassenger
  • jQuery 悬停时滚动到 div 并返回到第一个元素

    我基本上有一个具有设定尺寸的 div 和overflow hidden 该 div 包含 7 个子 div 但一次只显示一个 我希望当它们各自的链接悬停时能够平滑地垂直滚动 但是 第一部分 div 没有链接 并且是没有悬停链接时的默认部分
  • 如何使用 JavaScript 获取元素的填充值?

    我有一个textarea在我的 HTML 中 我需要获取整数或浮点形式的填充数值 以像素为单位 我如何使用 JavaScript 获取它 我没有使用 jQuery 所以我正在寻找纯 JavaScript 解决方案 这将返回padding l
  • Aurelia - 仅 HTML 自定义元素的内联定义

    我的 Aurelia 视图模型中有一个递归对象 如下所示 Class BottomlessPit Name string MorePits BottomlessPit null 因此 我想在 Aurelia 视图中使用递归模板 它只会在一个
  • 不使用控件时,视频元素在 Chrome 中消失

    So I think这是一个浏览器错误 它出现在一个更复杂的设计 网站中 但我已经进行了很好的尝试 简化了我的代码和设计等 并发现了以下内容 嵌入时
  • Javascript onload 不起作用[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我正在使用
  • 在方法内部执行方法

    我目前正在 FreeCodeCamp 中进行 JavaScript 练习 我的代码应该使用的测试用例之一是函数调用 如下所示 addTogether 2 3 这是我得到的基本功能 function addTogether return 当我
  • 如何获得 JavaScript 阶乘程序的循环来显示所使用的工作?

    你好 我面临着用 JavaScript 编写一个程序的挑战 尽管我对它不太了解 但它要求用户输入一个数字 然后计算该数字的阶乘 我使用了已经提出的问题并设法使计算正常工作 但无法获得所需的输出 我必须在以下输出中获取它 而不使用任何花哨的库
  • JQuery 删除和内存泄漏

    我正在开发一个游戏 我看到了很多内存消耗 我使用jquery animate 动画完成后 我 remove 元素 我的问题是 从 dom 树中删除一个元素后 对象还存在记忆中吗 Javascript 是一种垃圾收集语言 这意味着当没有代码保

随机推荐

  • 例说hg(六)———— hg branch 创建分支

    开篇 branch 分支 應該也是 Hg 最重要的技能之一 在一個多人專案的開發過程中我們有時候要開發新功能 有時候是要修正某個Bug 有時候想要測試某個特異功能能不能 work 這時候我們通常都會從主 branch 再開出一條新的 bra
  • 小白的成长轨迹(二):披荆斩棘,未来可期

    大家好 我是孤焰 一名双非本科的大四学生 又是一年的1024 我坚持撰写博客已经为期一年 很感谢大家一直以来的支持 在这一年期间这位名为 孤焰 的少年又有哪些成长呢 下面便请细听分说 希望这些成长经历可以对正在看这篇文章的小可爱们有一些帮助
  • 点击echarts柱状图动态改变数据项颜色样式

    首先附上参考文章连接 https blog csdn net weixin 42870683 article details 103528254添加链接描述 今天来实现点击echarts柱状图 动态改变柱状图数据项颜色样式的案例 只要认真做
  • 向日葵的windows账号名

    向日葵的windows账号名
  • Windows11安装WSL2.0

    写这篇文章主要是记录下自己安装时的步骤 因为在网上找的一些文章无法正常安装 我安装wsl是用于在windows上运行ubuntu20 04 一 WSL2 0安装 1 启用适用于 Linux 的 Windows 子系统 2种方式第一种方式是图
  • TCP服务器—实现数据通信

    目录 前言 1 接口介绍 2 编写服务器 3 编写客户端 4 编译链接 5 测试 6 总结 前言 今天我们要介绍的是使用TCP协议实现数据通信 相比于之前写的UDP服务器实现数据信 在主体逻辑上并没有差别 客户端向服务器发送信息 服务器接受
  • 泣神曲服务器维护,泣神曲手机版_泣神曲安卓版V1.0.0预约_第一手游网

    泣神曲手游是一款玩法内容丰富的魔幻MMO动作手游 精美魔幻画面带给你极致体验 自由交易随心买卖 史诗争霸一触即发 感兴趣的小伙伴们可别错过了 泣神曲手游简介 这是一款超燃的魔幻风格的角色扮演类手机游戏 圣域激斗 开放地图场景 霸气英雄悉数登
  • 【Endnote】利用Endnote给Word的论文添加文献,根据期刊选择相应的引文和参考文献格式(根据期刊,不涉及自定义)

    版 本 介 绍 版本 Endnote x9 for mac 软件语言 英文 能下载中文的肯定更方便啊 电脑 Mac win的应该会更加简单 网上有更多攻略 正文开始 1 名词解释 在用Word完成论文后 需要为论文添加引文和参考文献 往往是
  • 当服务器无法访问,如何快速定位问题点

    工作和生活中 我们难免会遇到这样的问题 这种情况出现时 如何快速定位排查呢 一 了解什么是域名 VS IP 1 什么是域名 www baidu com 2 为什么用域名通信 不直接用IP通信 ip地址不好记忆 如 124 56 78 333
  • XSS大全

    XSS的原理和特性 xss 将用户的输入当作前端代码执行 注入攻击的本质 是把用户输入的数据当做代码执行 这里有两个关键条件 第一个是用户能够控制输入 第二个是原本程序要执行的代码 拼接了用户输入的数据 html 定义了网页的结构 css
  • MSB和LSB,建议先看下面(其实就是大小端的问题)

    最高有效位 MSB 指二进制中最高值的比特 在16比特的数字音频中 其第1个比特便对16bit的字的数值有最大的影响 例如 在十进制的15389这一数字中 相当于万数那1行 1 的数字便对数值的影响最大 比较与之相反的 最低有效位 LSB
  • Docker使C盘爆满问题

    问题描述 C爆满 查看大文件发现Docker文件超大 猜想应该是Docker镜像文件或者其他文件存于C盘导致 解决 安装docker后会自动创建两个发行版 wsl l v all 关闭Docker 关闭所有发行版 wsl shutdown
  • 将unique_ptr转换为shared_ptr

    std unique ptr
  • CTF入门学习笔记——Crypto密码(古典密码)

    文章目录 CTF入门学习笔记 Crypto密码 古典密码 凯撒密码 看我回旋踢 摩斯密码 摩斯 维吉尼亚密码 Vigen re 栅栏密码 篱笆墙的影子 栅栏密码 篱笆墙的影子 猪圈密码 待补充 CTF入门学习笔记 Crypto密码 古典密码
  • 苹果sf字体_全网首发丨iOS13越狱系统字体分析+iOS13新字体分享

    根据可靠消息分析 最快明天 最迟后天 iOS13系统的越狱就要来了 雨哥也 提前解包了iOS13 2系统的原生字体出来研究一下 未雨绸缪 有备无患 看看iOS12升级到iOS13后系统字体做了哪些升级和变化 喜欢手机字体美化的要认真往下看
  • Coverage官方手册翻译

    下面是官方手册的翻译 Coverage手册 Coverage命令行使用 当你安装 coverage py 将一个名为coverage的命令行脚本py放在Python脚本目录中 为了帮助多版本安装 它还将创建coverage2或coverag
  • 剑指 Offer 62. 圆圈中最后剩下的数字(简单 约瑟夫问题 递归 数学)

    剑指 Offer 62 圆圈中最后剩下的数字 0 1 n 1这n个数字排成一个圆圈 从数字0开始 每次从这个圆圈里删除第m个数字 删除后从下一个数字开始计数 求出这个圆圈里剩下的最后一个数字 例如 0 1 2 3 4这5个数字组成一个圆圈
  • 打印 pyspark.sql.dataframe.DataFrame 有哪些列

    在 PySpark 中 要打印 pyspark sql dataframe DataFrame 的列 可以使用 columns 属性 以下是一个示例代码 from pyspark sql import SparkSession 创建 Spa
  • 串口发送QString buff=“81 20 33 0A 0d“,如何接收 “Q 3” 并换行回车,

    采用Qt写 需要一个showHex函数 将接收的一串QByteArray类型的16进制 转化为对应的字符串16进制 QString ShowHex QByteArray str QDataStream out str QIODevice R
  • vue基础知识八:为什么data属性是一个函数而不是一个对象?

    一 实例和组件定义data的区别 vue实例的时候定义data属性既可以是一个对象 也可以是一个函数 const app new Vue el app 对象格式 data foo foo 函数格式 data return foo foo 组