.js

按照上一篇的组件树创建目录
image.png
按照 esm 的方式创建各组件的 js 文件,也可以把样式抽离出去成 scss 或 css 文件

main

  1. import App from 'App';
  2. Vue.createApp(App).mount("#app");

App

  1. import MyHeader from './components/MyHeader';
  2. const App = {
  3. components: {
  4. MyHeader
  5. },
  6. data() {
  7. return {
  8. navData: [
  9. {id: 1, title: 'Baidu', link: 'http://www.baidu.com'},
  10. {id: 2, title: 'Google', link: 'http://www.google.com'},
  11. {id: 3, title: 'Bing', link: 'http://www.bing.com'}
  12. ],
  13. navData2: [
  14. {id: 1, title: '京东', link: 'http://www.jd.com'},
  15. {id: 2, title: '淘宝', link: 'http://www.taobao.com'},
  16. {id: 3, title: '天猫', link: 'http://www.tmall.com'}
  17. ]
  18. }
  19. },
  20. template: `
  21. <div>
  22. <my-header :nav-data="navData" />
  23. <my-header :nav-data="navData2" />
  24. </div>
  25. `
  26. }
  27. export default App;

MyHeader

  1. import MyLogo from './MyLogo';
  2. import MyNav from './MyNav';
  3. import MyUser from './MyUser';
  4. const MyHeader = {
  5. components: {
  6. MyLogo,
  7. MyNav,
  8. MyUser
  9. },
  10. props: ['navData']
  11. template: `
  12. <header>
  13. <my-logo />
  14. <my-nav :nav-data="navData" />
  15. <my-user />
  16. </header>
  17. `
  18. }
  19. export default MyHeader;

MyLogo

  1. import './index.scss';
  2. const MyLogo = {
  3. template: `
  4. <div class="my-logo">LOGO</div>
  5. `
  6. }
  7. export default MyLogo;
  1. .my-logo {
  2. float: left;
  3. padding: 0 20px;
  4. }

MyNav

  1. import NavItem from './NavItem';
  2. import './index.scss';
  3. const MyNav = {
  4. components: {
  5. NavItem
  6. },
  7. props: ['navData']
  8. template: `
  9. <ul class="my-nav">
  10. <nav-item v-for="item of navData" :key="item.id" :nav-item="item"/>
  11. </ul>
  12. `
  13. }
  14. export default MyNav;

NavItem

  1. const NavItem = {
  2. props: ['navItem'],
  3. template: `
  4. <li>
  5. <a :href="navItem.link" target="_blank">{{ navItem.title }}</a>
  6. </li>
  7. `
  8. }
  9. export default NavItem;
  1. .my-nav {
  2. float: left;
  3. padding: 0 35px;
  4. margin: 0;
  5. list-style:none;
  6. .nav-item {
  7. float: left;
  8. padding: 0 15px;
  9. }
  10. }

MyUser

  1. const MyUser = {
  2. template: `
  3. <div>
  4. <a href=“#”>Sign in</a> | <a href=“#”>Sign up</a>
  5. </div>
  6. `
  7. }
  8. export default MyUser;

.vue

.vue 的本质是在一个文件内包含

  • template
  • script
  • style

然后.vue 会打包成 .js

为了 import 时可以忽略写 .vue 在 webpack.config.js 加上

  1. model.exports = {
  2. //...
  3. resolve: {
  4. extension: ['.js', '.jsx', '.vue']
  5. },
  6. // ...
  7. }

在 webpack 中已经配置 vue-loader 可以解析到 .vue 文件
App

  1. <template>
  2. <div>
  3. <my-header :nav-data="navData" />
  4. <my-header :nav-data="navData2" />
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. name: 'app',
  10. components: {
  11. MyHeader
  12. },
  13. data() {
  14. return {
  15. navData: [
  16. {id: 1, title: 'Baidu', link: 'http://www.baidu.com'},
  17. {id: 2, title: 'Google', link: 'http://www.google.com'},
  18. {id: 3, title: 'Bing', link: 'http://www.bing.com'}
  19. ],
  20. navData2: [
  21. {id: 1, title: '京东', link: 'http://www.jd.com'},
  22. {id: 2, title: '淘宝', link: 'http://www.taobao.com'},
  23. {id: 3, title: '天猫', link: 'http://www.tmall.com'}
  24. ]
  25. }
  26. },
  27. }
  28. </script>

