如何在一个文件中写多个Vue组件(译-有删改)
原文地址 Writing multiple Vue components in a single file
在一个文件中编写多个组件是React的模式,其中一些文件包含多个组件。
走开发过程中,有些组件对文件/导出组件是“私有的”,因为没有其他组件需要使用它们。这个时候我们倾向于把它们写到一个文件中。
我们将使用vue-cli
脚手架项目中的默认“Hello World”组件作为示例。
默认情况下,有两个文件,App
和HelloWorld
,HelloWorld
接收msg
属性并呈现它。
要将它们写在单个文件中,如果用React实现的话一般如下所示:
const HelloWorld = ({ msg }) => (<div>
<h1>Hello world</h1>
<div>{msg}</div>
</div>);
const App = () => (<div id="app">
<HelloWorld msg="Welcome to Your React App" />
</div>);
export default App;
由于React代码实际上就是普通的JavaScript,因此您可以在一个文件中定义多个组件。
在Vue中,它仍然是可能的,但它有点复杂,有多种方法可以实现:

示例仓库:vue-multiple-components-in-sfc。
一. 使用render函数
<template>
<div id="app">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
// inline component
const HelloWorld = {
props: ['msg'],
render(h) {
return h('div', [
h('h1', 'Hello world'),
h('div', this.msg)
])
}
};
export default {
name: 'app',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
二. 使用Vue.component和template
<template>
<div id="app">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import Vue from 'vue';
// inline component with template string 👍
const HelloWorld = Vue.component('hello-world', {
props: ['msg'],
template: `<div>
<h1>Hello world</h1>
<div>{{ this.msg }}</div>
</div>`
});
export default {
name: 'app',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
但是这种方式不能在Vue Runtime-only构建版本上生效,会有如下的错误提示

关于Vue几种不同构建版本的区别可以参考:Explanation of Different Builds
上面的问题可以使用带compiler的Vue构建版本来修复
例如:
//Webpack
module.exports = {
// ...
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
}
}
}
或者vue.config.js
中添加:
module.exports = {
runtimeCompiler: true
};
三. 仅使用template而不使用Vue.component
<template>
<div id="app">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
// inline component with template string 👍
const HelloWorld = {
props: ['msg'],
template: `<div>
<h1>Hello world</h1>
<div>{{ this.msg }}</div>
</div>`
};
export default {
name: 'app',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
这个方法也需要带compiler的Vue构建版本
四.使用JSX(编译为渲染函数)
我们可以用JSX重写我们的初始渲染函数示例 App.js
:
<template>
<div id="app">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
// inline component with JSX
const HelloWorld = {
props: ['msg'],
render() {
return (<div>
<h1>Hello world</h1>
<div>{this.msg}</div>
</div>);
}
};
export default {
name: 'app',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Vue CLI 3+已经配置了babel-plugin-transform-vue-jsx
Using JSX with Vue and Why You Should Care