vue3快速学习(vue2转vue3学习)

首先要知道的一些方法,基础api。避免看不懂vue3。 1. reactive 返回对象的响应式…

首先要知道的一些方法,基础api。避免看不懂vue3。

1. reactive

返回对象的响应式副本,实际上reactive 将解包所有深层的 refs,同时维持 ref 的响应性。

个人理解:相当于把reactive里面的内容a,push到一个对象中,而且还互相相应。我称这个对象为依赖于a的副本。内容为空,后续通过 obj.count = count 这样的写法,也能将其绑定响应。

const obj = reactive({ count: 0 })
响应式转换是“深层”的——它影响所有嵌套 property。在基于 ES2015 Proxy 的实现中,返回的 proxy 是不等于原始对象的。建议只使用响应式 proxy,避免依赖原始对象。

类型声明:

function reactive<T extends object>(target: T): UnwrapNestedRefs<T>

例子:

当将 ref 分配给 reactive property 时,ref 将被自动解包。

2. readonly

接受一个对象 (响应式或纯对象) 或 ref 并返回原始对象的只读代理。只读代理是深层的:任何被访问的嵌套 property 也是只读的。

和reactive一样也是push给一个对象,但是他这个对象是不能改变它的值的。它本身是可以改变的,而且如果给这个对象设置watch了的话,还会触发它的监听器。

3. isProxy

检查对象是否是由 reactive 或 readonly 创建的 proxy。

4. isReactive

检查对象是否是由 reactive 创建的响应式代理

注意:从普通对象创建的只读 proxy,用isReactive检查会是false.如: const plain = readonly({ name: 'Mary' }) console.log(isReactive(plain)) // -> false

例子:

如果该代理是 readonly 创建的,但包裹了由 reactive 创建的另一个代理,它也会返回 true。

5. isReadonly

检查对象是否是由 readonly 创建的只读代理。

6. toRaw

返回 reactive 或 readonly 代理的原始对象。这是一个“逃生舱”,可用于临时读取数据而无需承担代理访问/跟踪的开销,也可用于写入数据而避免触发更改。
不建议保留对原始对象的持久引用。请谨慎使用。例子:

7. markRaw

标记一个对象,使其永远不会转换为 proxy。返回对象本身。
也就是它设置的值,对象,数组等。是不是响应的。

markRaw 和下方的 shallowXXX API 使你可以有选择地退出默认的深度响应式/只读转换模式,并将原始的,未被代理的对象嵌入状态图中。它们可以根据情况灵活运用:

有些值不应该是响应式的,例如复杂的第三方类实例或 Vue 组件对象。
当渲染具有不可变数据源的大列表时,跳过 proxy 转换可以提高性能。

这些例子是进阶的运用,因为原始选择退出仅在根级别,因此,如果将嵌套在内的、未标记的原始对象添加进响应式对象,然后再次访问该响应式对象,就会得到原始对象被代理后的版本。这可能会导致同一性风险——即执行一个依赖于对象本身的操作,但同时使用同一对象的原始版本和被代理后的版本:

同一性风险通常很少见。然而,为了正确地使用这些 API,同时安全地避免同一性风险,就需要对响应性系统的工作原理有一个充分的理解。

8. shallowReactive

创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (暴露原始值)。
个人理解:类似浅拷贝。

与 reactive 不同,任何使用 ref 的 property 都不会被代理自动解包。

9. shallowReadonly
创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换 (暴露原始值)。

与 readonly 不同,任何使用 ref 的 property 都不会被代理自动解包。

下面是主要使用的api

Refs

接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。
示例:

注意:如果将对象分配为 ref 值,则它将被 reactive 函数处理为深层的响应式对象。可以连着上面的reactive一起看着理解。

类型声明:

有时我们可能需要为 ref 的内部值指定复杂类型。可以在调用 ref 时传递一个泛型参数以覆盖默认推断,从而简洁地做到这一点:

如果泛型的类型未知,则建议将 ref 转换为 Ref<T>:

Ref 解包

当 ref 作为渲染上下文 (从 setup() 中返回的对象) 上的 property 返回并可以在模板中被访问时,它将自动浅层次解包内部值。只有访问嵌套的 ref 时需要在模板中添加 .value:

如果你不想要访问实际的对象实例,可将其用 reactive 包裹:

访问响应式对象
当 ref 作为响应式对象的 property 被访问或更改时,为使其行为类似于普通 property,它会自动解包内部值:

如果将新的 ref 赋值给现有 ref 的 property,将会替换旧的 ref:

Ref 解包仅发生在被响应式 Object 嵌套的时候。当从 Array 或原生集合类型如 Map访问 ref 时,不会进行解包:

响应式状态解构
当我们想使用大型响应式对象的一些 property 时,可能很想使用 ES6 解构来获取我们想要的 property:

遗憾的是,使用解构的两个 property 的响应性都会丢失。对于这种情况,我们需要将我们的响应式对象转换为一组 ref。这些 ref 将保留与源对象的响应式关联:

isRef

检查值是否为一个 ref 对象。

unref

如果参数是一个 ref,则返回内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val 的语法糖函数。

这个一般用在ts文件里面。

toRef

可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。

一般用来对某个对象里面的一个属性进行一个响应链接。

当你要将 prop 的 ref 传递给复合函数function时,toRef 很有用:

即使源 property 不存在,toRef 也会返回一个可用的 ref。这使得它在使用可选 prop 时特别有用,可选 prop 并不会被 toRefs 处理。

toRefs

将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref

结合 ref对象 仅有一个 .value property,指向该内部值。根据原型链就能理解下面 ref 和原始 property 已经“链接”起来了 这句话了.

更简单理解toRef只能传一个,toRefs能传多个。

当从组合式函数返回响应式对象时,toRefs 非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行解构/展开:

customRef

创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收 track 和 trigger 函数作为参数,并且应该返回一个带有 get 和 set 的对象。

使用自定义 ref 通过 v-model 实现 debounce 的示例:

类型声明:

shallowRef

创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的。

triggerRef

手动执行与 shallowRef 关联的任何作用 (effect)。

回归正题

vue2在data里定义的a,在vue3中这么定义,ref里面定义其初始值。如:a:9, 在vue3写法就是const a = ref(9)watch的写法变成

独立的 computed 属性

下面是最新总的写法

使用 setup 函数时,它将接受两个参数:

props
context

setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新。

例子:

如果需要解构 prop,可以通过使用 setup 函数中的 toRefs 来完成此操作

const { title } = toRefs(props)

使用toRefs解绑后会安全消除 prop 的响应性。如:

const { title } = toRefs(props)

console.log(title.value)

context 是一个普通的 JavaScript 对象,它暴露三个组件的 property:

它不是响应式的,这意味着你可以安全地对 context 使用 ES6 解构。

attrs slots 是有状态的对象,它们总是会随组件本身的更新而更新。这意味着你应该避免对它们进行解构,并始终以 attrs.x 或 slots.x 的方式引用 property。
请注意,与 props 不同,attrs 和 slots 是非响应式的。
如果你打算根据 attrs 或 slots 更改应用副作用,那么应该在 onUpdated 生命周期钩子中执行此操作

执行 setup 时,组件实例尚未被创建。因此,你只能访问以下 property:

props
attrs
slots
emit

换句话说,你将无法访问以下组件选项:

data
computed
methods

注意,从 setup 返回的 refs 在模板中访问时是被自动解开的,因此不应在模板中使用 .value

setup 还可以返回一个渲染函数,该函数可以直接使用在同一作用域中声明的响应式状态:

注册组件

#3.x 语法
在 3.x 中,由于 VNode 是上下文无关的,不能再用字符串 ID 隐式查找已注册组件。取而代之的是,需要使用一个导入的 resolveComponent 方法:// 3.x

Vue 3 现在提供一个 emits 选项,和现有的 props 选项类似。这个选项可以用来定义一个组件可以向其父组件触发的事件。

在 Vue 2 中,你可以定义一个组件可接收的 prop,但是你无法声明它可以触发哪些事件:

vue3.的行为
和 prop 类似,现在可以通过 emits 选项来定义组件可触发的事件:

