一、总结

1.vue中组件是用来复用的,为了防止data复用,将其定义为函数。

2.vue组件中的data数据都应该是相互隔离,互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响,就需要通过data函数返回一个对象作为组件的状态。

3.当我们将组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,拥有自己的作用域,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。

4.当我们组件的date单纯的写成对象形式,这些实例用的是同一个构造函数,由于JavaScript的特性所导致,所有的组件实例共用了一个data,就会造成一个变了全都会变的结果。

二、代码分析:

vue每次会通过组件创建出一个构造函数,每个实例都是通过这个构造函数new出来的

假如data是一个对象,将这个对象放到这个放到原型上去

function VueComponent(){}
VueComponent.prototype.$options = {data:{name:'three'}
}
let vc1 = new VueComponent();
vc1.$options.data.name = 'six'; // 将vc1实例上的data修改为six
let vc2 = new VueComponent(); // 在new一个新的实例vc2
console.log(vc2.$options.data.name); six
// 输出vc2的data的值是six,这时候发现vc2中的data也被修改了,他们data相互影响

将data改为一个函数

// 这样就可以保证每个组件调用data返回一个全新的对象,和外部没有关系
function VueComponent(){}
VueComponent.prototype.$options = {data: () => ({name:'three'})
}
let vc1 = new VueComponent();
let objData = vc1.$options.data()
objData.name = 'six'; // 调用data方法会返回一个对象,用这个对象作为它的属性
console.log(objData)
let vc2 = new VueComponent();
console.log(vc2.$options.data());

三、源码

1.在core/global-api/extend.js中会调用mergeOptions方法

    const Sub = function VueComponent (options) {this._init(options)} // 创建一个子类Sub.prototype = Object.create(Super.prototype)Sub.prototype.constructor = SubSub.cid = cid++    Sub.options = mergeOptions( // 调用mergeOptions进行合并Super.options,extendOptions)Sub.extend = Super.extendSub.mixin = Super.mixinSub.use = Super.use

2.mergeOptions方法(src/core/util/options.js)

// 将两个对象合并到一个对象中
// 包括生命周期的合并,data的合并等
export function mergeOptions (parent: Object,child: Object,vm?: Component
): Object {if (process.env.NODE_ENV !== 'production') {checkComponents(child)}if (typeof child === 'function') {child = child.options}normalizeProps(child, vm)normalizeInject(child, vm)normalizeDirectives(child)if (!child._base) {// 对extend和mixins做合并if (child.extends) {parent = mergeOptions(parent, child.extends, vm)}if (child.mixins) {for (let i = 0, l = child.mixins.length; i < l; i++) {parent = mergeOptions(parent, child.mixins[i], vm)}}}const options = {}let key// 循环父类for (key in parent) {mergeField(key)}// 循环子类for (key in child) {if (!hasOwn(parent, key)) {mergeField(key)}}// 合并字段function mergeField (key) {const strat = strats[key] || defaultStratoptions[key] = strat(parent[key], child[key], vm, key)}return options
}

3.合并data(src/core/util/options.js)

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}// 如果是函数就调用mergeDataOrFn进行合并return mergeDataOrFn(parentVal, childVal)}return mergeDataOrFn(parentVal, childVal, vm)
}

4.源码总结:

通过vue.extend方法创建一个子类,创建子类之后会把自己的选项和父类的选项使用mergeOptions方法做一个合并,自己的选项就包含data。在mergeOptions中会调用strats.data对子类的data进行合并,这个方法中首先会判断子类的data进行判断,要求data必须是一个函数,如果不是会报错告诉它这个data应该是一个函数定义,因为每一个组件都会返回一个实例,如果是data就会调用 mergeDataOrFn方法进行合并。然后会合并父类的extend、minin、use方法,最后extend返回的就是这个子类的方法。

补充:

为什么要合并?因为子组件也要有父组件的属性,extend方法是通过一个对象创建了一个构造函数,但是这个构造函数并没有父类的属性,因为它是一个新函数,和之前的Vue构造函数是没有关系的。通过extend产生了一个子函数,这个子函数需要拥有vue实例上的所以东西,它就要做一次合并。

四、为什么new Vue这个里面的data可以放一个对象?

因为这个类创建的实例不会被复用。它只会new一次,不用考虑复用。

