根据上一篇的案例,我们都是把所有的组件定义在main.js
的文件中,这样显得非常的混乱:
const { createApp, mount } = window.Vue;
const MyUser = {
template: `
<div style="float: left;">
<a href="#">登录</a>
<span> | </span>
<a href="#">注册</a>
</div>`,
};
const NavItem = {
template: `
<li style="float: left; padding: 0 15px;">
<a :href="item.link" target="_blank">{{ item.title }}</a>
</li>`,
props: ["item"]
};
const MyNav = {
template: `
<ul style="float: left; padding: 0 35px; margin: 0; list-style: none;">
<nav-item v-for="item in navData" :key="item.id" :item="item" />
</ul>`,
props: ["navData"],
components: {
NavItem
}
};
const MyLogo = {
template: `<div style="float: left; padding: 0 20px;">Logo</div>`
};
const MyHeader = {
template: `
<header style="border: 1px solid #333;">
<my-logo />
<my-nav :nav-data="navData" />
<my-user />
<div style="clear: both;"></div>
</header>`,
// 注册数据属性
props: ["navData"],
components: {
MyLogo,
MyNav,
MyUser
}
};
const App = {
template: `
<div>
<!-- 使用组件 -->
<!-- 父组件给子组件传递数据 -->
<my-header :nav-data="navData" />
<!-- 复用组件,相互独立 -->
<my-header :nav-data="navData" />
</div>`,
components: {
// 注册组件,这样的方式叫做局部注册
// 局部注册:在组件内部的局部注册另外一个组件,只供当前组件使用
MyHeader
},
data() {
return {
navData: [
{
id: 1,
title: "百度",
link: "https:www.baidu.com"
},
{
id: 2,
title: "谷歌",
link: "https:www.google.com"
},
{
id: 3,
title: "必应",
link: "https:www.bing.com"
}
]
};
}
};
createApp(App).mount("#app");
通过上面的代码我们能够发现,每一个组件其实就是一个个的对象,我们可以利用 ESM 的导入导出功能把每一个组件都单独的抽离出去:
例如components/myHeader/index.js
文件导入了所有的组件:
import MyLogo from "../MyLogo/index.js";
import MyNav from "../MyNav/index.js";
import MyUser from "../MyUser/index.js";
const MyHeader = {
template: `
<header>
<my-logo />
<my-nav :nav-data="navData" />
<my-user />
<div style="clear: both;"></div>
</header>`,
// 注册数据属性
props: ["navData"],
components: {
MyLogo,
MyNav,
MyUser
}
};
export default MyHeader;
然后在在App.js
文件进行导入:
import MyHeader from "./components/MyHeader/index.js"
const App = {
template: `
<div>
<my-header :nav-data="navData" />
</div>`,
components: {
// 注册组件,这样的方式叫做局部注册
// 局部注册:在组件内部的局部注册另外一个组件,只供当前组件使用
MyHeader
},
data() {
return {
navData: [
{
id: 1,
title: "百度",
link: "https:www.baidu.com"
},
{
id: 2,
title: "谷歌",
link: "https:www.google.com"
},
{
id: 3,
title: "必应",
link: "https:www.bing.com"
}
]
};
}
};
export default App;
我们的组件化不一定非要用.vue
文件,因为我们的组件就是一个个的对象,只不过 Vue 对相应的对象进行了处理!
有没有发现通过我们对上面这些组件抽离拆分后,这好像有点类似我们.vue
文件的雏形,只不过我们现在把 template、script 还有 style 都写在了一块,.vue
文件把这三大部分都进行了分离,使其看起来更简单明了。
但是我们的浏览器无法解析.vue
文件,这就需要一些工具把.vue
文件进行解析返回一个对象,例如在webpack
中使用vue-loader
。
然后我们可以把.js
文件后缀更改为.vue
的后缀,我项目使用的是 Vite 对 Vue 进行解析,目录如下:
例如我们在components/MyHeader/index.vue
文件进行 template、script 还有 style 进行分离:
<template>
<header>
<my-logo />
<my-nav :nav-data="navData" />
<my-user />
<div style="clear: both"></div>
</header>
</template>
<script>
import MyLogo from "../MyLogo/index.vue";
import MyNav from "../MyNav/index.vue";
import MyUser from "../MyUser/index.vue";
export default {
name: "my-header",
props: ["navData"],
components: {
MyLogo,
MyNav,
MyUser
}
};
</script>
<style lang="scss" scoped>
header {
border: 1px solid #333;
}
</style>
以上代码,我们把 template、script 还有 style 都放在了.vue
的文件中,但是看起来也不会显的很乱。
然后我们在App.vue
文件中导入MyHeader
组件看看解析后的效果:
<template>
<my-header :nav-data="navData" />
</template>
<script>
import MyHeader from "./components/MyHeader/index.vue";
console.log(MyHeader)
export default {
components: {
MyHeader
},
data() {
return {
navData: [
{
id: 1,
title: "百度",
link: "https:www.baidu.com"
},
{
id: 2,
title: "谷歌",
link: "https:www.google.com"
},
{
id: 3,
title: "必应",
link: "https:www.bing.com"
}
]
};
}
};
</script>
<style lang="scss" scoped></style>
可以看到.vue
的内容最终还是会被编译为一个对象!!!
另外,某些组件很多的业务都需要使用,如果每个地方都需要进行局部注册就会显得很麻烦,Vue 为我们提供了component
方法供我们进行组件的全局注册。
import { createApp } from "vue";
import globalComponent from "./components/Global/index";
import App from "./App.vue";
const app = createApp(App);
// 我们把所有的全局组件都放到 Global 的文件夹下方便管理
globalComponent(app);
app.mount("#app");
import Search from "./Search/index.vue";
function globalComponent(app) {
// 使用实例对象上的 component 方法进行全局注册
app.component("my-search", Search);
}
export default globalComponent;
<template>
<header>
<!-- 不需要进行局部注册,就可以直接使用 -->
<my-search />
<my-logo />
<my-nav :nav-data="navData" />
<my-user />
<div style="clear: both"></div>
</header>
</template>
<script>
import MyLogo from "../MyLogo/index.vue";
import MyNav from "../MyNav/index.vue";
import MyUser from "../MyUser/index.vue";
export default {
name: "my-header",
props: ["navData"],
components: {
MyLogo,
MyNav,
MyUser
}
};
</script>
<style lang="scss" scoped>
header {
border: 1px solid #333;
}
</style>