Vue 官方团队于 2020 年 9 月 18 日晚 11 点半左右发布了 Vue3.0 版本 🎉。代号为 One Piece。
Vue 3.0 终于发布了,具体更新内容详见 v3.0.0。官网地址 Vue,但内容还都是英文的,毕竟刚发布嘛,中文内容还没那么快。
索性不如自己阅读仓库文档,看看 Vue3 都给我们带来了哪些具体变化。
响应式基础
声明响应式状态
要从 JavaScript 对象创建一个响应式状态,可以使用 reactive 方法:
import { reactive } from 'vue'
// 响应式状态
const state = reactive({
count: 0
})
reactive 相当于 Vue 2.x 中的 Vue.observable() API ,为避免与 RxJS 中的 observables 混淆因此对其重命名。这里返回的状态是一个响应式对象。该响应式转换是“深度转换”——它会影响传入对象的所有属性值。
Vue 中响应式状态的基本场景是我们可以在渲染期间使用它。借助独立的依赖跟踪体系,当响应式状态改变时视图会自动更新。
这就是 Vue 响应式系统的本质。当从组件中的 data() 返回一个对象时,它在内部通过 reactive() 变成响应式对象。模板会被编译成能够使用这些响应式 property 的渲染函数。
在响应式基础 API 章节你可以学习更多关于 reactive 的内容。
创建独立的响应值作为 refs
想象一下,我们有一个独立的原始值 (例如,一个字符串),我们想让它变成响应式的。当然,我们可以把这个字符串作为唯一的属性创建对象,并将其传递给 reactive。不过 Vue 为我们提供了一个可以实现相同效果的方法 ——ref:
import { ref } from 'vue'
const count = ref(0)
ref 将返回一个响应式可变的对象,作为它所持有的内部值的响应式引用--这就是名称的由来。此对象只包含一个名为 value 的属性 :
import { ref } from 'vue'
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
Ref 展开
当一个 ref 在渲染上下文(从 setup () 中返回的对象)上作为一个属性返回,并在模板中被访问时,它会自动展开其内部值。故在模板中就不必追加 .value了:
<template>
<div>
<span>{{ count }}</span>
<button @click="count ++">Increment count</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return {
count
}
}
}
</script>
访问响应式对象
当 ref 作为响应式对象的属性被访问或变更时,它会自动展开内部值,表现行为类似于普通的属性
const count = ref(0)
const state = reactive({
count
})
console.log(state.count) // 0
state.count = 1
console.log(count.value) // 1
如果将新的 ref 赋值给一个关联了 ref 的属性值,将会替换旧的 ref:
const otherCount = ref(2)
state.count = otherCount
console.log(state.count) // 2
console.log(count.value) // 1
Ref 展开仅发生在被响应式 Object 内嵌的时候。当从 Array 或原生集合类型如 Map访问 ref 时,不会进行展开:
const books = reactive([ref('Vue 3 Guide')])
// 需要使用 .value
console.log(books[0].value)
const map = reactive(new Map([['count', ref(0)]]))
// 需要使用 .value
console.log(map.get('count').value)
解构响应式状态
当我们要使用大型响应式对象的一些属性时,可能会考虑使用 ES6 解构来获取我们想要的属性值:
import { reactive } from 'vue'
const book = reactive({
author: 'Vue Team',
year: '2020',
title: 'Vue 3 Guide',
description: 'You are reading this book right now ;)',
price: 'free'
})
let { author, title } = book
遗憾的是,使用解构的两个属性响应式都会丢失。对于这种情况,我们需要将我们的响应式对象转换为一组 ref。这些 ref 将保留与源对象的响应式关联:
import { reactive, toRefs } from 'vue'
const book = reactive({
author: 'Vue Team',
year: '2020',
title: 'Vue 3 Guide',
description: 'You are reading this book right now ;)',
price: 'free'
})
let { author, title } = toRefs(book)
title.value = 'Vue 3 Detailed Guide' // 我们需要使用 .value 作为标题,现在是 ref
console.log(book.title) // 'Vue 3 Detailed Guide'
你可以在 Refs API 部分中了解更多有关 `refs' 的信息
使用 readonly 防止篡改响应式对象
有时我们想跟踪响应式对象 (ref 或 reactive) 的变化,但我们也希望在应用程序的特定位置上防止对它的修改。例如,当我们有一个被 provide 的响应式对象时,我们不想让它在注入的时候被改变。为此,我们可以给原始对象创建一个只读的 Proxy 对象:
import { reactive, readonly } from 'vue'
const original = reactive({ count: 0 })
const copy = readonly(original)
// 变更 original 会触发依赖于 copy 的监听器(译者注:即 copy 也能得到变更后的值)
original.count++
// 变更 copy 会失败并弹出警告信息
copy.count++ // 警告: "Set operation on key 'count' failed: target is readonly."