官方文档


组件名

kebab-case命名方式

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

PascalCase命名方式

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

全局注册

  1. Vue.component('my-component-name',{
  2. //...选项
  3. })

注册之后可以在任何新创建的Vue根实例(new Vue)的模板中使用

局部注册

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

  1. var ComponentA = { /* ... */ }
  2. var ComponentB = { /* ... */ }
  3. var ComponentC = { /* ... */ }

然后在 components 选项中定义你想要使用的组件:

  1. new Vue({
  2. el: '#app',
  3. components: {
  4. 'component-a': ComponentA,
  5. 'component-b': ComponentB
  6. }
  7. })

对于 components 对象中的每个 property 来说,其 property 名就是自定义元素的名字,其 property 值就是这个组件的选项对象。

局部注册组件调用

注意局部注册的组件在其子组件中不可用
**
若使ComponentAComponentB 中可用

普通写法:

  1. var ComponentA = { /* ... */ }
  2. var ComponentB = {
  3. components: {
  4. 'component-a': ComponentA
  5. },
  6. // ...
  7. }

Babel 和 webpack 使用 ES6模块写法:

  1. import ComponentA from './ComponentA.vue'
  2. export default {
  3. components: {
  4. ComponentA
  5. },
  6. // ...
  7. }

在对象中放一个类似ComponentA的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:

  • 用在模板中的自定义元素的名称
  • 包含了这个组件选项的变量名

在模块系统中局部注册

创建一个 components目录,并将每个组件放置在其各自的文件中。

一个假设的ComponentB.jsComponentB.vue文件中

  1. import ComponentA from './ComponentA'
  2. import ComponentC from './ComponentC'
  3. export default {
  4. components: {
  5. ComponentA,
  6. ComponentC
  7. },
  8. // ...
  9. }

基础组件的自动化全局注册

可能你的许多组件只是包裹了一个输入框或按钮之类的元素,是相对通用的。我们有时候会把它们称为基础组件,它们会在各个组件中被频繁的用到。
所以会导致很多组件里都会有一个包含基础组件的长列表:

  1. import BaseButton from './BaseButton.vue'
  2. import BaseIcon from './BaseIcon.vue'
  3. import BaseInput from './BaseInput.vue'
  4. export default {
  5. components: {
  6. BaseButton,
  7. BaseIcon,
  8. BaseInput
  9. }
  10. }

而只是用于模板中的一小部分:

  1. <BaseInput
  2. v-model="searchText"
  3. @keydown.enter="search"
  4. />
  5. <BaseButton @click="search">
  6. <BaseIcon name="search"/>
  7. </BaseButton>

如果你恰好使用了 webpack (或在内部使用了 webpack 的 Vue CLI 3+),那么就可以使用 require.context 只全局注册这些非常通用的基础组件。这里有一份可以让你在应用入口文件 (比如 src/main.js) 中全局导入基础组件的示例代码:

  1. import Vue from 'vue'
  2. import upperFirst from 'lodash/upperFirst'
  3. import camelCase from 'lodash/camelCase'
  4. const requireComponent = require.context(
  5. // 其组件目录的相对路径
  6. './components',
  7. // 是否查询其子目录
  8. false,
  9. // 匹配基础组件文件名的正则表达式
  10. /Base[A-Z]\w+\.(vue|js)$/
  11. )
  12. requireComponent.keys().forEach(fileName => {
  13. // 获取组件配置
  14. const componentConfig = requireComponent(fileName)
  15. // 获取组件的 PascalCase 命名
  16. const componentName = upperFirst(
  17. camelCase(
  18. // 获取和目录深度无关的文件名
  19. fileName
  20. .split('/')
  21. .pop()
  22. .replace(/\.\w+$/, '')
  23. )
  24. )
  25. // 全局注册组件
  26. Vue.component(
  27. componentName,
  28. // 如果这个组件选项是通过 `export default` 导出的,
  29. // 那么就会优先使用 `.default`,
  30. // 否则回退到使用模块的根。
  31. componentConfig.default || componentConfig
  32. )
  33. })

注意

全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生。
**

笔记


**
就是说Vue实例和组件的实例有差别但是差别不大,因为毕竟一个是父类一个是子类

一般的应用,会拥有一个根实例,在根实例里面嵌套一个一个的组件

组件可以互相嵌套,而且,所有的组件最外层必须有一个根实例组件分为:全局组件和局部组件

全局组件在任意的实例、父级组件中都能使用,局部组件只能在创建自己的父级组件或者实例中使用

全局注册:

  1. Vue.component('hello',{
  2. template:"<h1>hello</h1>"
  3. })

组件通过template来确定自己的模板,template里的模板必须有根节点,标签必须闭合

组件的属性挂载通过:data方法来返回一个对象作为组件的属性,这样做的目的是为了每一个组件实例都拥有独立的data属性

局部注册:

  1. components:{
  2. 'hello':{
  3. template:"<h1>asdasdasdasdasdas</h1>"
  4. }
  5. }

在实例或者组件中注册另一个组件,这个时候,被注册的组件只能在注册它的实例或组件的模板中使用,一个组件可以被多个组件或实例注册

注意浏览器规则

因为vue在解析模板的时候会根据某些html的规则,例如,在table里只能放tr,td,th..,如果放入组件不会解析 这个时候我们可以放入tr使用is方式来标识这个tr其实是组件

  1. <table id="app">
  2. <tr is="hello"></tr>
  3. </table>

template

  1. <template id="my-hello">
  2. <div>
  3. <h1>hello world</h1>
  4. <p>hahahah</p>
  5. </div>
  6. </template>
  7. //组件中
  8. template:"#my-hello"

is切换

在实例、组件的模板中的某一个标签上,可以通过is属性来指定为另一个目标的组件,这个时候我们一般会使用component标签来占位、设置is属性来指定目标组件

  1. <component :is="type"></component>
  2. //组件中
  3. data:{
  4. type:'aaa'
  5. },
  6. components:{
  7. 'aaa':{template:"<h1>AAAAAAAAAAAAA</h1>"},
  8. 'bbb':{template:"<h1>BBBBBBBBBBBBB</h1>"}
  9. }

组件嵌套

应用中划分的组件可能会很多,为了更好的实现代码复用,所以必然会存在组件的嵌套关系

组件设计初衷就是要配合使用的,最常见的就是形成父子组件的关系:组件 A 在它的模板中使用了组件 B。

  1. <div id="app">
  2. <father/>
  3. </div>
  4. new Vue({
  5. el:"#app",
  6. components:{
  7. father:{ //定义了父组件
  8. template:'<div>这是father组件... <son/></div>',
  9. components:{ //定义子组件
  10. son:{
  11. template:"<div>这是son组件</div>"
  12. }
  13. }
  14. }
  15. }
  16. })