组件注册

上一节实验中,我们大概了解了一下组件的基础,这一节实验我们要深入组件注册。

组件名字

我们在注册组件的时候,我们都会给组件起一个名字,就好像我们人的名字一样。需要注意的是,我们的组件名字是有一些规范的,一般这种单文件组件,我们强烈推荐使用字母全小写且必须包含一个连字符,全部小写字母,单词使用中华线 - 隔开。

例如我们在 src/main.js 下注册的全局组件:

app.component('content-box', {
    template: `<div>
        这是插槽内容
        <slot></slot>
    </div>`
})

组件名字规范

在字符串模板或单个文件组件中定义组件时,定义组件名的方式有两种:

使用kebab-case

app.component('content-box', {
    template: `<div>
        这是插槽内容
        <slot></slot>
    </div>`
})

当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如:

<template>
  <div class="template-m-wrap">
    <content-box> Something bad happened. </content-box>
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  data() {
    return {
      searchText: "",
    };
  },
};
</script>

使用 PascalCase

app.component('contentBox', {
    template: `<div>
        这是插槽内容
        <slot></slot>
    </div>`
})

当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <contentBox> 和 <content-box> 都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的:

<template>
  <div class="template-m-wrap">
    <content-box> Something bad happened. </content-box>
      <contentBox>Something bad happened.</contentBox>
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  data() {
    return {
      searchText: "",
    };
  },
};
</script>

全局注册

想我们在 src/main.js 实现组件的注册:

import { createApp } from 'vue/dist/vue.esm-bundler.js'
import App from './App.vue'
import router from './router'
import store from './store'
let app = createApp(App)
app.use(store).use(router).mount('#app')
app.component('button-counter', {
    template: `<button @click="count">{{counter}}</button>`,
    data() {
        return {
            counter: 0,
        }
    },
    methods: {
        count() {
            this.counter++
        }
    }
})
// 我们再来定义一个全局组件
app.component('blog-title', {
    props: {
        title: {
            type: String,
            default: ''
        }
    },
    template: `<div>
        <h4>{{title}}</h4>
        <button @click="emitFn">changeSize</button>
    </div>`,
    methods: {
        emitFn() {
            this.$emit('change-size', 10)
        }
    },
    emits: ['change-size']
})
app.component('custom-input', {
    props: ['modalVal'],
    template: `
    <input v-model="value"> 
    `,
    computed: {
        value: {
            get() {
                return this.modalVal
            },
            set(val) {
                this.$emit('update:modalVal', val)
            }
        }
    }
})
app.component('content-box', {
    template: `<div>
        这是插槽内容
        <slot></slot>
    </div>`
})

以上组件都是全局注册组件,我们在使用的时候如下:

<template>
  <div class="template-m-wrap">
    <content-box> Something bad happened. </content-box>
    <blog-title title="这是博客标题"></blog-title>
    <custom-input v-model="searchText"></custom-input>
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  data() {
    return {
      searchText: "",
    };
  },
};
</script>

查看浏览效果如下:

Vue 3 组件注册_Vue

局部注册

全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。

你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:

import ComponentA from './ComponentA.vue'

export default {
  components: {
    ComponentA
  }
  // ...
}

接下来我们就来实现一个局部组件的注册:

我们现在在 src/views 新建一个组件 TestCom.vue:

<template>
    <div class="test-com-wrap">
        局部组件
    </div>
</template>
<script>
export default {
    name: 'TestCom',
}
</script>

然后导入到 src/views/TemplateM.vue 组件里面注册:

<template>
  <div class="template-m-wrap">
    <test-com></test-com>
  </div>
</template>
<script>
import TestCom from './TestCom'
export default {
  name: "TemplateM",
  components: {
    TestCom
  },
  data() {
    return {
      searchText: "",
    };
  },
};
</script>

我们查看浏览效果如下:

Vue 3 组件注册_Vue_02