美文网首页
Vue之`data`

Vue之`data`

作者: 人话博客 | 来源:发表于2019-01-16 12:41 被阅读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 ,当然就无法实现所谓的数据流了.

    相关文章

      网友评论

          本文标题:Vue之`data`

          本文链接:https://www.haomeiwen.com/subject/doxmdqtx.html