Vue3常用API总结

news2024/11/24 15:30:31

因为这个月的月初给自己定了个小目标,学完Vue3的基本使用,并使用Vue3亲手做一个小项目(稍微透露一下,我制作的是一个小工具,现在已经完成了90%了,这个月月底之前会通过博客的形式向大家展示,并且提供设计思路,大家敬请期待……),本文会频繁地对比Vue2来介绍Vue3,也将对各个API结合代码实例讲解,这既是对自己知识的总结,也希望能帮助到大家

一、前言

大家都知道,现在Vue3的各个版本已经陆续发布了,并且有很多的团队已经着手各个库的开发与Vue2向Vue3的升级,我们当然也不能落后,所以赶紧将你手中的Vue2升级到Vue3,跟着本文一起学习新的API吧

升级的方法可以点击本文开头的文章,在上一篇文章中有个保姆级别的教程告诉大家如何升级

二、正文

Vue2每次都把整个Vue导入,例如Vue2的 main.js 文件中的代码

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App)
}).$mount('#app')
复制代码

但很明显我们的项目中不可能用到Vue所有的API,因此很多模块其实是没有用的

那么在Vue3中,对外暴露了很多的API供开发者使用,我们可以根据自己的需求,将所需要的API从Vue中导入。例如 main.js 中的代码

import { createApp } from 'vue';
import App from './App.vue'

createApp(App).mount('#app')
复制代码

利用了 importexport 的导入导出语法,实现了按需打包模块的功能,项目打包后的文件体积明显小了很多

这也是我们本文需要对 Vue3 API 进行详细了解的原因

(1)setup

setup 函数也是 Compsition API 的入口函数,我们的变量、方法都是在该函数里定义的,来看一下使用方法

<template>
  <div id="app">
      <p>{{ number }}</p>
      <button @click="add">增加</button>
  </div>
</template>

<script>
// 1\. 从 vue 中引入 ref 函数
import {ref} from 'vue'
export default {
  name: 'App',
  setup() {
      // 2\. 用 ref 函数包装一个响应式变量 number
      let number = ref(0)

      // 3\. 设定一个方法
      function add() {
          // number是被ref函数包装过了的,其值保存在.value中
          number.value ++
      }

      // 4\. 将 number 和 add 返回出去,供template中使用
      return {number, add}
  }

}
</script>
复制代码

上述代码中用到了 ref 函数,下面会详细讲解,在这里你只需要理解它的作用是包装一个响应式的数据即可,并且你可以将 ref 函数包装过的变量看作是Vue2 data 中的变量

这样就简单实现了一个点击按钮数字加1的功能


在Vue2中,我们访问 dataprops 中的变量,都是通过类似 this.number 这样的形式去获取的,但要特别注意的是,在setup中,this 指向的是 undefined,也就是说不能再向Vue2一样通过 this 去获取变量了

那么到底该如何获取到 props 中的数据呢?

其实 setup 函数还有两个参数,分别是 propscontext,前者存储着定义当前组件允许外界传递过来的参数名称以及对应的值;后者是一个上下文对象,能从中访问到 attremitslots

其中 emit 就是我们熟悉的Vue2中与父组件通信的方法,可以直接拿来调用

(2)生命周期

Vue2中有 beforeCreatecreatedbeforeMountmountedbeforeUpdate 等生命周期函数

而在Vue3中,这些生命周期部分有所变化,并且调用的方式也有所改变,下面放上一张变化图来简单了解一下

Vue2Vue3
beforeCreatesetup
createdsetup
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestoryonBeforeUnmount
destoryedunMounted

Vue3的这些生命周期调用也很简单,同样是先从 vue 中导入,再进行直接调用

<template>
  <div id="app"></div>
</template>

<script>
// 1\. 从 vue 中引入 多个生命周期函数
import {onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, unMounted} from 'vue'
export default {
  name: 'App',
  setup() {
      onBeforeMount(() => {
          // 在挂载前执行某些代码
      })

      onMounted(() => {
          // 在挂载后执行某些代码
      })

      onBeforeUpdate(() => {
          // 在更新前前执行某些代码
      })

      onUpdated(() => {
          // 在更新后执行某些代码
      })

      onBeforeUnmount(() => {
          // 在组件销毁前执行某些代码
      })

      unMounted(() => {
          // 在组件销毁后执行某些代码
      })

      return {}
  }

}
</script>
复制代码

