[译] Vue 高性能组件注册

270 阅读2分钟

原文链接:itnext.io/vue-a-patte…

稍微用过 Vue 单文件组件的朋友,都知道如何在一个组件中使用另一个组件:

<template>
  <some-random-thing />
</template>

<script>
import SomeRandomThing from './components/SomeRandomThing'

export default {
  components: {
    SomeRandomThing,
  },
}
</script>

很常见,很普通,可能会变得乏味...

我们来看一个需求,假设有一个 Header 组件,包含应用的布局和一些信息,这些信息可能与用户相关 - UserInfo 组件,也可能与公司相关 - CompanyInfo 组件,希望根据配置值显示其中一个。

  • 方法一(可能是不少人的默认做法)
<template>
  <div>
    <company-info v-if="isCompany" />
    <user-info v-else />
    ...
  </div>
</template>

<script>
import UserInfo from './components/UserInfo'
import CompanyInfo from './components/CompanyInfo'

export default {
  components: {
    UserInfo,
    CompanyInfo,
  },
  props: {
    isCompany: { type: Boolean, default: false },
  },
}
</script>
  • 方法二:<component />
<component /> 可以作为组件的占位符,通过 :is prop 接收需要渲染的组件的 name
<template>
  <div>
    <component :is="componentName" />
  </div>
</template>

<script>
import UserInfo from './components/UserInfo'
import CompanyInfo from './components/CompanyInfo'

export default {
  components: {
    UserInfo,
    CompanyInfo,
  },
  props: {
    isCompany: { type: Boolean, default: false },
  },
  computed: {
    componentName () {
      return this.isCompany ? 'company-info' : 'user-info'
    },
  },
}
</script>

似乎改善了一点,但是,还是需要 import 组件并通过 components 注册,不够精简。

  • 方法三:动态引入 + <component />(有利于code splitting)
<template>
  <div>
    <component :is="componentInstance" />
  </div>
</template>

<script>
export default {
  props: {
    isCompany: { type: Boolean, default: false },
  },
  computed: {
    componentInstance () {
      const name = this.isCompany ? 'CompanyInfo' : 'UserInfo'
      return () => import(`./components/${name}`)
    }
  }
}
</script>

注意,this.isCompany 要在 import 语句外面访问,否则 isCompany 改变时不能触发 componentInstance 更新。

使用动态引入,Webpack 会在构建时为表达式中匹配的每个文件创建一个 chunk 文件,所以要确保在表达式中使用严格的 filter,使用名称和文件夹约定或者 webpack magic comments。