Vue的data为啥只能是函数原理详解

 更新时间:2022年10月19日 14:13:18   作者:当然是黑猫警长啦  
这篇文章主要为大家介绍了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 函数原理的资料请关注脚本之家其它相关文章!

相关文章

  • Vue2.0利用 v-model 实现组件props双向绑定的优美解决方案

    Vue2.0利用 v-model 实现组件props双向绑定的优美解决方案

    本篇文章主要介绍了Vue2 利用 v-model 实现组件props双向绑定的优美解决方案,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • vue大型项目之分模块运行/打包的实现

    vue大型项目之分模块运行/打包的实现

    这篇文章主要介绍了vue大型项目之分模块运行/打包的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • vue.js动态设置VueComponent高度遇到的问题及解决

    vue.js动态设置VueComponent高度遇到的问题及解决

    这篇文章主要介绍了vue.js动态设置VueComponent高度遇到的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 查看vue版本号以及vue/cli脚手架版本号方式

    查看vue版本号以及vue/cli脚手架版本号方式

    这篇文章主要介绍了查看vue版本号以及vue/cli脚手架版本号方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • vue-virtual-scroll-list虚拟组件实现思路详解

    vue-virtual-scroll-list虚拟组件实现思路详解

    这篇文章主要给大家介绍了关于vue-virtual-scroll-list虚拟组件实现思路的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2023-02-02
  • 如何使用vue过滤器filter

    如何使用vue过滤器filter

    这篇文章主要介绍了如何使用vue过滤器filter,对vue感兴趣的同学,可以参考下
    2021-05-05
  • uniapp中使用lottie实现JSON动画的操作步骤

    uniapp中使用lottie实现JSON动画的操作步骤

    这篇文章主要介绍了如何在项目中使用JSON动画组件,包括创建目录结构、下载JSON文件、编写自定义组件代码以及组件的使用方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-01-01
  • vue中使用h5 video标签实现弹窗播放本地视频的方法

    vue中使用h5 video标签实现弹窗播放本地视频的方法

    本文主要介绍了vue中使用h5 video标签实现弹窗播放本地视频的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • vue中jsencrypt与base64加密解密的实用流程

    vue中jsencrypt与base64加密解密的实用流程

    vue项目里面使用到的加密和解密的方法,本文主要介绍了vue中jsencrypt与base64加密解密的实用流程,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • 前端单独实现vue动态路由的示例代码

    前端单独实现vue动态路由的示例代码

    Vue动态路由权限涉及根据用户权限动态生成路由配置,实现此功能可增强应用安全性、灵活性,提升用户体验和开发效率,本文就来介绍一下前端单独实现vue动态路由的示例代码,感兴趣的可以了解一下
    2024-09-09

最新评论