要特别说明一下的就是,setup 函数代替了 beforeCreatecreated 两个生命周期函数,因此我们可以认为它的执行时间在beforeCreatecreated 之间

(3)reactive

reactive 方法是用来创建一个响应式的数据对象,该API也很好地解决了Vue2通过 defineProperty 实现数据响应式的缺陷

用法很简单,只需将数据作为参数传入即可,代码如下

<template>
  <div id="app">
    <!-- 4\. 访问响应式数据对象中的 count  -->
    {{ state.count }}
  </div>
</template>

<script>
// 1\. 从 vue 中导入 reactive 
import {reactive} from 'vue'
export default {
  name: 'App',
  setup() {
      // 2\. 创建响应式的数据对象
      const state = reactive({count: 3})

      // 3\. 将响应式数据对象state return 出去,供template使用
      return {state}
  }
}
</script>
复制代码

(4)ref

在介绍 setup 函数时,我们使用了 ref 函数包装了一个响应式的数据对象,这里表面上看上去跟 reactive 好像功能一模一样啊,确实差不多,因为 ref 就是通过 reactive 包装了一个对象 ,然后是将值传给该对象中的 value 属性,这也就解释了为什么每次访问时我们都需要加上 .value

我们可以简单地把 ref(obj) 理解为这个样子 reactive({value: obj})

这里我们写一段代码来具体看一下

<script>
import {ref, reactive} from 'vue'
export default {
  name: 'App',
  setup() {
      const obj = {count: 3}
      const state1 = ref(obj)
      const state2 = reactive(obj)

      console.log(state1)
      console.log(state2)
  }

}
</script>
复制代码

来看一下打印结果

[图片上传中...(image-ef9e20-1605864697238-15)]

注意: 这里指的 .value 是在 setup 函数中访问 ref 包装后的对象时才需要加的,在 template 模板中访问时是不需要的,因为在编译时,会自动识别其是否为 ref 包装过的

那么我们到底该如何选择 refreactive 呢?

建议:

  1. 基本类型值(StringNmuberBoolean 等)或单值对象(类似像 {count: 3} 这样只有一个属性值的对象)使用 ref
  2. 引用类型值(ObjectArray)使用 reactive

(5)toRef

toRef 是将某个对象中的某个值转化为响应式数据,其接收两个参数,第一个参数为 obj 对象;第二个参数为对象中的属性名

代码如下:

<script>
// 1\. 导入 toRef
import {toRef} from 'vue'
export default {
    setup() {
        const obj = {count: 3}
        // 2\. 将 obj 对象中属性count的值转化为响应式数据
        const state = toRef(obj, 'count')

        // 3\. 将toRef包装过的数据对象返回供template使用
        return {state}
    }
}
</script>
复制代码

但其实表面上看上去 toRef 这个API好像非常的没用,因为这个功能也可以用 ref 实现,代码如下

<script>
// 1\. 导入 ref
import {ref} from 'vue'
export default {
    setup() {
        const obj = {count: 3}
        // 2\. 将 obj 对象中属性count的值转化为响应式数据
        const state = ref(obj.count)

        // 3\. 将ref包装过的数据对象返回供template使用
        return {state}
    }
}
</script>
复制代码

乍一看好像还真是,其实这两者是有区别的,我们可以通过一个案例来比较一下,代码如下

<template>
    <p>{{ state1 }}</p>
    <button @click="add1">增加</button>

    <p>{{ state2 }}</p>
    <button @click="add2">增加</button>
</template>

<script>
import {ref, toRef} from 'vue'
export default {
    setup() {
        const obj = {count: 3}
        const state1 = ref(obj.count)
        const state2 = toRef(obj, 'count')

        function add1() {
            state1.value ++
            console.log('原始值:', obj);
            console.log('响应式数据对象:', state1);
        }

        function add2() {
            state2.value ++
            console.log('原始值:', obj);
            console.log('响应式数据对象:', state2);
        }

        return {state1, state2, add1, add2}
    }
}
</script>
复制代码

我们分别用 reftoRefobj 中的 count 转化为响应式,并声明了两个方法分别使 count 值增加,每次增加后打印一下原始值 obj 和被包装过的响应式数据对象,同时还要看看视图的变化

ref:

[图片上传中...(image-c23a78-1605864697237-14)]

可以看到,在对响应式数据的值进行 +1 操作后,视图改变了,原始值未改变,响应式数据对象的值也改变了,这说明 ref 是对原数据的一个拷贝,不会影响到原始值,同时响应式数据对象值改变后会同步更新视图

toRef:

[图片上传中...(image-4a5589-1605864697237-13)]

可以看到,在对响应式数据的值进行 +1 操作后,视图未发生改变,原始值改变了,响应式数据对象的值也改变了,这说明 toRef 是对原数据的一个引用,会影响到原始值,但是响应式数据对象值改变后会不会更新视图

总结:

  1. ref 是对传入数据的拷贝;toRef 是对传入数据的引用
  2. ref 的值改变会更新视图;toRef 的值改变不会更新视图

(6)toRefs

了解完 toRef 后,就很好理解 toRefs 了,其作用就是将传入的对象里所有的属性的值都转化为响应式数据对象,该函数支持一个参数,即 obj 对象

我们来看一下它的基本使用

<script>
// 1\. 导入 toRefs
import {toRefs} from 'vue'
export default {
    setup() {
        const obj = {
            name: '前端印象',
            age: 22,
            gender: 0
        }
        // 2\. 将 obj 对象中属性count的值转化为响应式数据
        const state = toRefs(obj)

        // 3\. 打印查看一下
        console.log(state)
    }
}
</script>
复制代码

打印结果如下:

[图片上传中...(image-94f4ce-1605864697237-12)]

返回的是一个对象,对象里包含了每一个包装过后的响应式数据对象

(7)shallowReactive

听这个API的名称就知道,这是一个渐层的 reactive,难道意思就是原本的 reactive 是深层的呗,没错,这是一个用于性能优化的API

其实将 obj 作为参数传递给 reactive 生成响应式数据对象时,若 obj 的层级不止一层,那么会将每一层都用 Proxy 包装一次,我们来验证一下

<script>
import {reactive} from 'vue'
export default {
    setup() {
        const obj = {
            a: 1,
            first: {
                b: 2,
                second: {
                    c: 3
                }
            }
        }

        const state = reactive(obj)

        console.log(state)
        console.log(state.first)
        console.log(state.first.second)
    }
}
</script>
复制代码

来看一下打印结果:

[图片上传中...(image-7b04e7-1605864697237-11)]

设想一下如果一个对象层级比较深,那么每一层都用 Proxy 包装后,对于性能是非常不友好的

接下来我们再来看看 shallowReactive

<script>
import {shallowReactive} from 'vue'
export default {
    setup() {
        const obj = {
            a: 1,
            first: {
                b: 2,
                second: {
                    c: 3
                }
            }
        }

        const state = shallowReactive(obj)

        console.log(state)
        console.log(state.first)
        console.log(state.first.second)
    }
}
</script>
复制代码

来看一下打印结果:

[图片上传中...(image-aded97-1605864697237-10)]

结果非常的明了了,只有第一层被 Proxy 处理了,也就是说只有修改第一层的值时,才会响应式更新,代码如下:

<template>
    <p>{{ state.a }}</p>
    <p>{{ state.first.b }}</p>
    <p>{{ state.first.second.c }}</p>
    <button @click="change1">改变1</button>
    <button @click="change2">改变2</button>
</template>
<script>
import {shallowReactive} from 'vue'
export default {
    setup() {
        const obj = {
            a: 1,
            first: {
                b: 2,
                second: {
                    c: 3
                }
            }
        }

        const state = shallowReactive(obj)

        function change1() {
            state.a = 7
        }

        function change2() {
            state.first.b = 8
            state.first.second.c = 9
            console.log(state);
        }

        return {state}
    }
}
</script>
复制代码

来看一下具体过程:

[图片上传中...(image-7e28c0-1605864697237-9)]

首先我们点击了第二个按钮,改变了第二层的 b 和第三层的 c,虽然值发生了改变,但是视图却没有进行更新;

当我们点击了第一个按钮,改变了第一层的 a 时,整个视图进行了更新;

由此可说明,shallowReactive 监听了第一层属性的值,一旦发生改变,则更新视图

(8)shallowRef

这是一个浅层的 ref,与 shallowReactive 一样是拿来做性能优化的

