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)方式相比有以下优势:
- 丢掉麻烦的备份数据
- 省去for in 循环
- 可以监听对象和数组变化
- 代码更简化
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