Vue之`data`

2019-01-16  本文已影响0人  人话博客

Vue 中,我们定义数据使用 data.

Vue 的根节点里,它是一个对象.

var app = new Vue({
    el: '#app',
    data: {
      msg: 'this is msg'
    })

components 中,它是一个函数,内部返回一个对象

export default {
  name: 'cart-buy-button',
  data () {
    return {
      testNum: 0,
      addCounter: 0,
      removeCounter: 0
    }
  }
}

因为 vue 根节点,在整个vue单页面实例中,它有且只有一个,所以 data 可以设置成一个 Object{}
但是子组件可能会多次实例化和调用,所以为了确保子组件的数据的独立性和隔离性,需要使用 data(){return{}} 的方法.每次返回一个新的对象.


数据流的单向流动.

Vue 中,我们使用插值表达式,往某个非表单元素中插入 data 里的数据时,数据是单向流动的.

<div id='app'>
    <div>{{msg2}}</div>
    <button @click="changeDataMsg">change.data.msg</button>
</div>


var app = new Vue({
    el: '#app',
    data: {
        msg2: 'this is msg'
    },
    methods: {
      changeDataMsg() {
        this.msg2 = Math.random(1000).toString().substring(0, 2) + this.msg2
      }
}

结果:

vue数据单向流动.gif

在初学vue的时候,觉得挺新奇.
过了几天,觉得就是这样的.
在过了几天就发现,原来是

Vue在实例化的时候会把 data 里的属性使用 ES5 提供的 Object.defineProperty 重新定义一遍,并设置其属性的 getset

也就是说,我们给定的data属性,其内部是有可能这么一段代码.

let obj = {
  name: '李四',
  age: 22
}

let defaultName = '李四'
Object.defineProperty(obj, 'name', {
  set(newVal) {
    defaultName = newVal
    // 检测到新值,更新 dom
  },
  get() {
    return defaultName
  }
})

let defaultAge = 22
Object.defineProperty(obj, 'age', {
  set(newVal) {
    defaultAge = newVal
    // 检测到新值,更新 dom
  },
  get() {
    return defaultAge
  }
})

也就是说,所有(不管是根Vue还是components)的实例的data属性,都会被使用 Object.defineProperty重新定义.这也就是为什么Vue对于表单元素的双向绑定和非表单元素的单向数据流属性的基础.

关于 Object.defineProperty 可以参考我之前写的一篇
Object.defineProperty 解析


非 data 属性呢?

我们都知道,js是一本特别灵活的语言,可以很随意的给对象添加属性,而需要实现声明.

 created() {
      // 在非data里定义的数据,没有被 Object.defineProperty重新定义,所以无法检测到get,set,也不无法更新dom.
      this.defineOnCreatedProperty = '这是在 created 钩子函数里定义的变量'
    },

created钩子函数里,随意的给当前实例添加一个 defineOnCreatedProperty属性,是否也支持单向数据流&双向绑定呢?

<div id='#app'>
 <div>{{defineOnCreatedProperty}}</div>
    <button @click="changeCreatedData">change.created.data</button>
</div>

changeCreatedData() {
        this.defineOnCreatedProperty = '能否检测到改变????'
      }

结果:

vue数据单向流动2.gif

怎么点,都不能像 data 里定义的数据那样,支持数据流的特性.

原因也很简单:

data里声明,而是你自己定义的属性,那它就是一个普通的属性,vue不会去对待它(使用Object.defineProperty)去重新定义.所以,就无法检测到变化,不能检测到变化,就无法支持所有的数据流特性了.


总结

  1. vue的数据流,是里用的ES5提供的Object.defineProperty方法来重新定义data数据,以便获取属性的get/set来检测属性的变化,以实现数据流.
  2. 自己随便定义的属性,比如 this.defineOnCreatedProperty没有定义在data,没有Object.defineProperty去重新定义此属性以监控set/get ,当然就无法实现所谓的数据流了.
上一篇下一篇

猜你喜欢

热点阅读