shallowReactive 是监听对象第一层的数据变化用于驱动视图更新,那么 shallowRef 则是监听 .value 的值的变化来更新视图的

我们来看一下具体代码

<template>
    <p>{{ state.a }}</p>
    <p>{{ state.first.b }}</p>
    <p>{{ state.first.second.c }}</p>
    <button @click="change1">改变1</button>
    <button @click="change2">改变2</button>
</template>

<script>
import {shallowRef} from 'vue'
export default {
    setup() {
        const obj = {
            a: 1,
            first: {
                b: 2,
                second: {
                    c: 3
                }
            }
        }

        const state = shallowRef(obj)
        console.log(state);

        function change1() {
            // 直接将state.value重新赋值
            state.value = {
                a: 7,
                first: {
                    b: 8,
                    second: {
                        c: 9
                    }
                }
            }
        }

        function change2() {
            state.value.first.b = 8
            state.value.first.second.c = 9
            console.log(state);
        }

        return {state, change1, change2}
    }
}
</script>
复制代码

首先看一下被 shallowRef 包装过后是怎样的结构

[图片上传中...(image-4d7c9f-1605864697237-8)]

然后再来看看改变其值会有什么变化

[图片上传中...(image-7c6b67-1605864697237-7)]

我们先点击了第二个按钮,发现数据确实被改变了,但是视图并没随之更新;

于是点击了第二个按钮,即将整个 .value 重新赋值了,视图就立马更新了

这么一看,未免也太过麻烦了,改个数据还要重新赋值,不要担心,此时我们可以用到另一个API,叫做 triggerRef ,调用它就可以立马更新视图,其接收一个参数 state ,即需要更新的 ref 对象

我们来使用一下

<template>
    <p>{{ state.a }}</p>
    <p>{{ state.first.b }}</p>
    <p>{{ state.first.second.c }}</p>
    <button @click="change">改变</button>
</template>

<script>
import {shallowRef, triggerRef} from 'vue'
export default {
    setup() {
        const obj = {
            a: 1,
            first: {
                b: 2,
                second: {
                    c: 3
                }
            }
        }

        const state = shallowRef(obj)
        console.log(state);

        function change() {
            state.value.first.b = 8
            state.value.first.second.c = 9
            // 修改值后立即驱动视图更新
            triggerRef(state)
            console.log(state);
        }

        return {state, change}
    }
}
</script>
复制代码

我们来看一下具体过程

[图片上传中...(image-c43e3d-1605864697237-6)]

可以看到,我们没有给 .value 重新赋值,只是在修改值后,调用了 triggerRef 就实现了视图的更新

(9)toRaw

toRaw 方法是用于获取 refreactive 对象的原始数据的

先来看一段代码

<template>
    <p>{{ state.name }}</p>
    <p>{{ state.age }}</p>
    <button @click="change">改变</button>
</template>

<script>
import {reactive} from 'vue'
export default {
    setup() {
        const obj = {
            name: '前端印象',
            age: 22
        }

        const state = reactive(obj) 

        function change() {
            state.age = 90
            console.log(obj); // 打印原始数据obj
            console.log(state);  // 打印 reactive对象
        }

        return {state, change}
    }
}
</script>
复制代码

来看看具体过程

[图片上传中...(image-33b92-1605864697236-5)]

我们改变了 reactive 对象中的数据,于是看到原始数据 obj 和被 reactive 包装过的对象的值都发生了变化,由此我们可以看出,这两者是一个引用关系

那么此时我们就想了,那如果直接改变原始数据 obj 的值,会怎么样呢?答案是: reactive 的值也会跟着改变,但是视图不会更新

由此可见,当我们想修改数据,但不想让视图更新时,可以选择直接修改原始数据上的值,因此需要先获取到原始数据,我们可以使用 Vue3 提供的 toRaw 方法

toRaw 接收一个参数,即 ref 对象或 reactive 对象

<script>
import {reactive, toRaw} from 'vue'
export default {
    setup() {
        const obj = {
            name: '前端印象',
            age: 22
        }

        const state = reactive(obj) 
        const raw = toRaw(state)

        console.log(obj === raw)   // true
    }
}
</script>
复制代码

上述代码就证明了 toRaw 方法从 reactive 对象中获取到的是原始数据,因此我们就可以很方便的通过修改原始数据的值而不更新视图来做一些性能优化了