vue组件中的data为什么是一个函数相关推荐

  1. Vue 组件中的data为什么是一个函数?

    1.前言 在学习Vue的时候,发现组件中的data 是函数返回的形式,而挂载的实例中的data一般都是简单的对象格式,带着问题查了查文档,下面给出例子和解释. 2.正文 这里有一个 Vue 组件的示例 ...

  2. java socket中属性详解_前端开发:关于Vue组件中的data属性值是函数而不是对象的详解...

    最近在搞关于前端开发的基础知识归纳,发现了不少经典知识点,那么本篇博文就来分享一个经典的知识点:Vue组件中的data属性值为什么是函数而不是对象.首先来了解一下Vue组件的使用理念:在Vue组件使用 ...

  3. vue中的data为什么是一个函数?起到什么作用?

    前言 在学习vue的时候,我们一直在思考的一件事: 组件的data数据为什么必须要以函数返回的形式,为什么不是简单的对象形式呢? 一.data为什么是一个函数 面试回答: 如果data是一个函数的话, ...

  4. vue vue实例中的data与vue组件中的data()

    vue组件就是vue实例,可以被复用. 而在复用时,希望组件中的data应该是相互隔离的. 如果使用 data : {count: 0} 的形式,则复制的该组件会共享data中的数据,所以要使用: d ...

  5. Vue组件中的data和props属性

    组件中数据的绑定 在vue中数据通过data属性进行绑定,如下 <!DOCTYPE html> <html lang="en"> <head>& ...

  6. 为什呢vue组件中的data必须是函数?

    类比引用数据类型 Object是引用数据类型,如果不用function 返回,每个组件的data 都是内存的同一个地址,一个数据改变了其他也改变了; 关于JS中的数据类型:https://blog.c ...

  7. Vue组件中data的使用方式

    全局组件中的data使用方式: js中写法: Vue.component("mycom1",{template:'<h1>这是全局组件--{{msg}}</h1& ...

  8. vue中组件的data为什么是一个函数

    组件是可复用的vue实例,一个组件被创建好之后,就可能被用在各个地方,而组件不管被复用了多少次,组件中的data数据都应该是相互隔离,互不影响的,基于这一理念,组件每复用一次,data数据就应该被复制 ...

  9. vue组件中props与data的结合使用

    如前所述(vue组件属性(props)及私有数据data),vue组件中,props是组件公有属性,对外:data是组件的私有数据,对内.正因为props对外,由外部赋值,因此在组件内部,是只读的,即 ...

最新文章

  1. python比前端好学吗_前端学习到底难不难?
  2. python【蓝桥杯vip练习题库】BASIC-15字符串对比(水题)
  3. angular中父组件给子组件传值-@input
  4. Struts2 学习系列 (2) 访问web资源
  5. mysql 脏数据查询_MySQL数据库02
  6. 细粒度图像分类_北大提出PKU FG-XMedia:细粒度跨媒体检索数据集和评测基准
  7. Flash 与 JavaScript的交互总结
  8. telnet 无法连接_Telnet 为什么不能以 root 身份登录系统?
  9. CCF201312-4 有趣的数(100分)
  10. cisco Router专线路由器配置
  11. imx8qm HDMI-TX调试
  12. thinkphp商城系统 有什么优势 好在哪里
  13. Sublime Text新增GBK编码支持
  14. 《App后台开发运维和架构实践》样章下载
  15. ZigBee-CC2530单片机 - 4路硬件定时器PWM输出
  16. python-opencv视频转图片+图片转视频(步骤详解)(亲测有效)
  17. 竹子的精神高山流水,赞美竹子的句子,竹子散文
  18. 借助计算机音乐,计算机音乐制作在高校作曲教学中的应用
  19. 看似美好,实则无奈,水果业上限如此?
  20. 三个步骤教你如何通过天猫精灵控制智汀,实现不同生态设备相互联动

热门文章

  1. 网站变灰,6行代码,通通变灰
  2. J2ME资源:各厂商SDK和模拟器下载地址
  3. OpenGL 游戏开发: 熟悉练习【《OpenGL超级宝典》第二章】
  4. 锚定情境法:有效控制变量自评偏差
  5. BroadCastReceiver 简介
  6. 计算机网络发展及相关概念
  7. 物联网控制技术作业----信号流图---梅森公式
  8. 基本数据类型之整数类型变量
  9. 干货!区块链入门、进阶、行业专家观点!1000篇好文帮你破解区块链密码!(中篇)...
  10. 色差计算(颜色之间的相似度计算)