精华内容
下载资源
问答
  • Vue 组件 data为什么是函数

    千次阅读 2017-10-08 16:34:30
    但是在组件中,data必须是一个函数,而不能直接把一个对象赋值给它。 Vue.component('my-component', { template: 'OK', data() { return {} // 返回一个唯一的对象,不要和其他组件共用一个对象进行返回 }, })...

    在创建或注册模板的时候,传入一个data属性作为用来绑定的数据。但是在组件中,data必须是一个函数,而不能直接把一个对象赋值给它。

    Vue.component('my-component', {
      template: '<div>OK</div>',
      data() {
        return {} // 返回一个唯一的对象,不要和其他组件共用一个对象进行返回
      },
    })

    你在前面看到,在new Vue()的时候,是可以给data直接赋值为一个对象的。这是怎么回事,为什么到了组件这里就不行了。

    你要理解,上面这个操作是一个简易操作,实际上,它首先需要创建一个组件构造器,然后注册组件。注册组件的本质其实就是建立一个组件构造器的引用。使用组件才是真正创建一个组件实例。所以,注册组件其实并不产生新的组件类,但会产生一个可以用来实例化的新方式。

    理解这点之后,再理解js的原型链:

    var MyComponent = function() {}
    MyComponent.prototype.data = {
      a: 1,
      b: 2,
    }
    // 上面是一个虚拟的组件构造器,真实的组件构造器方法很多
    
    var component1 = new MyComponent()
    var component2 = new MyComponent()
    // 上面实例化出来两个组件实例,也就是通过<my-component>调用,创建的两个实例
    
    component1.data.a === component2.data.a // true
    component1.data.b = 5
    component2.data.b // 5

    可以看到上面代码中最后三句,这就比较坑爹了,如果两个实例同时引用一个对象,那么当你修改其中一个属性的时候,另外一个实例也会跟着改。这怎么可以,两个实例应该有自己各自的域才对。所以,需要通过下面方法来进行处理:

    var MyComponent = function() {
      this.data = this.data()
    }
    MyComponent.prototype.data = function() {
      return {
        a: 1,
        b: 2,
      }
    }

    这样每一个实例的data属性都是独立的,不会相互影响了。所以,你现在知道为什么vue组件的data必须是函数了吧。这都是因为js本身的特性带来的,跟vue本身设计无关。其实vue不应该把这个方法名取为data(),应该叫setData或其他更容易立即的方法名。

    展开全文
  • vuedata为什么是函数类型

    千次阅读 2020-07-30 08:19:50
    一、Vue.js中data的使用 我们先来回顾一下Vue的使用 <div id="app"> <p>{{ name }}</p> <p>{{ age }}</p> </div> var vm = new Vue({ el: '#app', data: { name: '...

    一个组件被复用多次的话,也就会创建多个实例。本质上,这些实例用的都是同一个构造函数。如果data是对象的话,对象属于引用类型,会影响到所有的实例。所以为了保证组件不同的实例之间data不冲突,data必须是一个函数。
    而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。

    一、Vue.js中data的使用

    我们先来回顾一下Vue的使用

    <div id="app">
      <p>{{ name }}</p>
      <p>{{ age }}</p>
    </div>
    
    
    var vm = new Vue({
    	el: '#app',
    	data: {
    		name: 'Lpyexplore',
    		age: '21'
    	},
    	components: {}
    	methods: {}
    })
    
    

    这个例子一般是在我们刚开始学Vue.js时遇到的。我们在这创建了一个Vue的实例对象,并给该实例对象定义了一些属性,比如el 表示跟哪个标签关联 、data表示该实例对象的一些初始属性 、methods表示该实例对象具有的方法等等。一般我们会以组件化的思想去开发(别担心,马上讲解什么是组件化的思想),所以我们还会用到Vue实例对象中的另一个属性components去注册别的组件。

    我们先来了解一下什么是组件化思想,我们一般会在一个页面创建Vue实例,并以该页面作为主文件,然后将其他页面作为该文件的子文件(组件),如图
    在这里插入图片描述
    我们可以看到,图中的Vue实例这个页面就是我们刚开始创建的全局Vue实例对象渲染出来的页面,我们以该页面为主文件。然后想在图上添加什么东西,只需要再创建一个文件,在该文件中创建一个Vue实例,但不通过el进行挂载,而是直接通过注册的方式,注册到另一个页面,作为别的页面的一部分,例如图中的样子。正是因为没有进行挂载,所以这个Vue实例是可以被反复使用的,也就是说可以在很多个页面都注册一次。

    二、data为对象类型

    好了,回到我们的正题data,经过这样的讲解,我们明白,我们第一次创建的Vue实例只会在该页面渲染一次

    function Vue() {
    	this.data= {                   
    		name: '张三',
    		age: '21'
    	}     
    }
    
    //创建了一个Vue实例返回给vm,会调用上面的定义的函数,并创建一个对象,该对象中有data属性
    let vm =new Vue()
    
    //此时的vm应该是这样的   
    vm = {
    	data: {
    		name: '张三', 
    		age: '21'
    	}
    }
    
    //在创建了Vue实例以后我们就要进行渲染页面了
    //这里的name会调用vm.data.name
    <div>{{ name }}</div>
    
    

    三、data为函数

    看了上面的例子,我们再来看看data为函数的例子,一般只有在可复用的Vue实例中,data才为函数

    data: function() {
    	return {
    		name: '李四',
    		age: '55'
    	}
    }
    
    
    • 组件中data使用函数的情况

    其实当我们把组件注册到别的页面上时,也会创建一个Vue实例,就像这个样子

    function Vue() {
    	//此处data的值为一个函数,调用时会return返回一个对象
    	this.data = function() {
    		return {
    			name: '李四',
    			age: '55'
    		}
    	}
    }
    
    //创建了一个Vue实例,会调用上面的定义的函数
    let vm1 =new Vue()
    
    //此时的vm1应该是这样的
    vm1 = {
    	//这里的data,是先获取了函数Vue中的data(data的值为函数),然后得到了data的返回值
    	this.data = {
    		name: '李四',
    		age: '55'
    	}
    }
    
    //将数据渲染到页面上
    //此处的name会调用实例对象vm1.data.name
    <div>{{ name }}</div>     //会渲染成<div>李四</div>
    
    

    这时我们延续上面的例子,我们再在另一个页面注册一下该组件,这时有会调用函数Vue,创建一个实例对象

    //又创建了一个Vue实例,会调用上面的定义的函数
    let vm2 = new Vue()
    
    //此时vm2是这样的
    vm2 = {
    	//这里的data,是先获取了函数Vue中的data(data的值为函数),然后得到了data的返回值
    	data: {
    		name: '李四',
    		age: '55'
    	}	
    }
    
    //将数据渲染到页面上
    //此处的name会调用实例对象vm2.data.name
    <div>{{ name }}</div>     //会渲染成<div>李四</div>
    
    

    如果我们此时把实例对象vm2中的data.name 改为 王五,我们来看一下两个实例对象渲染的结果如何

    //此处的name会调用实例对象vm1.data.name
    <div>{{ name }}</div>   //渲染成  <div>李四</div>
    
    
    //此处的name会调用实例对象vm2.data.name
    <div>{{ name }}</div>   //渲染成  <div>王五</div>
    
    

    我们发现,当实例对象vm2改变了他的data.name值时,实例对象vm1中的data.name值并没有改变。这是因为这两个实例对象在创建时,是先获得了一个函数,将该函数的返回值作为了自己属性data的值,并且这两个实例对象中data的值在栈中对应的堆中的地址也不一样,所以他们不会互相影响。

    • 组件中data为对象的情况

    接下来我们来看一下,如果组件中data使用对象类型会发生怎么样的情况。

    首先先将组件注册到一个页面中,这时会创建一个实例对象vm1

    function Vue() {
    	//此处data的值为一个对象
    	this.data = {
    		name: '李四',
    		age: '55'
    	}	
    }
    
    //创建了一个Vue实例,会调用上面的定义的函数
    let vm1 =new Vue()
    
    //此时的vm1应该是这样的
    vm1 = {
    	//这里的data是获取了函数Vue中的data属性的值
    	data: {
    		name: '李四',
    		age: '55'
    	}
    }
    
    //将数据渲染到页面上
    //此处的name会调用实例对象vm1.data.name
    <div>{{ name }}</div>     //会渲染成<div>李四</div>
    
    

    我们在将该组件注册到另一个页面上,此时会创建一个实例对象vm2

    function Vue() {
    	//此处data的值为一个对象
    	this.data = {
    		name: '李四',
    		age: '55'
    	}	
    }
    
    //创建了一个Vue实例,会调用上面的定义的函数
    let vm2 =new Vue()
    
    //此时的vm1应该是这样的
    vm2 = {
    	//这里的data是获取了函数Vue中的data属性的值
    	data: {
    		name: '李四',
    		age: '55'
    	}
    }
    
    //将数据渲染到页面上
    //此处的name会调用实例对象vm2.data.name
    <div>{{ name }}</div>     //会渲染成<div>李四</div>
    
    

    这时,我们改变实例对象vm2中data.name的值,改为王五,我们再来看一下这个组件在两个页面中分别渲染成什么样子

    //此处的name会调用实例对象vm1.data.name
    <div>{{ name }}</div>   //渲染成  <div>王五</div>
    
    
    //此处的name会调用实例对象vm2.data.name
    <div>{{ name }}</div>   //渲染成  <div>王五</div>
    
    

    我们可以看到,只改变了实例对象vm2中的data.name,为何实例对象vm1中的data.name值也改变了?这里就是要理解引用数据类型的概念了,如果还有不懂得,赶紧翻到引言部分,去看一下。

    因为我们刚开始定义了构造函数Vue时,给他内部的data设置了一个值,该值为对象类型,对象类型在js中称为引用数据类型,在栈中是存储着一个指向内存中该对象的堆中的地址。当我们创建一个实例对象时,要获取函数中的data,其实只是获取了那个堆中的地址,同样的,创建第二个实例对象时,获取的也是那个地址,然而该地址指向的都是同一个数据,也就是{name: ‘李四’, age: ‘55’},所以当我们改变其中一个实例对象的data.name时,其实是先顺着地址去找到内存中的那个对象,然后改变一些值,但是因为所有创建的实例都是按照地址去寻找值的,所以其中一个改变,另一个也跟着改变啦。

    下面放上一个图,让大家更容易理解
    在这里插入图片描述
    所以我们在使用复用型组件时,申明data属性的值时,必须要使用函数类型,因为每次创建实例对象时,他们都是获取属于他们自己的一个对象值,并且对应的堆中的地址都不相同,所以互不影响。此时的情况用图这样表示:
    在这里插入图片描述

    结束语

    所以讲了那么多,还是一个概念,引用数据类型的表现形式,如果还是有小伙伴不懂的,一定要翻到引言部分,点击链接去看一下这个概念,否则很难理解本篇文章。因为本文也是说到构造函数创建实例对象的概念,如果对于JavaScript中对象的概念不理解的话,也可以翻阅我之前写的一篇文章,全面剖析了js中的对象概念——充分了解JavaScript中的对象,顺便弄懂你一直不明白的原型和原型链。

    希望这篇文章能解开你们心中的疑惑,喜欢的点个关注,加个收藏,谢谢各位。

    转载自:https://blog.csdn.net/l_ppp/article/details/106673156#comments_12921812

    展开全文
  • Vue 组件 data 为什么必须是函数 文章目录Vue 组件 data 为什么必须是函数要理解这个问题,得从原型说起3 个栗子 理解后在看源码使用 debugger,看下 new vue 发生了什么1. 走到了初始化 vue 的步骤2. 来到 init ...

    Vue 组件 data 为什么必须是函数

    教科书般的解释(官网原话)

    当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象

    👆 注意不要囫囵吞枣,感受下下面 2 句话:

    • 组件为什么必须是函数
    • 组件可被创建多个实例

    很长一段时间我都理解为:为什么 vue 的 data 需要函数返回,那我们直接引入 JS 使用的时候,new Vue也没见的一定要函数返回啊。直到今天才发现是理解少了几个字,vue 创建的组件的 data 才需要函数返回

    不想看分析的直接看这里

    new Vue 可以不使用函数返回的原因在于,每次new的时候,传入的都是新的对象(新的内存地址)。所以修改其中一个 vue 实例并不会影响其他实例


    对于组件而言,组件定义好之后是有默认值 (我们把一个组件引入后,修改了部分值后。再次引入相同的组件时,第二次引入的组件初始值还是保持原来设置的) 所以在组件注册(vue 的一个内部流程)的时候,vue 会把这个组件传入的配置存下来,多次生成同一个组件的时候都会从存下来的配置中取值,然后通过new创建新的组件实例。可如果这时候 data 为对象 (引用类型的内存地址是一样的) ,那每次生成新的组件实例的 data 都指向了同一个内存区域,这时候其中一个同类型组件值更新了。其余的都会跟着一起更新

    要解决上述说的组件的问题,就需要用函数的形式,每次创建组件都通过 function 返回一个新的对象(内存地址不一样的对象)。这样组件的 data 才是自己单独的

    要理解这个问题,得从原型说起

    不熟看这里 👉 原型和原型链-基础,但是非常重要

    3 个栗子 理解后在看源码

    1. 案例 1:

    function Animal() {}
    Animal.prototype.data = { name: '宠物店', address: '广州' }
    var dog = new Animal()
    var cat = new Animal()
    console.log(dog.data.address) // 广州
    console.log(cat.data.address) // 广州
    dog.data.address = '东莞'
    console.log(cat.data.address) // 东莞
    dog.data === cat.data // true
    

    第一个小结论

    dog 和 cat 的原型都是 Animal。自然会继承原型的属性。继承过来后,因为 data 是普通对象,属于引用数据类型,所以 dog 和 cat 的 data 其实都指向同一块内存地址

    就连严格运算符判断都是相等的,说明他们值相等,内存地址也相同,修改其中一个将会影响另外一个

    2. 案例 2:

    function Animal() {
      this.data = this.data()
    }
    Animal.prototype.data = function() {
      return { name: '宠物店', address: '广州' }
    }
    var dog = new Animal()
    var cat = new Animal()
    console.log(dog.data.address) // 广州
    console.log(cat.data.address) // 广州
    dog.data.address = '东莞'
    console.log(cat.data.address) // 广州
    console.log(dog.data.address) // 东莞
    dog.data === cat.data // false
    

    稍微解释下:为什么第二行:this.data = this.data()

    我们在执行 new 的过程中,Animal 其实充当了constructor。详情可以看 new 一个对象发生了什么。这时候 this.data 还是一个函数,还没执行的函数,所以调用一下 this.data()。让函数返回一个值。然后重新赋值给 this.data

    结论 2
    用了 function 后,data 都被锁定在当前 function 的作用域中,然后被返回出去,相当于创建了另外一个对象,所以多个实例之间不会相互影响

    3. 案例 3

    function Animal({ data }) {
      this.data = data
    }
    var dog = new Animal({ data: { name: '宠物店', address: '广州' } })
    var cat = new Animal({ data: { name: '宠物店', address: '广州' } })
    
    console.log(dog.data.address) // 广州
    console.log(cat.data.address) // 广州
    
    dog.data === cat.data // false
    

    结论 3

    注意这里的变量声明方式,是直接放在了构造函数中,并不是通过原型链来查找的。这也就是为什么new Vue的时候 data 可以为非函数,在构造函数执行的时候,data 就已经相互隔离

    使用 debugger,看下 new vue 发生了什么

    多图预警!! new Vue 发生了什么!!

    关于 new Vue,可以看案例 3。在 new 的过程中,就已经传入参数赋值

    开始 debugger

    <!-- 引入vue -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    
    debugger
    // 在 new Vue之前,进入debugger模式
    var app = new Vue({
      el: '#app',
      data: { message: 'Hello Vue!' }
    })
    

    1. 走到了初始化 vue 的步骤

    2. 来到 init 方法内部

    • 4994 行 我们常见的 vm 对象。其实就是 vue 的 this 对象。(图片截的不够长,往上一点能看到 vm = this)
    • 4998 我们常说的生命周期第一步 beforeCreate
    • 5000 这是我们今天要深究的函数:initState 初始化 data 对象的
    • 5002 生命周期第二步 create

    验证了 vue 生命周期的一个知识点:beforeCreate 还不能拿到 this.data。需要在 create 的时候才能拿到

    3. 来到 initState 方法

    • 可以看到初始化props、初始化methods。然后才到初始化 data。如果没有 data 还会给个默认值{}
    • 初始化 data 后开始处理 computed。然后挂载 watch
    • 主题是研究 data 。继续进入到 initData 函数里面

    4. initData 方法

    data = vm._data = typeof data === 'function' ? getData(data, vm) : data || {}
    
    • 可以看到是有判断,如果传入的是函数,就调用该函数(getData方法里面就是调用函数返回对象的)。如果不是函数就默认拿 data,否则还是个默认值。
    • 接下来的步骤就是开始做一些代理,数据挟持的监听proxyobserver 之类的 不在我们 data 讨论范畴了。下次在分析

    小结

    new vue 小结

    new Vue 的过程和案例 3 是非常相似的,只是单纯的传入对象,然后使用 new 的特性,给 vm._data 对象赋值,其实也就是为当前的 vue 实例的 data 赋值,由于 new 的特性在,所以 data 不强求函数返回,当然也可以函数返回

    new Vue 的源码简单的看下。那继续看今天主角 components 的实现

    components 作为一个组件类型,只是一个简单的工厂模式(一开始的组件参数都是定好的,需要就创建一个新的组件,简称工厂模式),创建很多的组件实例。就像案例 1 一样

    还是先写一个 debugger 进入源码

    日常多图预警!!

    <!-- 引入vue -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    
    // 在 new Vue之前,进入debugger模式
    debugger
    // 定义一个名为 button-counter 的新组件
    Vue.component('button-counter', {
      data: function() {
        return {
          count: 0
        }
      },
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
    })
    

    1. 进入到了 initAssetRegisters 初始化登记注册(组件注册)

    • 5225 行。判断要注册的是一个 component 组件
    • 5232 行。判断要注册的是 directive 指令。注册事件都的确在 initAssetRegisters中。
    • 5226 行 validateComponentName 验证组件名称是否被占用
    • 5229 是判断组件是否有定义的名称,没有就用自己组件的标签。这是为了 上一步,验证组件是否已经生成的。
    • 5230 this.options._base.extend(definition) 有这么一段代码,下一步就到这里面看看

    2. extend 函数中

    • this.options._base 其实就是下图中的 Vue。调用 Vue.extend
    • 留意看 5146-5148 行。我在 5147 打了断点。后续的步骤会回到这里
    • 这一路执行下来。生成了一个Sub对象。
    • 5149-5155 行。就是准备一个 new 的过程。
    Sub.prototype = Object.create(Super.prototype) // 构造器原型
    Sub.prototype.constructor = Sub // 构造函数等于Sub方法。在new的时候就会执行Sub里面的内容
    Sub.cid = cid++
    Sub.options = mergeOptions(Super.options, extendOptions) // 合并参数等
    
    • 5192 行。把 Sub 对象 return 了回去。那就是回到了 initAssetRegisters 函数那边去了
    • 回去后,把 Sub 赋值给了definition 对象(第一步的 5230 行)
    • 接着 definition 也被返回出去了。其中这一个返回被一个函数包裹着。函数被赋值为 Vue[type](第一步的 5217 行接收了)这时候 type 是component。相当于 调用 Vue.component 的话,返回值就是Sub
    • 重点: 5152 行和 5154 行中。Sub.options 合并了 2 个对象,分别是 Super.options(应该是父组件的一些参数了)。第二个就是合并了自己的参数,其中 data 就在 5154 行中。后面的步骤还会说这个 options

    有点长,分开 2 张图


    3. 想办法进入 init 方法看看

    因为在步骤 2 中我们留了个断点,而一开始创建组件的方式是全局创建的。可能很多步骤没有看到,把代码改一改,改成局部组件,在 debugger 一下

    代码改成这样子,因为之前留有断点,所以就无须 debugger 了,刷新即可直接到我们定好的断点里面去:

    var ComponentA = {
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>',
      data() {
        return { count: 0 }
      }
    }
    var app = new Vue({
      el: '#app',
      components: {
        'component-a': ComponentA
      }
    })
    

    能回到 Sub 里面。说明我们之前摸索的步骤被调用了。Sub 方法被调用,才会执行到init。那我们在 init。返回上一步,看下是谁调用的。

    看来这一步就是开始 new 一个新的组件。所以触发到了 init 方法

    这次进来总算看到有下一步的函数

    4. 进入组件的 init 方法中

    • 特别熟悉的感觉。没错!就是 new Vue 那个过程!毕竟组件也有自己的生命周期,参数,子组件,所以又回到了这里
    • initState - initData 的过程我就不重复。不清楚的可以再看上面 new Vue的过程。

    5. 组件的 data 在 initData 中的作用

    这里开始绕了。思路要清晰

    • 回想步骤 2 extend 函数中 5152 行。和 5154 行。是不是存储了组件的 options

    • 那在下图的 4700 行中。vm 就是当前的组件。他的options就是来自组件注册时,生成的Sub对象

    6. 这时候抽象出来一些代码

    • Sub.options 是组件注册的时候就开始有值了。所以我们也给个默认值演示
    • Sub.prototype.init 估计是后期赋值,赋值为创建 vue 的生命周期的函数。所以我们也给他来一个简化版的函数,只模拟赋值 this.data 的过程,看一下效果
    var Sub = function() {
      this.init()
    }
    Sub.prototype = {}
    Sub.prototype.constructor = Sub
    Sub.prototype.init = function() {
      this.data = typeof Sub.options.data === 'function' ? Sub.options.data() : Sub.options.data
    }
    Sub.options = {} // 等下会给默认值
    

    7. 根据抽象出来的代码,模拟 new 几个组件

    第一次尝试用的是 data 对象形式:

    ::: tip 原理和最上面的案例 1 一样

    因为 data 是引用类型。并且一开始 Sub.options 就是有值的,在创建新组件的时候拿的都是同一个地方的值

    :::

    // 上面也说了。先给sub.options来个默认值。模拟传入的参数
    Sub.options = {
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>',
      data: {
        count: 0
      }
    }
    
    // 结合步骤6的代码。创建3个组件
    var component1 = new Sub()
    var component2 = new Sub()
    var component3 = new Sub()
    
    console.log(component1) // {data:{count:0}}
    console.log(component2) // {data:{count:0}}
    console.log(component2) // {data:{count:0}}
    
    // 看着好像没啥问题?我们来修改一个组件的值
    component1.data.count = 1
    
    // 传说中的组件中值会相互影响情况出现了
    console.log(component1) // {data:{count:1}}
    console.log(component2) // {data:{count:1}}
    console.log(component3) // {data:{count:1}}
    

    如果改成函数的形式呢?

    ::: tip 原理和案例 2 一样。

    虽然这时候 Sub.options 拿到也是同一个地方的值。可是 Sub.options.data 已经是函数类型,而不是引用类型。函数执行后,返回的值都是不用堆内存的地址,所以修改某一个Sub实例(组件的值)其余的组件都不会受到影响

    :::

    // 上面也说了。先给sub.options来个默认值。模拟传入的参数
    Sub.options = {
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>',
      data() {
        return {
          count: 0
        }
      }
    }
    
    // 结合步骤6的代码。创建3个组件
    var component1 = new Sub()
    var component2 = new Sub()
    var component3 = new Sub()
    
    console.log(component1) // {data:{count:0}}
    console.log(component2) // {data:{count:0}}
    console.log(component3) // {data:{count:0}}
    
    component1.data.count = 2
    // 现在就不会互相影响了
    console.log(component1) // {data:{count:2}}
    console.log(component2) // {data:{count:0}}
    console.log(component2) // {data:{count:0}}
    

    8. 最后总结一下 demo

    可以自己试着改一改。跑一跑

    var Sub = function() {
      this.init()
    }
    Sub.prototype = {}
    Sub.prototype.constructor = Sub
    Sub.prototype.init = function() {
      this.data = typeof Sub.options.data === 'function' ? Sub.options.data() : Sub.options.data
    }
    Sub.options = {
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>',
      data() {
        return {
          count: 0
        }
      }
    }
    
    // 结合步骤6的代码。创建3个组件
    var component1 = new Sub()
    var component2 = new Sub()
    var component3 = new Sub()
    
    console.log(component1) // {data:{count:0}}
    console.log(component2) // {data:{count:0}}
    console.log(component3) // {data:{count:0}}
    
    component1.data.count = 2
    // 现在就不会互相影响了
    console.log(component1) // {data:{count:2}}
    console.log(component2) // {data:{count:0}}
    console.log(component2) // {data:{count:0}}
    

    原文首发:Vue 组件 data 为什么必须是函数 这是新的博客地址,感兴趣可以看看

    展开全文
  • 在 new Vue() 中,data 是可以作为一个对象进行操作的,然而在 component 中,data 只能以函数的形式存在,不能直接将对象赋值给它。 new Vue({ el: '#app', data: { message: 'Love' }, template: '<p>...

    new Vue() 和component组件中使用

    new Vue() 中,data 是可以作为一个对象进行操作的,然而在 component 中,data 只能以函数的形式存在,不能直接将对象赋值给它。

    new Vue({
        el: '#app',
        data: {
            message: 'Love'
        },
        template: '<p>It’s great to love cakes.</p>'
    })
    // 因为组件是可复用的 Vue 实例
    // 定义一个名为 button-counter 的新组件
    Vue.component('button-counter', {
      data: function () {
        return {
          count: 0
        }
      },
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
    })

    data为什么是函数, 不是对象?

    这并非是 Vue 自身如此设计,而是跟 JavaScript 特性相关,我们来回顾下 JavaScript 的原型链

    var Component = function() {};
    Component.prototype.data = {
        message: '10'
    }
    var component1 = new Component(),
        component2 = new Component();
    component1.data.message = '20';
    console.log(component2.data.message);  // 20
    
    // 上面原因是因为component1和component2的属性data引用的是同一个内存地址

    从上面可以了解到,vue组件就是一个vue实例。

    JS中的实例是通过构造函数来创建的,每个构造函数可以new出很多个实例,那么每个实例都会继承原型上的方法或属性。vuedata数据其实是vue原型上的属性,数据存在于内存当中。vue为了保证每个实例上的data数据的独立性,规定了必须使用函数,而不是对象。

    因为使用对象的话,每个实例(组件)上使用的data数据是相互影响的,这当然就不是我们想要的了。对象是对于内存地址的引用,直接定义个对象的话组件之间都会使用这个对象,这样会造成组件之间数据相互影响。

    以上两个实例都引用同一个对象,当其中一个实例属性改变时,另一个实例属性也随之改变,只有当两个实例拥有自己的作用域时,才不会互相干扰。

    var Component = function() {
        this.data = this.data()
    }
    Component.prototype.data = function(){
        return {
            message: '10'
        }
    }
    var component1 = new Component(),
        component2 = new Component();
    component1.data.message = '20';
    console.log(component2.data.message);  // 10

    为什么使用函数不会有这种问题

    使用函数后,使用的是data()函数,data()函数中的this指向的是当前实例本身。

    展开全文
  • 为什么vuedata必须是一个函数

    万次阅读 多人点赞 2019-03-28 10:25:54
    本文从JavaScript原型链角度来解释为什么vue中的data必须是一个函数 VUE组件中的data必须是函数 类别引用数据类型 Object是引用数据类型,如果不用function返回,每个组件的data都是内存的同一个地址,一个数据...
  • vue data 为什么需要函数return?

    千次阅读 2019-07-16 10:53:27
    vue为了保证每个实例上的data数据的独立性,规定了必须使用函数,而不是对象。 因为使用对象的话,每个实例(组件)上使用的data数据是相互影响的,这当然就不是我们想要的了。对象是对于内存地址的引用,直接定义...
  • 主要介绍了Vue组件为什么data必须是一个函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 为什么vuedata必须的返回函数

    千次阅读 2018-09-27 18:21:09
    data的值是一个对象, 是引用数据类型,如果不用函数return ,每个组件的data 都是同一个对象,一个数据改变了其他也改变了; 所以为了不让多处的组件共享同一data对象,只能返回函数。 更深的理解 ...
  • vuedata必须是函数

    千次阅读 2017-10-08 20:57:52
    看了好多博客论坛啥的,我比较笨不是很理解,包括我之前转载的一篇,不过我转载的我是看懂了,今天没事重新过了下官网,下面我们一起看看官网是如何给出解答的,这里面第一...通过 Vue 构造器传入的各种选项大多数都可
  • 主要给大家介绍了关于Vue的组件中data选项为什么必须是函数的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Vue具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • 如果是对象会导致 对象是引用类型,当同一个组件被多次...将data设置一个函数,该函数会返回一个初始数据对象,用function return 其实就相当于申明了新的变量,相互独立 data () { return { items: ['a', '...
  • vue--为什么data属性必须是一个函数

    千次阅读 2019-02-26 17:25:21
    问题描述:为什么vue组件中,我们的data属性必须是一个函数,new Vue()中的data除外,因为new Vue中只有一个data属性。 原因:因为我们能抽离出来的组件,肯定是具有复用性的,它在项目中会存在多个实例。如果data...
  • Vue组件data选项为什么必须是个函数Vue的根实例则没有此限制?
  • Vuevue中的data为什么是一个函数

    千次阅读 2019-04-18 16:04:20
    为什么在项目中data需要使用return返回数据呢? 大家知道用组件化来写vue项目,每个.vue文件都是一个个组件。那什么是vue中的组件? 官网写的很易懂——组件就是一个可复用的vue的实例。 这也就意味着如果你的data是...
  • vue data 为什么返回一个函数

    千次阅读 2019-02-25 15:18:54
    但是在组件中,data必须是一个函数,而不能直接把一个对象赋值给它。 Vue.component('my-component', { template: '&amp;lt;div&amp;gt;hello Vue&amp;lt;/div&amp;gt;', da...
  • 今天学习vue组件的时候,发现组件里面的东西,其实和定义的root实例...这是为什么呢下面举一个小例子来类比一下 正确的定义一个组件: //定义组件 <template id="cpn"> <div> <h2>我是{{name}}...
  • vue组件中data为什么必须是一个函数

    千次阅读 2020-03-21 18:11:57
    总结: 综上可知,如果data是一个函数的话,这样每复用一次组件,就会返回一份新的...所以说vue组件的data必须是函数。这都是因为js的特性带来的,跟vue本身设计无关。 js本身的面向对象编程也是基于原型链和构造...
  • 分析Vue.js组件中的data为何是函数类型而非对象类型引言正文一、Vue.js中data的使用 引言 要理解本篇文章,必须具备JavaScript中对象的概念,如果有想要深入了解的小伙伴,可以查看我之前剖析的js中对象概念的一篇...
  • vue data里回调函数里 this指向

    千次阅读 2019-04-16 15:05:25
    **vue data里回调函数里 this指向** 使用elementui的日期选择器,限制启止时间选择 — 以后的bug节省时间 html: <el-date-picker v-model="searchData[item.prop]" type="date" value-format=...
  • 主要介绍了vue data不可以使用箭头函数问题,本文通过源码解析给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
  • Q: vue中的data为什么是一个函数 类型:Object | Function 限制:组件的定义只接受 function 当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 113,443
精华内容 45,377
关键字:

vue里的data为什么是函数

vue 订阅