注意: 补充一句,当 toRaw 方法接收的参数是 ref 对象时,需要加上 .value 才能获取到原始数据对象

(10)markRaw

markRaw 方法可以将原始数据标记为非响应式的,即使用 refreactive 将其包装,仍无法实现数据响应式,其接收一个参数,即原始数据,并返回被标记后的数据

我们来看一下代码

<template>
    <p>{{ state.name }}</p>
    <p>{{ state.age }}</p>
    <button @click="change">改变</button>
</template>

<script>
import {reactive, markRaw} from 'vue'
export default {
    setup() {
        const obj = {
            name: '前端印象',
            age: 22
        }
        // 通过markRaw标记原始数据obj, 使其数据更新不再被追踪
        const raw = markRaw(obj)   
        // 试图用reactive包装raw, 使其变成响应式数据
        const state = reactive(raw) 

        function change() {
            state.age = 90
            console.log(state);
        }

        return {state, change}
    }
}
</script>
复制代码

我们来看一下在被 markRaw 方法处理过后的数据是否还能被 reactive 包装成响应式数据

[图片上传中...(image-19b983-1605864697236-4)]

从图中可以看到,即使我们修改了值也不会更新视图了,即没有实现数据响应式

(11)provide && inject

与 Vue2中的 provideinject 作用相同,只不过在Vue3中需要手动从 vue 中导入

这里简单说明一下这两个方法的作用:

  • provide :向子组件以及子孙组件传递数据。接收两个参数,第一个参数是 key,即数据的名称;第二个参数为 value,即数据的值
  • inject :接收父组件或祖先组件传递过来的数据。接收一个参数 key,即父组件或祖先组件传递的数据名称

假设这有三个组件,分别是 A.vueB.vueC.vue,其中 B.vueA.vue 的子组件,C.vueB.vue 的子组件

// A.vue
<script>
import {provide} from 'vue'
export default {
    setup() {
        const obj= {
            name: '前端印象',
            age: 22
        }

        // 向子组件以及子孙组件传递名为info的数据
        provide('info', obj)
    }
}
</script>

// B.vue
<script>
import {inject} from 'vue'
export default {
    setup() {   
        // 接收A.vue传递过来的数据
        inject('info')  // {name: '前端印象', age: 22}
    }
}
</script>

// C.vue
<script>
import {inject} from 'vue'
export default {
    setup() {   
        // 接收A.vue传递过来的数据
        inject('info')  // {name: '前端印象', age: 22}
    }
}
</script>
复制代码

(12)watch && watchEffect

watchwatchEffect 都是用来监视某项数据变化从而执行指定的操作的,但用法上还是有所区别

watch:watch( source, cb, [options] )

参数说明:

  • source:可以是表达式或函数,用于指定监听的依赖对象
  • cb:依赖对象变化后执行的回调函数
  • options:可参数,可以配置的属性有 immediate(立即触发回调函数)、deep(深度监听)

当监听 ref 类型时:

<script>
import {ref, watch} from 'vue'
export default {
    setup() {   
        const state = ref(0)

        watch(state, (newValue, oldValue) => {
            console.log(`原值为${oldValue}`)
            console.log(`新值为${newValue}`)
            /* 1秒后打印结果:
                            原值为0
                            新值为1
            */
        })

        // 1秒后将state值+1
        setTimeout(() => {
            state.value ++
        }, 1000)
    }
}
</script>
复制代码

当监听 reactive 类型时:

<script>
import {reactive, watch} from 'vue'
export default {
    setup() {   
        const state = reactive({count: 0})

        watch(() => state.count, (newValue, oldValue) => {
            console.log(`原值为${oldValue}`)
            console.log(`新值为${newValue}`)
            /* 1秒后打印结果:
                            原值为0
                            新值为1
            */
        })

        // 1秒后将state.count的值+1
        setTimeout(() => {
            state.count ++
        }, 1000)
    }
}
</script>
复制代码

当同时监听多个值时:

<script>
import {reactive, watch} from 'vue'
export default {
    setup() {   
        const state = reactive({ count: 0, name: 'zs' })

        watch(
            [() => state.count, () => state.name], 
            ([newCount, newName], [oldvCount, oldvName]) => {
                console.log(oldvCount) // 旧的 count 值
                console.log(newCount) // 新的 count 值
                console.log(oldName) // 旧的 name 值
                console.log(newvName) // 新的 name 值
            }
        )

        setTimeout(() => {
          state.count ++
          state.name = 'ls'
        }, 1000)
    }
}
</script>
复制代码

