美文网首页
vue Provide

vue Provide

作者: 仰望天空的人 | 来源:发表于2023-03-09 10:27 被阅读0次

    Provide (提供)#

    要为组件后代提供数据,需要使用到 provide 选项:

    js

    export default {
      provide: {
        message: 'hello!'
      }
    }
    
    

    对于 provide 对象上的每一个属性,后代组件会用其 key 为注入名查找期望注入的值,属性的值就是要提供的数据。

    如果我们需要提供依赖当前组件实例的状态 (比如那些由 data() 定义的数据属性),那么可以以函数形式使用 provide

    js

    export default {
      data() {
        return {
          message: 'hello!'
        }
      },
      provide() {
        // 使用函数的形式,可以访问到 `this`
        return {
          message: this.message
        }
      }
    }
    
    

    然而,请注意这不会使注入保持响应性。我们会在后续小节中讨论如何让注入转变为响应式

    应用层 Provide#

    除了在一个组件中提供依赖,我们还可以在整个应用层面提供依赖:

    js

    import { createApp } from 'vue'
    
    const app = createApp({})
    
    app.provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
    
    

    在应用级别提供的数据在该应用内的所有组件中都可以注入。这在你编写插件时会特别有用,因为插件一般都不会使用组件形式来提供值。

    Inject (注入)#

    要注入上层组件提供的数据,需使用 inject 选项来声明:

    js

    export default {
      inject: ['message'],
      created() {
        console.log(this.message) // injected value
      }
    }
    
    

    注入会在组件自身的状态之前被解析,因此你可以在 data() 中访问到注入的属性:

    js

    export default {
      inject: ['message'],
      data() {
        return {
          // 基于注入值的初始数据
          fullMessage: this.message
        }
      }
    }
    

    输入参数#

    尽管其响应性不依赖 ref,组合式函数仍可接收 ref 参数。如果编写的组合式函数会被其他开发者使用,你最好在处理输入参数时兼容 ref 而不只是原始的值。unref() 工具函数会对此非常有帮助:

    js

    import { unref } from 'vue'
    
    function useFeature(maybeRef) {
      // 若 maybeRef 确实是一个 ref,它的 .value 会被返回
      // 否则,maybeRef 会被原样返回
      const value = unref(maybeRef)
    }
    
    

    如果你的组合式函数在接收 ref 为参数时会产生响应式 effect,请确保使用 watch() 显式地监听此 ref,或者在 watchEffect() 中调用 unref() 来进行正确的追踪。

    除了 Vue 内置的一系列指令 (比如 v-modelv-show) 之外,Vue 还允许你注册自定义的指令 (Custom Directives)。

    我们已经介绍了两种在 Vue 中重用代码的方式:组件组合式函数。组件是主要的构建模块,而组合式函数则侧重于有状态的逻辑。另一方面,自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。

    一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。钩子函数会接收到指令所绑定元素作为其参数。下面是一个自定义指令的例子,当一个 input 元素被 Vue 插入到 DOM 中后,它会被自动聚焦:

    js

    const focus = {
      mounted: (el) => el.focus()
    }
    
    export default {
      directives: {
        // 在模板中启用 v-focus
        focus
      }
    }
    
    

    template

    <input v-focus />
    

    插件没有严格定义的使用范围,但是插件发挥作用的常见场景主要包括以下几种:

    1. 通过 app.component()app.directive() 注册一到多个全局组件或自定义指令。

    2. 通过 app.provide() 使一个资源可被注入进整个应用。

    3. app.config.globalProperties 中添加一些全局实例属性或方法

    4. 一个可能上述三种都包含了的功能库 (例如 vue-router)。

    这个组件中有一个 <button> 按钮来触发打开模态框,和一个 class 名为 .modal 的 <div>,它包含了模态框的内容和一个用来关闭的按钮。

    当在初始 HTML 结构中使用这个组件时,会有一些潜在的问题:

    position: fixed 能够相对于浏览器窗口放置有一个条件,那就是不能有任何祖先元素设置了 transform、perspective 或者 filter 样式属性。也就是说如果我们想要用 CSS transform 为祖先节点 <div class="outer"> 设置动画,就会不小心破坏模态框的布局!

    这个模态框的 z-index 受限于它的容器元素。如果有其他元素与 <div class="outer"> 重叠并有更高的 z-index,则它会覆盖住我们的模态框。

    <Teleport> 提供了一个更简单的方式来解决此类问题,让我们不需要再顾虑 DOM 结构的问题。让我们用 <Teleport> 改写一下 <MyModal>:

    template
    <button @click="open = true">Open Modal</button>

    <Teleport to="body">
    <div v-if="open" class="modal">
    <p>Hello from the modal!</p>
    <button @click="open = false">Close</button>
    </div>
    </Teleport>

    不使用构建工具#

    如果你没有使用任何构建工具,而是从 CDN 或其他源来加载 Vue,请确保在部署时使用的是生产环境版本(以 .prod.js 结尾的构建文件)。生产环境版本会被最小化,并移除了所有仅用于开发环境的代码分支。

    • 如果需要使用全局变量版本(通过 Vue 全局变量访问):请使用 vue.global.prod.js
    • 如果需要 ESM 版本(通过原生 ESM 导入访问):请使用 vue.esm-browser.prod.js

    更多细节请参考构建文件指南

    追踪运行时错误#

    应用级错误处理 可以用来向追踪服务报告错误:

    js

    import { createApp } from 'vue'
    const app = createApp(...)
    app.config.errorHandler = (err, instance, info) => {
      // 向追踪服务报告错误
    }
    
    

    诸如 SentryBugsnag 等服务也为 Vue 提供了官方集成。

    在 JavaScript 中访问透传 Attributes#

    如果需要,你可以在 <script setup> 中使用 useAttrs() API 来访问一个组件的所有透传 attribute:

    vue

    <script setup>
    import { useAttrs } from 'vue'
    
    const attrs = useAttrs()
    </script>
    
    

    如果没有使用 <script setup>attrs 会作为 setup() 上下文对象的一个属性暴露:

    js

    export default {
      setup(props, ctx) {
        // 透传 attribute 被暴露为 ctx.attrs
        console.log(ctx.attrs)
      }
    }
    
    

    需要注意的是,虽然这里的 attrs 对象总是反映为最新的透传 attribute,但它并不是响应式的 (考虑到性能因素)。你不能通过侦听器去监听它的变化。如果你需要响应性,可以使用 prop。或者你也可以使用 onUpdated() 使得在每次更新时结合最新的 attrs 执行副作用。

    相关文章

      网友评论

          本文标题:vue Provide

          本文链接:https://www.haomeiwen.com/subject/dyyrqdtx.html