[ Vue3 不太冷的知识 ] Vue 提供的几个 Composition API

568 阅读1分钟

useCssModule

Vue 开启 cssModule 后,可以通过这个 API 取到经过 vue-loader 处理后的 className。

- HelloWorld.vue
// template
<div :class="$style.hello">text</div>

// script
export default {
  setup() {
    const $style = useCssModule()
    console.log($style.hello); // "HelloWorld_hello_1ae9G"
  }
}

// style
<style module>
  .hello {
    color: red;
  }
</style>

Vue CSS Modules文档参考

源码解析
获取当前组件实例下的 type.__cssModules.$style 对象。
tip: __cssModules 由 vue-loader 注入

function useCssModule(name = '$style') {
  if (!__GLOBAL__) {
    const instance = getCurrentInstance()!
    const modules = instance.type.__cssModules
    const mod = modules[name]
    if (!mod) {
      return EMPTY_OBJ
    }
    return mod
  } else {
    return EMPTY_OBJ
  }
}


简单封装例子

   import { useCssModule, ref, watchEffect } from 'vue'

function useClassnames(namesGetter) {
  const $styles = useCssModule()

  const classnames = ref([])
  watchEffect(function() {
    classnames.value = getClassnames()
  })
  function getClassnames() {
    const names = namesGetter()
    if (Array.isArray(names)) {
      return names.filter(i => !!i).map(it => $styles[it])

    } else {
      const result = []
      for (const key in names) {
        names[key] && classNames.push($styles[key])
      }
      return result
    }
  }
  return classnames
}

// 使用
const rootStyle = useClassnames(() => ({
  hello: true,
  active: props.active
}))




useCssVars

在 Vue 组件的 root el 的 style 上添加 CSS 变量。

// 用法

// template
<div class="text-color">1</div>

// script

function useTheme() {
  const theme = reactive({
    textColor: '#b53f6b'
  })
  const getTheme = (useProxy) => {
    const { active } = useProxy
    return active ? theme : {}
  }
  useCssVars(getTheme)
}

export default {
  setup() {
    useTheme()
    const active = ref(true)
    return { active }
  }
}

// style
.text-color {
  color: var(--textColor);
}

useCssVars 实现源码

useContext

获取当前组件里 setup 方法的第二个参数 context


function useHeaderSlot() {
   const { slots } = useContext()
   return slots && slots.header
}

export default {
  setup() {
      const headerSlot = useHeaderSlot()
  }
}

useSSRContext

拓展

由于Compositon API 已经不存在 this 了。所以获取插件添加到全局的方法比较麻烦。但是可以从组件实例的 proxy 对象里能取到。

// main.js
const app = createApp(App)
app.config.globalProperties.foo = 'bar'
app.mount('#app')

// useRenderContext,js
function useRenderContext(){
  const i = getCurrentInstance()!
  return i.proxy
}
  
  
setup() {
  const { foo } = useRenderContext()
  foo // bar
}