因为 watch 方法的第一个参数我们已经指定了监听的对象,因此当组件初始化时,不会执行第二个参数中的回调函数,若我们想让其初始化时就先执行一遍,可以在第三个参数对象中设置 immediate: true

watch 方法默认是渐层的监听我们指定的数据,例如如果监听的数据有多层嵌套,深层的数据变化不会触发监听的回调,若我们想要其对深层数据也进行监听,可以在第三个参数对象中设置 deep: true

补充: watch方法会返回一个stop方法,若想要停止监听,便可直接执行该stop函数


接下来再来聊聊 watchEffect,它与 watch 的区别主要有以下几点:

  1. 不需要手动传入依赖
  2. 每次初始化时会执行一次回调函数来自动获取依赖
  3. 无法获取到原值,只能得到变化后的值

来看一下该方法如何使用:

<script>
import {reactive, watchEffect} from 'vue'
export default {
    setup() {   
        const state = reactive({ count: 0, name: 'zs' })

        watchEffect(() => {
            console.log(state.count)
            console.log(state.name)
            /*  初始化时打印:
                            0
                            zs

                1秒后打印:
                            1
                            ls
            */
        })

        setTimeout(() => {
          state.count ++
          state.name = 'ls'
        }, 1000)
    }
}
</script>
复制代码

从上述代码中可以看出,我们并没有像 watch 方法一样先给其传入一个依赖,而是直接指定了一个回调函数

当组件初始化时,将该回调函数执行一次,自动获取到需要检测的数据是 state.countstate.name

根据以上特征,我们可以自行选择使用哪一个监听器

(13)getCurrentInstance

我们都知道在Vue2的任何一个组件中想要获取当前组件的实例可以通过 this 来得到,而在Vue3中我们大量的代码都在 setup 函数中运行,并且在该函数中 this 指向的是 undefined,那么该如何获取到当前组件的实例呢?

这时可以用到另一个方法,即 getCurrentInstance

<template>
    <p>{{ num }}</p>
</template>
<script>
import {ref, getCurrentInstance} from 'vue'
export default {
    setup() {   
        const num = ref(3)
        const instance = getCurrentInstance()
        console.log(instance)

        return {num}
    }
}
</script>
复制代码

我们来看一下其打印结果

[图片上传中...(image-1b311e-1605864697235-3)]

因为 instance 包含的内容太多,所以没截完整,但是主要的内容都在图上了,我们重点来看一下 ctxproxy,因为这两个才是我们想要的 this 的内容

[图片上传中...(image-fa3e9c-1605864697235-2)]

[图片上传中...(image-e6fbec-1605864697235-1)]

可以看到 ctxproxy 的内容十分类似,只是后者相对于前者外部包装了一层 proxy,由此可说明 proxy 是响应式的

(14)useStore

在Vue2中使用 Vuex,我们都是通过 this.$store 来与获取到Vuex实例,但上一部分说了原本Vue2中的 this 的获取方式不一样了,并且我们在Vue3的 getCurrentInstance().ctx 中也没有发现 $store 这个属性,那么如何获取到Vuex实例呢?这就要通过 vuex 中的一个方法了,即 useStore

// store 文件夹下的 index.js
import Vuex from 'vuex'

const store = Vuex.createStore({
    state: {
        name: '前端印象',
        age: 22
    },
    mutations: {
        ……
    },
    ……
})

// example.vue
<script>
// 从 vuex 中导入 useStore 方法
import {useStore} from 'vuex'
export default {
    setup() {   
        // 获取 vuex 实例
        const store = useStore()

        console.log(store)
    }
}
</script>
复制代码

我们来看一下打印结果

image.png

然后接下来就可以像之前一样正常使用 vuex

(15)获取标签元素

最后再补充一个 ref 另外的作用,那就是可以获取到标签元素或组件

在Vue2中,我们获取元素都是通过给元素一个 ref 属性,然后通过 this.$refs.xx 来访问的,但这在Vue3中已经不再适用了

接下来看看Vue3中是如何获取元素的吧

<template>
  <div>
    <div ref="el">div元素</div>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue'