2.x 版本中在一个元素上同时使用 v-if 和 v-for 时,v-for 会优先作用。

#3.x 语法

v-if 会拥有比 v-for 更高的优先级。

在 2.x 中,如果一个元素同时定义了 v-bind="object" 和一个相同的独立 attribute,那么这个独立 attribute 总是会覆盖 object 中的绑定。

在 3.x 中,如果一个元素同时定义了 v-bind="object" 和一个相同的独立 attribute,那么绑定的声明顺序将决定它们如何被合并。

换句话说,相对于假设开发者总是希望独立 attribute 覆盖 object 中定义的内容,现在开发者能够对自己所希望的合并行为做更好的控制。

script setup是vue3中新引入的语法糖,目的是简化使用Composition API时冗长的模板代码。
如:

当我们需要引入一个components时,不仅需要在文件头部显式import进行导入,而且需要components字段加入声明。

不仅如此,在setup中声明的变量如果需要被模板使用,那么需要在setup的尾部显式return返回,如果你的组件模板使用的变量不多,还可以勉强接受。但是当你的变量和方法逐渐增加时,每次都要在setup后进行return返回,这无疑是一件枯燥的事情,在重构代码时,你也会面临巨大挑战。

为了解决这个问题,vue3添加了script setup语法糖提案。

像上面这段代码,使用script setup语法糖重构后,将变成:

基本用法
若要使用script setup语法,只需在原vue文件中的script标签加入setup属性。

<script setup lang="ts">

<script>

使用后意味着,script标签内的内容相当于原本组件声明中setup()的函数体,不过也有一定的区别。

使用setup中的参数
<script setup="props, context" lang="ts">

<script>

像这样,只要在setup处声明即可自动导入,同时也支持解构语法:

<script setup="props, { emit }" lang="ts">

<script>

还有一种写法 每次return的时候,结合三点运算符实现

setup() {
const state = reactive({
listParam: {
searchKey: "",
mainFollower: ""
}
})
watch([() => state.listParam.customerName, () => state.listParam.mainFollower],
([newCustomerName, newMainFoller],[oldCustomerName,oldMainFoller]) => {
state.listParam.customerName = newCustomerName.trim()
state.listParam.mainFollower = newMainFoller.trim()
},{
immediate: true
})
return {
toRefs(state) // 三点运算符实现多个返回
}
}

await语法支持
在script setup内可以直接使用await语法:

computed

接受一个 getter 函数,并根据 getter 的返回值返回一个不可变响应式 ref 对象。

或者,接受一个具有 get set 函数的对象,用来创建可写的 ref 对象。

类型声明:

用ts的泛类,你可以自己定义computed的类型

立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

使用watchEffect监听数据,可以单个或多个,不需要传入监听的数据源,而是直接执行里面的方法,获取到更新后的值

js文件

类型声明:

watch可以获取改变前后的值,watchEffect不可以

watch API 与选项式 API this.$watch (以及相应的 watch 选项) 完全等效。watch 需要侦听特定的数据源,并在单独的回调函数中执行副作用。默认情况下,它也是惰性的——即回调仅在侦听源发生变化时被调用。

与 watchEffect 相比,watch 允许我们:

惰性地执行副作用;
更具体地说明应触发侦听器重新运行的状态;
访问被侦听状态的先前值和当前值。

watch侦听单一源
侦听器数据源可以是一个具有返回值的 getter 函数,也可以直接是一个 ref:

watch侦听多个源
侦听器还可以使用数组以同时侦听多个源:

[fooRef, barRef]这是你要监听的2个变量。

[foo, bar], [prevFoo, prevBar],这是2个改变前后监听到的值。

例子:

监听单一数据:

监听多数据:

与 watchEffect 相同的行为
watch 与 watchEffect 在手动停止侦听、清除副作用 (将 onInvalidate 作为第三个参数传递给回调)、刷新时机和调试方面有相同的行为。

类型声明:

本文来自网络,不代表软粉网立场,转载请注明出处:https://www.rfff.net/p/6046.html

作者: HUI

发表评论

您的电子邮箱地址不会被公开。

返回顶部