MyHeader

  1. <template>
  2. <header>
  3. <my-logo />
  4. <my-nav :nav-data="navData" />
  5. <my-user />
  6. </header>
  7. </template>
  8. <script>
  9. import MyLogo from './MyLogo';
  10. import MyNav from './MyNav';
  11. import MyUser from './MyUser';
  12. export default {
  13. name: 'my-header',
  14. components: {
  15. MyLogo,
  16. MyNav,
  17. MyUser
  18. }
  19. props: ['navData']
  20. }
  21. </script>

MyLogo

  1. <template>
  2. <div class="my-logo">LOGO</div>
  3. </template>
  4. <script>
  5. export default {
  6. name: 'my-logo'
  7. }
  8. </script>
  9. <style lang="scss">
  10. .my-logo {
  11. float: left;
  12. padding: 0 20px;
  13. }
  14. </style>

MyNav

  1. <template>
  2. <ul class="my-nav">
  3. <nav-item v-for="item of navData" :key="item.id" :nav-item="item"/>
  4. </ul>
  5. </template>
  6. <script>
  7. export default {
  8. name: 'my-nav',
  9. components: {
  10. NavItem
  11. },
  12. props: ['navData']
  13. }
  14. </script>
  15. <style lang="scss">
  16. .my-nav {
  17. float: left;
  18. padding: 0 35px;
  19. margin: 0;
  20. list-style:none;
  21. }
  22. </style>

NavItem

  1. <template>
  2. <li>
  3. <a :href="navItem.link" target="_blank">{{ navItem.title }}</a>
  4. </li>
  5. </template>
  6. <script>
  7. export default {
  8. name: 'nav-item',
  9. props: ['navItem']
  10. }
  11. </script>
  12. <style lang="scss">
  13. .nav-item {
  14. float: left;
  15. padding: 0 15px;
  16. }
  17. </style>

MyUser

  1. <template>
  2. <div>
  3. <a href=“#”>Sign in</a> | <a href=“#”>Sign up</a>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: 'my-user',
  9. }
  10. </script>

组件全局注册

组件注册

  • 全局注册
  • 局部注册

在组件树最顶层,即在 main.js 中 createApp 返回的对象通过 component 方法注册

  1. import App from './App';
  2. const app = Vue.createApp(App);
  3. app.component('my-search', {
  4. data() {
  5. return {
  6. placeholder: 'Please type the keyword...',
  7. keyword: ''
  8. }
  9. },
  10. template: `
  11. <div style="float: left">
  12. <input type="text" :placeholder="placeholder" v-model="keyword" />
  13. <button @click="searchAction">Search</button>
  14. </div>
  15. `,
  16. methods: {
  17. searchAction() {
  18. console.log(this.keyword);
  19. }
  20. }
  21. });
  22. app.mount("#app");

这样可以在所有组件中不需要局部相应的注册来使用,如在 MyHeader 中使用

  1. <template>
  2. <header>
  3. <my-logo />
  4. <my-search />
  5. <my-nav :nav-data="navData" />
  6. <my-user />
  7. </header>
  8. </template>
  9. <script>
  10. import MyLogo from './MyLogo';
  11. import MyNav from './MyNav';
  12. import MyUser from './MyUser';
  13. export default {
  14. name: 'my-header',
  15. components: {
  16. MyLogo,
  17. MyNav,
  18. MyUser
  19. }
  20. props: ['navData']
  21. }
  22. </script>

分离全局注册

创建一个 globalComponents.js 方法

  1. export default function globalComponents (app) {
  2. app.component('my-search', {
  3. data() {
  4. return {
  5. placeholder: 'Please type the keyword...',
  6. keyword: ''
  7. }
  8. },
  9. template: `
  10. <div style="float: left">
  11. <input type="text" :placeholder="placeholder" v-model="keyword" />
  12. <button @click="searchAction">Search</button>
  13. </div>
  14. `,
  15. methods: {
  16. searchAction() {
  17. console.log(this.keyword);
  18. }
  19. }
  20. });
  21. }
  1. import App from './App';
  2. import globalComponents from './components/Global'
  3. const app = Vue.createApp(App);
  4. globalComponents(app);
  5. app.mount("#app");