export default {
  setup() {
      // 创建一个DOM引用,名称必须与元素的ref属性名相同
      const el = ref(null)

      // 在挂载后才能通过 el 获取到目标元素
      onMounted(() => {
        el.value.innerHTML = '内容被修改'
      })

      // 把创建的引用 return 出去
      return {el}
  }
}
</script>
复制代码

获取元素的操作一共分为以下几个步骤:

  1. 先给目标元素的 ref 属性设置一个值,假设为 el
  2. 然后在 setup 函数中调用 ref 函数,值为 null,并赋值给变量 el,这里要注意,该变量名必须与我们给元素设置的 ref 属性名相同
  3. 把对元素的引用变量 el 返回(return)出去

补充:设置的元素引用变量只有在组件挂载后才能访问到,因此在挂载前对元素进行操作都是无效的

当然如果我们引用的是一个组件元素,那么获得的将是该组件的实例对象,这里就不做过多的演示了

三、结束语

本文也是笔者对Vue3的学习与理解。因为在之前学习的过程中也查阅了大量的文档资料,并不断地测试摸索,以及在Vue3项目中的心得体会,都让我对Vue3有了更深的认识,与此同时,我在各个社区或者是社交群里都发现很多小伙伴对Vue3的API都不太熟悉,甚至不知道有这些API,所以我就写下了这篇总结文章,将我所知道、所理解的都分享给大家

最后编辑于:2024-09-24 21:09:24


喜欢的朋友记得点赞、收藏、关注哦!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2188204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何提高游戏本地化的质量使用QE门户网站Logrus IT

高质量的游戏本地化是全球市场成功的关键。这尤其适用于AAA和AA级别的游戏&#xff0c;玩家在这些游戏中投入了大量资金&#xff0c;并期望从中获得完美的游戏体验。尽管公司做出了努力&#xff0c;但传统的质量控制方法并不总是能够防止所有错误和本地化不准确。让我们更详细地…

【深度学习】交叉熵

交叉熵&#xff08;Cross-Entropy&#xff09;是信息论中的一个重要概念&#xff0c;也是在机器学习和深度学习中用于分类任务的常见损失函数。它衡量的是两个概率分布之间的差异&#xff0c;特别是模型的预测概率分布与真实分布的差异。 交叉熵最初是从信息论引入的&#xff0…

检查jar冲突,查找存在相同class的jar

写在前面 本文看下如何查找jar冲突&#xff0c;即查找哪些jar包中存在相同的class。如果是存在相同jar的不同版本&#xff0c;基本一眼就能看出来&#xff0c;然后结合maven的依赖关系将其剔除掉即可&#xff0c;但是当你遇到了有人手动拷贝某些class到jar包中导致冲突的情况时…

【高频SQL基础50题】21-25

我又回来了。 目录 1.删除重复的电子邮箱 2.文章浏览 I 3.上升的温度 4.各赛事的用户注册率 5.超过 5 名学生的课 1.删除重复的电子邮箱 高级字符串检索题。 使用自连接的方式&#xff0c;面对上亿级别数据&#xff0c;效率也可以很高。 # Write your MySQL query st…

【算法】链表:92.反转链表(medium)+双指针

系列专栏 《分治》 《模拟》 《Linux》 目录 1、题目链接 2、题目介绍 3、解法 &#xff08;双指针&#xff09; 4、代码 是 206. 反转链表 - 力扣&#xff08;LeetCode&#xff09;的类型题&#xff0c;且难度提升&#xff0c;可以先完成206&#xff0c;然后参照206的…

MATLAB工具库:数据统计分析工具MvCAT、MhAST等

MATLAB工具库&#xff1a;数据统计分析工具MvCAT、MhAST等 工具1&#xff1a;Multivariate Copula Analysis Toolbox (MvCAT)MATLAB中运行 工具2&#xff1a;Multi-hazard Scenario Analysis Toolbox (MhAST) 参考 The University of California-软件库-Software 工具1&#xf…

10.3学习

1.循环依赖 循环依赖其实就是循环引用&#xff0c;也就是两个或者两个以上的 Bean 互相持有对方&#xff0c;最终形成闭环。比如A 依赖于B&#xff0c;B又依赖于A Spring中循环依赖场景有: prototype 原型 bean循环依赖 构造器的循环依赖&#xff08;构造器注入&#xff09;…

