一文带你简单理解Vue的data为何只能是函数

 更新时间:2022年10月16日 09:15:17   作者:当然是黑猫警长啦  
如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data,下面这篇文章主要给大家介绍了关于简单理解Vue的data为啥只能是函数的相关资料,需要的朋友可以参考下

前言

在学习vue的时候vue2只有在组件中严格要求data必须是一个函数,而在普通vue实例中,data可以是一个对象,但是在vue3出现后data必须一个函数,当时看着官方文档说的是好像是对象的引用问题,但是内部原理却不是很了解,今天通过一个简单的例子来说明为啥data必须是一个函数

参考 (vue2data描述)

参考: (vue3data描述)

1.Vue3中的data

const { createApp } = Vue
const app = {
    data: {
        a: 1
    },
    template: `
    <h1>{{a}}</h1>
    `
}
createApp(app).mount('#app')

可以看到上来vue就给了警告说明data必须是一个函数 下面直接抛错

2.vue中的data

var app = new Vue({
    el: '#app',
    data: { a: 'hello world' }
})

这种写法是可以的,前面提过普通实例data可以是对象,但是在组件中必须是函数, 那么在vue2中难道普通实例就没有缺陷嘛?答案:是有缺陷的, 比如这样

<div id="app1">{{ message }}</div>
<div id="app2">{{ message }}</div> 
const data = { message: 'hello world' }
const vue1 = new Vue({
    el: '#app1',
    data
})

const vue2 = new Vue({
    el: '#app2',
    data
})

这样在页面中会显示2个内容为hello world的div标签 那么当我们通过实例去改变messag呢?

 vue1.message = 'hello Vue'

奇怪的事情发生了,我知识改变了vue1的实例中的数据,但是其他实例的数据也发生了改变,相信很简单就能看出来这应该是共用同一个对象的引用而导致的,这在开放中是非常不友好的,开发者很容易就产生连串的错误,vue2也知道这种缺陷只是没有在普通实例中去体现而已,只在组件中实现了对于data的约束

为了让大家更好的立即为啥data必须是一个函数,黑猫在此简单实现一个vue的实例然后来证明为啥data是一个函数,以及如果data不是一个函数,我们应该如何处理

3.证明data是函数以及原理实现

在实现简单原理之前,我们需要搞清楚Vue在创建实例之前,对于data到底做了什么事情简单来说就是:

vue 在创建实例的过程中调用data函数返回实例对象通过响应式包装后存储在实例的data上并且实例可以直接越过data上并且实例可以直接越过data上并且实例可以直接越过data访问属性

1.通过这句描述可以知道Vue是一个构造函数,并且传入的参数中有一个data的属性,我们可以$data去访问,也可以直接访问这个属性,并且我们需要对这个data做代理
那么简单实现如下

function Vue(options) {
    this.$data = proxy(options.data())
}
function proxy(options) {
    return new Proxy(options, {
        get(target, key, value, receiver) {
            return Reflect.get(target, key, value, receiver)
        },
        set(target, key, newValue, receiver) {
            Reflect.set(target, key, newValue, receiver)
        }
    })
}
const data = function () {
    return {
        a: 'hello world'
    }
}
const vue1 = new Vue({
    data
})
const vue2 = new Vue({
    data
})
vue1.$data.a = 'hello Vue'
console.log(vue1.$data.a) // hello Vue
console.log(vue2.$data.a) // hello world

通过简单实现可与看出来,当我们的data是一个函数的时候,在Vue的构造函数中,只有有实例创建就有执行data函数,然后返回一个特别的对象,所以当我们修改其中一个实例的时候并不会对其他实例的数据产生变化

那么当data不是一个函数呢 ,我们简单改下代码,代码如下

function Vue(options) {
    this.$data = proxy(options.data)
}
function proxy(options) {
    return new Proxy(options, {
        get(target, key, value, receiver) {
            return Reflect.get(target, key, value, receiver)
        },
        set(target, key, newValue, receiver) {
            Reflect.set(target, key, newValue, receiver)
        }
    })
}
const data = {
    a: 'hello world'
}
const vue1 = new Vue({
    data
})
const vue2 = new Vue({
    data
})
vue1.$data.a = 'hello Vue'
console.log(vue1.$data.a) // hello Vue
console.log(vue2.$data.a) // hello Vue

可以看出,由于共用一个对象,当代理的时候也是对同一个对象进行代理,那么当我们通过一个实例去改变数据的时候,就会影响其他实例的状态

4.如果data必须是一个对象呢?

假如有人提出如果data是一个对象,那么我们应该如何处理呢,其实也非常简单,在代理的时候我们可以将传入的data对象通过深拷贝即可,这样我们就不会使用相同引用的对象啦。
[深拷贝封装参考我以前的文章](不一样的深拷贝)

总结

到此这篇关于Vue的data为何只能是函数的文章就介绍到这了,更多相关Vue data为何只能是函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue中插入HTML代码的方法

    Vue中插入HTML代码的方法

    这篇文章主要介绍了Vue中插入HTML代码的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • vue实现点击隐藏与显示实例分享

    vue实现点击隐藏与显示实例分享

    在本篇文章中小编给大家分享了vue如何实现点击隐藏与显示的相关内容,有需要的朋友们跟着学习下。
    2019-02-02
  • vue中$set与$delete的使用及说明

    vue中$set与$delete的使用及说明

    这篇文章主要介绍了vue中$set与$delete的使用及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • VUE+element-ui文件上传的示例代码

    VUE+element-ui文件上传的示例代码

    图片和文件上传在很多项目中都可以使用的到,本文主要介绍了VUE+element-ui文件上传的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Vue左滑组件slider使用详解

    Vue左滑组件slider使用详解

    这篇文章主要为大家详细介绍了Vue左滑组件slider的使用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08
  • 解决VUEX的mapState/...mapState等取值问题

    解决VUEX的mapState/...mapState等取值问题

    这篇文章主要介绍了解决VUEX的mapState/...mapState等取值问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • vue自定义过滤器创建和使用方法详解

    vue自定义过滤器创建和使用方法详解

    这篇文章主要为大家详细介绍了vue自定义过滤器创建和使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • vue中使用postcss-px2rem的两种方法

    vue中使用postcss-px2rem的两种方法

    这篇文章主要介绍了vue项目中使用postcss-px2rem的方法总结,在项目中为了屏幕适配,经常会用到rem,postcss-px2rem就是为了让我们直接在将代码中px自动转化成对应的rem的一个插件,需要的朋友可以参考下
    2022-05-05
  • vue 如何从单页应用改造成多页应用

    vue 如何从单页应用改造成多页应用

    这篇文章主要介绍了vue 如何从单页应用改造成多页应用,帮助大家更好的理解和使用vue,感兴趣的朋友可以了解下
    2020-10-10
  • vue如何解决this.refs拿取v-for下元素undefine问题

    vue如何解决this.refs拿取v-for下元素undefine问题

    这篇文章主要介绍了vue如何解决this.refs拿取v-for下元素undefine问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05

最新评论