阅读 113

Vue3 组件注册(1)

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

Vue2 相比,Vue3 中注册组件变得更加简单了。

1. 注册组件的方式

如果不使用组件,复杂逻辑堆积在一起,像这样:

<div id="app"></div>

<template id="my-app">
  <input type="text" v-model="message">
  <h2>{{ message }}</h2>

  <h2>{{ title }}</h2>
  <p>{{ desc }}</p>

  <button @click="btnClick">按钮</button>
</template>

<script src="./js/vue.js"></script>
<script>
  const App = {
    data() {
      return {
        message: '你好啊',
        title: '我是标题',
        desc: '我是内容...'
      }
    },
    methods: {
      btnClick() {
        console.log('按钮被点击了');
      }
    },
    template: '#my-app'
  };

  Vue.createApp(App).mount('#app');
</script>
复制代码

所有的内容都写在一起必然是不现实的。因此,我们可以使用组件将各部分内容抽离出去。就是说,如果现在有一部分内容(模板、逻辑等),我们希望将这部分内容抽取到一个独立的组件中去维护,那么该如何注册一个组件呢?

比如下面的模板希望抽离成一个单独的组件:

<h2>{{ title }}</h2>
<p>{{ message }}</p>
复制代码

注册的组件分成两种:

  • 全局组件:在任何其它的组件中都可以使用的组件;
  • 局部组件:只有在注册的组件中才能使用的组件;

2. 注册全局组件

  • 全局组件需要使用我们全局创建的 app 来注册
  • 通过 component 方法传入组件名称组件对象,即可注册一个全局组件了;
  • 之后,我们可以在 App 组件的 template直接使用这个全局组件

image-20211012190053494.png

<body> 元素中的代码如下:

<div id="app"></div>

<template id="my-app">
  <h2>我是标题</h2>
  <p>我是内容...</p>

  <component-a></component-a>
  <component-a></component-a>
  <component-a></component-a>
</template>

<template id="component-a">
  <h2>我是标题</h2>
  <p>我是内容...</p>
</template>

<script src="./js/vue.js"></script>
<script>
  const App = {
    template: '#my-app'
  };

  const app = Vue.createApp(App)

  // 使用 Vue 的 createApp() 函数返回的 app 对象,注册一个全局组件
  // 全局组件:意味着注册的这个组件可以在任何的组件模板中使用(但在开发中一般不推荐注册全局组件)
  // app.component(组件名称, 组件对象);
  app.component('component-a', {
    // template: `<h3>我是component-a组件</h3>`
    template: '#component-a'
  });

  app.mount('#app');
</script>
复制代码

上面注册的全局组件中只有 template,其实,我们注册的组件中也可以有自己的代码逻辑(比如自己的 datacomputedmethods 等等):

// 使用 Vue 的 createApp() 函数返回的 app 对象,注册一个全局组件
app.component('component-a', {
  data() {
    return {
      title: '我是标题',
      message: '我是内容...'
    }
  },
  methods: {
    btnClick() {
      console.log('按钮发生了点击');
    }
  },
  template: '#component-a'
});
复制代码

<body> 元素中的代码如下:

<div id="app"></div>

<template id="my-app">
  <!-- 使用组件 -->
  <component-a></component-a>
  <component-a></component-a>
  <component-a></component-a>
</template>

<template id="component-a">
  <h2>{{ title }}</h2>
  <p>{{ message }}</p>
  <button @click="btnClick">按钮</button>
</template>

<script src="./js/vue.js"></script>
<script>
  const App = {
    template: '#my-app'
  };

  const app = Vue.createApp(App)

  // 使用 Vue 的 createApp() 函数返回的 app 对象,注册一个全局组件
  app.component('component-a', {
    data() {
      return {
        title: '我是标题',
        message: '我是内容...'
      }
    },
    methods: {
      btnClick() {
        console.log('按钮发生了点击');
      }
    },
    template: '#component-a'
  });

  app.mount('#app');
</script>
复制代码

当然,我们也可以注册多个全局组件:

<div id="app"></div>

<template id="my-app">
  <component-a></component-a>
  <component-b></component-b>
</template>

<template id="component-a">
  <h2>{{ title }}</h2>
  <p>{{ message }}</p>
  <button @click="btnClick">按钮</button>
</template>

<template id="component-b">
  <input type="text" v-model="message">
  <h2>ComponentB</h2>
</template>

<script src="./js/vue.js"></script>
<script>
  const App = {
    template: '#my-app'
  };

  const app = Vue.createApp(App)

  // 使用 Vue 的 createApp() 函数返回的 app 对象,注册一个全局组件
  app.component('component-a', {
    data() {
      return {
        title: '我是标题',
        message: '我是内容...'
      }
    },
    methods: {
      btnClick() {
        console.log('按钮发生了点击');
      }
    },
    template: '#component-a'
  });

  // 再注册一个全局组件,名为 component-b
  app.component('component-b', {
    data() {
      return {
        message: 'Hello World!'
      }
    },
    template: '#component-b'
  })

  app.mount('#app');
</script>
复制代码

页面效果:

image-20211016123733854.png

你可能会说,不对啊,为什么按钮和文本框在同一行啊?其实原因非常简单,因为在 Vue3 中,组件的 template 中不再需要用一个根元素包裹了。而在 Vue2 中,则需要用一个根元素包裹,一般会用一个 <div> 元素去包裹。因此,如果在这里我们也加上 <div> 元素去包裹,因为 <div> 元素是块级元素会独占一行的,那么就能让按钮和文本框不在同一行了。但是由于我们这里没有 <div> 元素,所以在渲染完行内元素 <button> 后就会来渲染行内元素 <input> ,结果就在同一行了。其实,后面我们读源码时就会知道为什么 Vue3template 中不需要根元素了(其实是因为它会把 Fragment 当成根元素去处理)。

以上,就是注册多个全局组件的过程。需要说明的是,在开发中一般不推荐注册全局组件。另外,我们目前在注册多个全局组件的时候,所有代码仍然是放在一个 html 文件里的,看起来有点复杂。因此,后面我们会讲另外一种开发模式:SFCSingle File Components,单文件组件)的开发模式,就是把有关代码抽取到 .vue 文件中。

文章分类
前端
文章标签