mysql-索引笔记

索引 1、什么是索引 索引是对数据库中数据的一种结构化表示。它像一本书的目录&#xff0c;能够快速定位信息&#xff0c;而无需逐行扫描所有数据。 索引的出现其实就是为了提高数据查询的效率&#xff0c;就像书的目录一样。 2、索引的常见模型 2.1.哈希表 用一个哈希函…

ChatGPT推出Canvas功能

"Canvas" 是 OpenAI 推出的全新界面&#xff0c;专为增强写作和编程协作而设计。它让用户能够在聊天之外更高效地进行编辑、审阅和反馈&#xff0c;提供了内联编辑、代码调试和文档版本控制等功能。目前&#xff0c;"Canvas" 已面向 ChatGPT Plus 和 Team …

Java进销存ERP管理系统源码

文章目录 1.项目介绍2.获取方式 1.项目介绍 主要模块:零售管理、采购管理、销售管理 仓库管理、财务管理、报表查询系统管理等。 支持预付款、收入支出 仓库调拨、组装拆卸、订单等特色功能 拥有库存状况、出入库 统计等报表 同时对角色和权限进行了细致全面控制&#xff0c…

【Spring】@RequestMapping、@RestController和Postman

文章目录 1.RequestMapping 注解介绍2. RequestMapping 使用3. RequestMapping 是 GET 还是 POST 请求&#xff1f;GET 请求POST 请求指定 GET/POST 方法类型 2. Postman 介绍1. 创建请求2. 传参介绍1. 普通传参2. form-data3. x-www-form-urlencoded form 表单&#xff0c;对应…

【深度学习】损失函数

损失函数&#xff08;Loss Function&#xff09;是机器学习和深度学习模型中的一个核心概念&#xff0c;它用于衡量模型的预测输出与真实标签之间的差异。通过优化&#xff08;最小化&#xff09;损失函数&#xff0c;模型可以不断调整其内部参数&#xff0c;提升预测性能。不同…

通信工程学习:什么是IP网际协议

IP&#xff1a;网际协议 IP网际协议&#xff08;Internet Protocol&#xff0c;简称IP&#xff09;是整个TCP/IP协议栈中的核心协议之一&#xff0c;它负责在网络中传送数据包&#xff0c;并提供寻址和路由功能。以下是对IP网际协议的详细解释&#xff1a; 一、对IP网际协议的…

Ubuntu安装Hadoop3.4

1、创建Hadoop用户 sudo adduser hadoop 将Hadoop加进sudo用户组,赋予更高权限: sudo usermod -G sudo hadoop 3、安装JDK(略) 查看JDK安装路径:which java 和 ls -al 3、配置SSH免密登录 在Hadoop分布式集群环境中,各个机器之间的通信通常需要使用SSH的方式进行连…

判断一个队列实例是否为空Queue.empty()

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 判断一个队列实例是否为空 Queue.empty() [太阳]选择题 根据给定的Python代码&#xff0c;哪个选项是错误的&#xff1f; import queue print("【执行】q queue.Queue()") …

react-问卷星项目(5)

实战 路由 路由设计&#xff0c;网址和页面的关系&#xff0c;就是从业务上分析需要哪些页面哪些页面内容可以抽离&#xff0c;业务流程要有入有出增加页面和Layout模版&#xff0c;模版就是抽离页面公共部分&#xff0c;比如都有顶部或者左侧导航&#xff0c;直接上代码&…

Solidity 设计模式:实现灵活与可扩展的智能合约架构

Solidity 作为以太坊智能合约的主要编程语言&#xff0c;拥有许多独特的设计模式&#xff0c;这些模式帮助开发者实现更加灵活、可扩展和安全的合约架构。设计模式不仅能够简化开发过程&#xff0c;还能减少常见的编程错误&#xff0c;并提高智能合约的可维护性和可升级性。本文…

舞动春日:SpringBoot打造古典舞在线交流平台

第四章 系统设计 4.1系统概要设计 本古典舞在线交流平台采用B/S结构来开发&#xff0c;这种结构是在互联网兴起后出现的&#xff0c;是一个适用于互联网环境下的模型结构&#xff0c;用户只要能上网通过浏览器就可以在任何时间、任何地点的使用。系统工作原理图如图4-1所示&…

华为OD机试 - 区间交叠问题 - 贪心算法(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…