vue3快速上手,基础知识(二)

91 阅读3分钟

前言

  • 响应式工具解读
  • 响应式API:进阶解读
  • vue3中自定义指令与vue2有哪些不同
  • 特殊属性

1、响应式工具

1-1. toRef()

描述

基于一个响应式对象,解构出一个可读写的属性,并且与源属性所关联sou

语法
 // sourceObject 源对象<响应式对象> 
 // sourceAttribute 源属性<string>
 const ref = toRef(sourceObject, sourceAttribute)
例子
 const state = reactive({ foo: 1, bar: 3 })
 const fooRef = toRef(state, 'foo')
 ​
 // 修改 toRef 生成的属性会更新源属性
 fooRef.value ++
 console.log(state.foo) // 2
 // 更改源属性也会更新 ref
 state.foo ++
 console.log(fooRef.value) // 3

1-2. toRefs()

描述

toRefs复制关联整个响应式对象将其转成普通对象,使其可以解构/展开并且不会失去响应式

语法
 const { foo, bar } = toRefs(souceObject)
例子
 function useFeatureX() {
     const state = reactive({
         foo: 1,
         bar: 2
     })
     // ...基于状态的操作逻辑
     // 在返回时都转为 ref
     return toRefs(state)
 }
 // 可以结构不会失去响应式
 const { foo, bar } = useFeatureX()

2、响应式API:进阶

2-1. shallowRef()

描述

ref()的浅层转换,只会将第一层转为响应式

例子
 const peopleObj = shallowRef({ name: '张三' })
 ​
 watchEffect(() => {
    console.log("name", peopleObj.value.name)
 })
 ​
 // name 张三
 peopleObj.value.name = '我被修改了' // 不会触发更新,是一个副作用
 // name 我被修改了
 peopleObj.value = { name: '我被修改了' } // 会触发更新

2-2. triggerRef()

描述

强制更新浅层ref的副作用,通常在对浅引用的内部值进行深度变更后使用。

例子
 const shallow = shallowRef({
   greet: 'Hello, world'
 })
 ​
 // 触发该副作用第一次应该会打印 "Hello, world"
 watchEffect(() => {
   console.log(shallow.value.greet)
 })
 ​
 // 这次变更不应触发副作用,因为这个 ref 是浅层的
 shallow.value.greet = 'Hello, universe'
 ​
 // triggerRef会强制执行shallowRef修改所产生的副作用
 // 打印 "Hello, universe",
 triggerRef(shallow)

2-3. shallowReactive()

描述

reactive() 不同,这里没有深层级的转换:一个浅层响应式对象里只有根级别的属性是响应式的。属性的值会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。

例子
 const state = shallowReactive({
   foo: 1,
   nested: {
     bar: 2
   }
 })
 ​
 // 更改状态自身的属性是响应式的
 state.foo++
 ​
 // ...但下层嵌套对象不会被转为响应式
 isReactive(state.nested) // false
 ​
 // 不是响应式的
 state.nested.bar++

2-4. shallowReadonly()

描述

readonly() 不同,这里没有深层级的转换:只有根层级的属性变为了只读。属性的值都会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。

例子
 const state = shallowReadonly({
   foo: 1,
   nested: {
     bar: 2
   }
 })
 ​
 // 更改状态自身的属性会失败
 state.foo++
 ​
 // ...但可以更改下层嵌套对象
 isReadonly(state.nested) // false
 ​
 // 这是可以通过的
 state.nested.bar++

2-5. effectScope()

描述

创建一个 effect 作用域,可以捕获到作用域内所有的响应式副作用

例子
 const scope = effectScope()
 ​
 scope.run(() => {
     const doubled = computed(() => counter.value * 2)
 ​
     watch(doubled, () => console.log(doubled.value))
 ​
     watchEffect(() => console.log('Count: ', doubled.value))
 ​
     onScopeDispose(() => {
         console.log('scope 被停止了!')
     })
 })
 ​
 // 处理掉当前作用域内的所有 effect
 scope.stop()
 ​
 getCurrentScope() // 返回 effectScope()

2-6. getCurrentScope()

描述

返回存在的 effect作用域undefined

例子

点着里前往

2-7. onScopeDispose()

描述

在当前活跃的 effect 作用域上注册一个处理回调函数。当相关的 effect 作用域被注销是会调用这个回调函数

例子

点着里前往

3、自定义指令

3-1. v-if & v-for

不同于 vue2,在 vue3v-if 优先级比 v-for 优先级高,不过还是不推荐一起使用

3-2. v-memo 3.2+

描述

缓存子组件,如果每一个值与最后一次渲染相同,整个子树的更新将被跳过。

 <div v-memo="[valueA, valueB]">
   ...
 </div>

当组件重新渲染,如果 valueAvalueB 都保持不变,这个 <div> 及其子项的所有更新都将被跳过。

v-memo 传入空依赖数组 (v-memo="[]") 将与 v-once 效果相同。

4、组件

4-1. 内置元素 <components>

可以搭配 is 实现动态组件

 <script setup>
 import Foo from './Foo.vue'
 import Bar from './Bar.vue'
 </script>
 ​
 <template>
   <--! is 接受一个 string | Component 类型,会动态渲染对应组件-->
   <component :is="Math.random() > 0.5 ? Foo : Bar" />
 </template>

5、特殊属性

5-1. key

vue3 的 key 与 vue2 的区别

  • vue3key 可以被绑定在 template容器上,这在 vue2 中是不被允许的

     <template v-for="todo in todos" :key="todo.name">
       <li>{{ todo.name }}</li>
     </template>
    
  • vue3 会自动为条件分支生成唯一的 key,在 vue2 中需要手动添加

     <--! Vue2.x -->
         <div v-if="loginType === 'username'" key="a">A</div>
         <div v-else key="b">B</div>
         
     <--! Vue3 -->
         <div v-if="loginType === 'username'">A</div>
         <div v-else>B</div>
    

5-2. is

用于绑定动态组件

  • is 被绑定在普通 html 标签时,会当作普通属性存在
  • components 使用时,保留 vue2 的功能