目录
1. 组件的注册
1.1 组件注册的传统步骤
1.1.1 传统步骤:
-
创建组件构造器
-
注册组件
-
使用组件
<div id="app">
<!--3.使用组件-->
<my-component></my-component>
<div>
<my-component></my-component>
</div>
</div>
<my-component></my-component>
<script src="../js/vue.js"></script>
<script>
// 1.创建组件构造器
const cpnConstructor = Vue.extend({
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈</p>
<p>我是内容,哈哈哈</p>
</div>`
});
// 2.注册组件
Vue.component('my-component', cpnConstructor);
const app = new Vue({
el: '#app',
data: {
}
});
</script>
注意:组件模板template中只能有一个根元素!(在不使用v-if、v-els-if指令时)
1.1.2 注册组件传统步骤解析
-
Vue.extend():
- 调用Vue.extend()创建的是一个组件构造器。
- 通常在创建组件构造器时,传入template代表我们自定义组件的模板。
- 该模板就是在使用到组件的地方 要显示的HTML代码。
- 事实上,这种写法在Vue2.x的文档中几乎已经看不到了,会直接使用语法糖写法,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。
-
Vue.component():
- 调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。
- 所以需要传递两个参数:① 注册组件的标签名 ② 组件构造器
-
组件必须挂载在某个Vue实例下,否则它不会生效。
- 本例中使用了三次
- 而第三次其实并没有生效
1.2 组件名大小写问题
组件名的命名规范:
短横线分隔命名
Vue.component('my-component-name', { /* ... */ })
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>
。
首字母大写命名
Vue.component('MyComponentName', { /* ... */ })
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name>
和 <MyComponentName>
都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
1.3 全局组件和局部组件
1.3.1 全局组件
当我们通过调用Vue.component()
注册组件时,这些组件是全局注册的
-
这意味着该组件可以在任意 Vue 根实例 (
new Vue
)下使用。下面的示例中创建了多个Vue实例,注册的全局组件可以在多个Vue实例作用范围内使用<div id="app"> <!--3.使用组件--> <my-component></my-component> <div> <my-component></my-component> </div> <my-component></my-component> </div> <div id="app2"> <my-component></my-component> </div> <script src="../js/vue.js"></script> <script> // 1.创建组件构造器 const cpnConstructor = Vue.extend({ template: ` <div> <h2>我是标题</h2> <p>我是内容,哈哈哈</p> <p>我是内容,哈哈哈</p> </div>` }); // 2.注册组件 Vue.component('my-component', cpnConstructor); const app = new Vue({ el: '#app', data: { } }); const app2 = new Vue({ el: '#app2', data: { } }) </script>
-
全局注册往往是不够理想的,会造成构建结果体积的累加。开发中用的最多的是局部组件,且一般只有一个Vue根实例
1.3.2 局部组件
如果组件是在某个实例中注册的,那么该组件就是一个局部组件。
<div id="app">
<!--3.使用组件-->
<my-component></my-component>
<div>
<my-component></my-component>
</div>
<my-component></my-component>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建组件构造器
const cpnConstructor = Vue.extend({
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈</p>
<p>我是内容,哈哈哈</p>
</div>`
});
const app = new Vue({
el: '#app',
data: {
},
// 2.注册局部组件
components: {
'my-component': cpnConstructor,
}
});
</script>
1.4 父组件和子组件的注册
在前面我们看到了组件树:
- 组件和组件之间存在层级关系
- 而其中一种非常重要的关系就是父子组件的关系
- Vue实例可以看成是一个特殊的父组件
通过代码组成这种层级关系示例:
<div id="app">
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建子组件构造器
const childCpn = Vue.extend({
template: `
<div>
<h2>我是子组件中的内容</h2>
<p>我是子组件中的内容</p>
<p>我是子组件中的内容</p>
</div>`
});
// 2.创建父组件构造器
const cpn = Vue.extend({
template: `
<div>
<h2>我是父组件中的内容</h2>
<p>我是父组件中的内容</p>
<p>我是父组件中的内容</p>
<child></child>
</div>`,
// 注册子组件
components: {
// 将childCpn注册为cpn的子组件
child: childCpn
}
});
const app = new Vue({
el: '#app',
data: {
},
components: {
// 注册父组件
cpn: cpn
}
})
</script>
父子组件错误用法:以子标签的形式在Vue实例中使用
-
因为当子组件注册到父组件的
components
时,Vue会编译好父组件的模板 -
该模板的内容已经决定了父组件将要渲染的HTML(相当于父组件中已经有了子组件中的内容了)
-
<child></child>
是只能在父组件中被识别的。
1.5 注册组件语法糖
上面注册组件的方式可能会有些繁琐,Vue为了简化这个过程,提供了注册组件的语法糖。
- 主要是省去了调用
Vue.extend()
的步骤,可以直接使用一个对象来代替。
1.5.1 注册全局组件语法糖
<div id="app">
<!--3.使用组件-->
<my-component></my-component>
<div>
<my-component></my-component>
</div>
</div>
<script src="../js/vue.js"></script>
<script>
/*// 创建组件构造器
const cpnConstructor = Vue.extend({
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈</p>
<p>我是内容,哈哈哈</p>
</div>`
});*/
// 注册全局组件的语法糖,省略了创建组件构造器的过程
Vue.component('my-component', {
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈</p>
<p>我是内容,哈哈哈</p>
</div>`
});
const app = new Vue({
el: '#app',
data: {
}
});
</script>
1.5.2 注册局部组件语法糖
<div id="app">
<!--3.使用组件-->
<my-component></my-component>
<div>
<my-component></my-component>
</div>
</div>
<script src="../js/vue.js"></script>
<script>
/*// 创建组件构造器
const cpnConstructor = Vue.extend({
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈</p>
<p>我是内容,哈哈哈</p>
</div>`
});*/
const app = new Vue({
el: '#app',
data: {
},
components: {
// 注册局部组件语法糖,省略了创建组件构造器的过程
"my-component": {
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈</p>
<p>我是内容,哈哈哈</p>
</div>`
}
}
});
</script>
1.6 模板的分离写法
通过语法糖简化了Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是template模块。如果我们能将其中的HTML分离出来,结构必然会变得更加清晰。
Vue提供了两种方案来定义组件的HTML模板内容:
-
使用
<script>
标签,并带上type
属性,属性值为text/x-template
,通过id
属性来标识、引用该模板。<div id="app"> <cpn></cpn> </div> <!--带上type属性,属性值为text/x-template--> <script type="text/x-template" id="cpn"> <div> <h2>我是标题</h2> <p>我是内容,哈哈哈</p> </div> </script> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { }, components: { cpn: { //通过模板的id属性来引用模板 template: '#cpn' } } }) </script>
-
使用
<template>
标签(推荐),通过id
属性来标识、引用该模板。<div id="app"> <cpn></cpn> </div> <template id="cpn"> <div> <h2>我是标题</h2> <p>我是内容...</p> </div> </template> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { }, components: { cpn: { //通过模板的id属性来引用模板 template: '#cpn' } } }) </script>
注意:组件模板中只能有一个根元素,即<script>
标签、<template>
标签内部用一个根元素包裹起来(在不使用v-if、v-els-if指令时)。