Vue3.0学习第三天 数据双向绑定

1,989 阅读4分钟

01-vue3的双向数据绑定

我们都知道,vue3在数据的双向绑定上与vue2完全不同

  • vue2 基于Object.defineProperty()实现
    • Object.defineProperty() 在一个对象上定义一个新的属性,或者修改这个对象上已经存在的属性
// 演示代码
let Person = {}
let backup = null // 备份数据
Object.defineProperty(Person, 'name', {
    value: 'Jack', // key 的值
    writable: true, // 是否可写,默认false
    enumerable: true, // 是否可枚举,是否可for in
    configurable: ture, // 是否可配置,是否可删除等,默认fasle
    get: function() { // getter方法
        return backup
    },
    set: function(newVal) {  // setter方法,接受参数为新值
        backup = newVal
    }
})
  • vue3 基于Proxy
    • new Proxy()在对象层面上进行拦截,不需要对对象中的属性进行遍历依次绑定
// 演示代码
let self = this;
this.$data = new Proxy(this.data, {
  get: function(target, key, vceiver) {
      return target[key]
  },
  set: function(target, key, value, vceiver) {
      target[key] = value
      slef.render()
  }
})

总结Proxy与Object.defineProperty(obj, prop, desc)方式相比有以下优势:

  1. 丢掉麻烦的备份数据
  2. 省去for in 循环
  3. 可以监听对象和数组变化
  4. 代码更简化

02-组合API-reactive函数

  • reactive函数可以绑定一个复杂类型数据,使它成为一个响应式数据
// 演示代码
import { reactive } from 'vue' // 引入reactive函数
export default {
  name: 'App',
  setup () {
    // 普通对象数据
    // const obj = {
    //   name: 'ls',
    //   age: 18
    // }
    
    // 使用reactive进行双向绑定的对象数据
    const obj = reactive({
      name: 'ls',
      age: 18
    })

    // 修改名字方法
    const updateName = () => {
      console.log('updateName')
      obj.name = 'zs'
    }

    return { obj ,updateName}
  }
}

总结:  通常是用来定义响应式复杂类型数据

03-组合API-toRef函数

  • toRef函数可以转换响应式对象某个属性为单独响应式数据,并且值是关联的
// 演示代码
import { reactive, toRef } from 'vue'
export default {
  name: 'App',
  setup () {
    // 1. 响应式数据对象
    const obj = reactive({
      name: 'ls',
      age: 10
    })
    // 2. 如果模板中只需要使用name数据
    // 注意:从响应式数据对象中解构出的属性数据,不再是响应式数据
    // 不能直接 let { name } = obj 解构,这样出来的是一个普通数据
    const name = toRef(obj, 'name')
    const updateName = () => {
      console.log('updateName')
      // 注意:toRef转换响应式数据会包装成对象,其中value属性用来存放值
      name.value = 'zs'
    }

    return {name, updateName}
  }
}

总结:

  • 平常可能不会用到,使用场景,只需要对象中某个属性双向绑定时。
  • 会把数据包装成对象,修改值时是修改这个对象的value属性。

04-组合API-toRefs函数

  • toRefs函数可以转换响应式对象中所有属性为单独响应式数据,对象成为普通对象,并且值是关联的
// 演示代码
import { reactive, toRefs } from 'vue'
export default {
  name: 'App',
  setup () {
    // 1. 响应式数据对象
    const obj = reactive({
      name: 'ls',
      age: 10
    })
    console.log(obj)
    // 2. 解构或者展开响应式数据对象得到的数据就是普通数据了
    // const {name,age} = obj
    // console.log(name,age)
    // const obj2 = {...obj}
    // console.log(obj2)
    
    const obj3 = toRefs(obj)
    console.log(obj3) // 可以在控制台上看对象里的数据是响应式数据

    const updateName = () => {
      // 和toRef函数一样会把数据包装成对象,修改值时需要修改对象的value属性
      // obj3.name.value = 'zs'
      // 如果对象也是响应式的则可以直接这样修改值
      obj.name = 'zs'
    }

    return {...obj3, updateName}
  }
}

总结:

  • 使用场景:剥离响应式对象(解构|展开),想使用响应式对象中的多个或者所有属性做为响应式数据。
  • 会把数据包装成对象,修改值时是修改这个对象的value属性。所以通常和reactive函数配合使用

05-组合API-ref函数

  • ref函数常用于简单数据类型定义为响应式数据(其实也可以定义复杂数据类型)
    • 再修改值,获取值的时候,需要.value
    • 在模板中使用ref申明的响应式数据,可以省略.value
// 演示代码
import { ref } from 'vue'
export default {
  name: 'App',
  setup () {
    // 1. name数据
    const name = ref('ls')
    console.log(name)
    // 改变name的方法
    const updateName = () => {
      // 需要改变的是他的value值
      name.value = 'zs'
    }
    // ref常用定义简单数据类型的响应式数据
    // 其实也可以定义复杂数据类型的响应式数据
    // 对于数据未之的情况下 ref 是最适用的,如请求获取的数据
    // const data = ref(null)
    // setTimeout(()=>{
    //   data.value = res.data
    // },1000)
    return {name, updateName}
  }
}

总结:

  • ref一般用于绑定简单数据类型的响应式数据,其也可以定义复杂数据类型
  • 在不明确数据是简单数据类型还是复杂数据类型时可以使用ref

平时建议什么时候使用ref什么时候使用reactive?

  • 当明确知道需要的是一个复杂类型响应式数据时,使用reactive和toRefs,其他情况使用ref