vue3中在<script setup>中获取全局内容(三种方式)

26,983 阅读2分钟

摘要

在vue3中并没有暴露出一个获取全局方法的的接口
所以我们并不能通过 import {全局方法} from 'vue' 的方法来获取

首先在main.js中定义全局的内容

 const app = createApp(App)
 app.config.globalProperties.$test = '666'
 app.mount('#app')

方法一(不推荐)

  • 使用 getCurrentInstance 方法区获取 具体获取方法 // v3官网文档说是只能在生命周期内执行 但是setup其实也是一个生命周期 执行顺序在挂载之前 const ctx = getCurrentInstance() console.log('ctx', ctx)

这时我们就能在控制台中看到我们定义的内容了 image.png

不推荐原因

其实在官网中已经说的很明白了 v3.cn.vuejs.org/api/composi…

image.png

在生产环境内可能会获取不到该实例!!,而且我们确实不应该用该方法去代替this

方法二(推荐)

  • 使用 Provide / Inject

    v3.cn.vuejs.org/guide/compo…

    在main.js中provide

    app.provide('$test', '666')
    

    在组件内获取

    import { inject } from 'vue'
    const test = inject('$test')
       console.log('inject的$test', test)
    

这样就可以获取到了

image.png

扩展

  • 挂载方法 在main.js中provide
    import dayjs from 'dayjs'
    const formatTime = (time, format) => (time ? dayjs(time).format(format || 'YYYY-MM-DD') : '-')
    app.provide('dayjs', formatTime)
    

在组件中获取

const dayjs = inject('dayjs')
const formatResult = dayjs(1639014286)
console.log('dayFormat', formatResult)

image.png

方式三(不推荐 只适合应急的时候使用 因为我觉得这样用怪怪的)

  • 使用两个script标签来获取this并保存

首先现在main.js中像之前一样定义全局变量

import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 官方推荐将全局变量写进 globalProperties下
app.config.globalProperties.myOption = 'myOption'
app.mount('#app')

然后在组件中获取

<script>
import HelloWorld from './components/HelloWorld.vue'
import { onBeforeMount, defineComponent } from 'vue'
let that = this
export default defineComponent({
  beforeCreate() {
    that = this
  },
})
</script>
<script setup>
onBeforeMount(() => {
  console.log('that', that.myOption)
})
</script>

image.png

这样就可以获取到啦

在setup标签中一定要在 onBeforeMount之后再读取this!!!

一些问题

  • 为什么要创建两个script标签?
    • 因为在setup标签中是不绑定this的 所以只能在另一个script标签中获取
  • 为什么一定要在onBeforeMount之后才能获取呢?
    • 因为setup的生命周期是在beforeCreate,created之前执行的 我们在beforeCreate时保存的this,所以要在beforeCreate之后获取,onBeforeMount是在beforeCreate之后执行的 所以可以获取到 note
  • 如果按这样写了两个script标签那么就不可以在没写setup中再执行setup函数
<script>
import HelloWorld from './components/HelloWorld.vue'
import { onBeforeMount, defineComponent } from 'vue'
let that = this
export default defineComponent({
  beforeCreate() {
    console.log('beforeCreate')
    that = this
  },
  setup() {
    // 这里面的内容不会执行
    console.log('非单标签的setup')
  }
})
</script>
<script setup>
console.log('setup')
onBeforeMount(() => {
  console.log('that', that.myOption)
})
</script>
  • 为啥
    • 因为在标签中写setup本身就是一个语法糖 vue会检验是否有<script setup> 如果有,他将会执行执行其中的内容,并替代 options方式中的setup。也就是说 哪怕<script setup>中没有任何内容 只要有这个标签存在,他都不会执行options方式中的setup方法。
// 这是options方式
<script>
import HelloWorld from './components/HelloWorld.vue'
export default defineComponent({
  setup() {
    // 这里面的内容还是不会执行
    console.log('非单标签的setup')
  }
})
</script>
// 这是<script setup>
<script setup></script>

你可能回想(会不会是因为 setup标签放到下方 所以覆盖了上方的setup方法呢?) 经测试 这个执行方式无关你放置<script setup></script>的位置 哪怕将其放到options方式上方他仍然不会执行!