天天看点

Vue3从入门到精通 14

作者:绘芽研究社1号
Vue3从入门到精通 14

目录:

1异步组件

1.1什么是异步组件?

1.2为什么要使用异步组件?

1.3如何使用异步组件?

2依赖注入

2.1什么是依赖注入?

2.2如何使用依赖注入?

2.2.1 Prop 逐级透传问题

2.2.2 Provide (提供)

2.2.3应用层 Provide

2.2.4 Inject (注入)

2.2.5总结

2.3示例

1 异步组件

Vue3从入门到精通 14

在传统的 Vue.js 开发中,组件是在应用程序启动时就立即加载的。

这种方式虽然简单,但是会导致应用程序的初始加载时间变长,影响用户体验。

为了提高应用程序的性能和加载速度,Vue.js 提供了异步组件。

Vue3从入门到精通 14

1.1 什么是异步组件?

在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。

异步组件是一种延迟加载组件的方式,即只有在需要使用该组件时才会进行加载。

Vue 提供了 defineAsyncComponent 方法来实现此功能。

1.2 为什么要使用异步组件?

异步组件可以减少打包的结果

会将异步组件分开打包,会采用异步的方式加载组件,可以有效的解决一个组件过大的问题。

不使用异步组件,如果组件功能比较多打包出来的结果就会变大。

1.3 如何使用异步组件?

Vue 提供了 defineAsyncComponent 方法来实现此功能。

类似 Vite 和 Webpack 这样的构建工具也支持此语法 (并且会将它们作为打包时的代码分割点),因此我们也可以用它来导入 Vue 单文件组件:

// 第一种方式
import { defineAsyncComponent } from 'vue'
// 异步加载组件
const AComponent = defineAsyncComponent(()=>{
 return  import("./components/AComponent.vue")
})

// 第二种方式
import { defineAsyncComponent } from 'vue'
// 异步加载组件
const AComponent = defineAsyncComponent(()=>
     import("./components/AComponent.vue")
)           

示例:

<template>
  <h1>{{ title }}</h1>
  <keep-alive>
    <component 
    :is="dyComponent">
    </component>
  </keep-alive>
  <hr>
  <button @click="changeHandle">
    切换组件
  </button>
</template>
<script>
import { defineAsyncComponent } from 'vue'
// 异步加载组件
const AComponent = defineAsyncComponent(()=>{
 return  import("./components/AComponent.vue")
})

// import AComponent from './components/AComponent.vue';
import BComponent from './components/BComponent.vue';
export default {
  data() {
    return {
      title: "动态组件",
      dyComponent: "BComponent"
    }
  },
  components: {
    AComponent,
    BComponent
  },
  methods: {
    changeHandle() {
      this.dyComponent = this.dyComponent === "AComponent" ? "BComponent" : "AComponent"
      console.log("切换组件:"+this.dyComponent);
    }
  }
}
</script>           

改造前:

Vue3从入门到精通 14

改造后:

Vue3从入门到精通 14

2 依赖注入

Vue3从入门到精通 14

2.1 什么事依赖注入?

依赖注入是一种设计模式。

他的目的是将组件之间的依赖关系解耦,使得组件之间的通信更加灵活和可维护。

在 vue 中,依赖注入是通过 provide 和 inject 两个 API 实现的。

2.2 如何使用依赖注入?

引用官网信息:https://cn.vuejs.org/guide/components/provide-inject.html#prop-drilling

2.2.1 Prop 逐级透传问题

通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:

Vue3从入门到精通 14

注意,虽然这里的 <Footer> 组件可能根本不关心这些 props,但为了使 <DeepChild> 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。

这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。

示例:

<template>
    <h3>{{ title }}</h3>
    <p>{{ title }} : {{ msg }}</p>
    <Child :msg="msg"></Child>
</template>
<script>
import Child from './Child.vue';

export default {
    data() {
        return {
            title: "Parent"
        }
    },
    components: {
        Child
    },
    props:{
        msg:{
            type:String
        }
    }
}
</script>           
<template>
    <h5>{{ title }}</h5>

    <p>{{ title }} : {{ msg }}</p>
</template>
<script>
export default{
    data(){
        return {
            title:"Child"
        }
    },
    props:{
        msg:{
            type:String
        }
    }
}
</script>           
<template>

  <h1>{{ title }}</h1>

  <Parent msg="依赖注入-root"></Parent>
</template>
<script>

import Parent from './components/Parent.vue';
export default {
  data() {
    return {
      title:"依赖注入"
    }
  },
  components:{
    Parent
  }
}

</script>           
Vue3从入门到精通 14

provide 和 inject 可以帮助我们解决这一问题。 [1] 一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

Vue3从入门到精通 14

2.2.2 Provide (提供)

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

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

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

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

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

然而,请注意这不会使注入保持响应性。

2.2.3 应用层 Provide

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

import { createApp } from 'vue'

const app = createApp({})

app.provide(/* 注入名 */ 'message', /* 值 */ 'hello!')           

在应用级别提供的数据在该应用内的所有组件中都可以注入。

这在你编写插件时会特别有用,因为插件一般都不会使用组件形式来提供值。

2.2.4 Inject (注入)

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

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

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

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

2.2.5 总结

注意:provide 和 inject 只能由上到下的传递,不能反向传递

2.3 示例

<template>
    <h5>{{ title }}</h5>

    <p>{{ message }}</p>
    <p>{{ parentMessage }}</p>
    <p>{{ title }} : {{ msg }}</p>
</template>
<script>
export default{
    inject: ['message','parentMessage'],
    data(){
        return {
            title:"Child"
        }
    },
    props:{
        msg:{
            type:String
        }
    }
}
</script>           
<template>
    <h3>{{ title }}</h3>
    <p>{{ title }} : {{ msg }}</p>

    <Child :msg="msg"></Child>
</template>
<script>
import Child from './Child.vue';

export default {
    provide(){
        return {
            parentMessage:"provide - Parent - "+this.title
        }
    },
    data() {
        return {
            title: "Parent"
        }
    },
    components: {
        Child
    },
    props:{
        msg:{
            type:String
        }
    }
}
</script>           
<template>
  <h1>{{ title }}</h1>

  <Parent msg="依赖注入-root"></Parent>
</template>
<script>

import Parent from './components/Parent.vue';
export default {
  data() {
    return {
      title: "依赖注入"
    }
  },
  provide: {
    message: "provide: 依赖注入"
  },
  components: {
    Parent
  }
}

</script>           
Vue3从入门到精通 14

继续阅读