7 组件注册
组件名
在注册一个组件的时候,我们始终需要给它一个名字。比如在全局注册的时候我们已经看到了:
Vue.component('my-component-name', { /* ... */ })
该组件名就是 Vue.component
的第一个参数
你给予组件的名字可能依赖于你打算拿它来做什么。当直接在 DOM 中使用一个组件 (而不是在字符串模板或单文件组件) 的时候,我们强烈推荐遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)。这会帮助你避免和当前以及未来的 HTML 元素相冲突
组件名大小写
定义组件名的方式有两种:
使用 kebab-case
Vue.component('my-component-name', { /* ... */ })
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>
。
使用 PascalCase
Vue.component('MyComponentName', { /* ... */ })
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name>
和 <MyComponentName>
都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
7.1 注册全局组件
到目前为止,我们只用过 Vue.component
来创建组件:
Vue.component('my-component-name', {
// ... 选项 ...
})
这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue
) 的模板中。比如:
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
new Vue({ el: '#app' })
使用组件
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。
7.2 定义和组件的三种方式
第一种方式:
//方法1:定义组件
var login = Vue.extend({
template:'<h1>登陆页面</h1>'
})
//注册组件
Vue.component('login',login);
<div id="app">
<login></login>
</div>
第二种方式:
//方法2:定义一个全局组件
Vue.component('register',{
template:'<h1>注册页面</h1>'
})
使用
<div id="app">
<register></register>
</div>
第三种方式:
//方法3:定义一个账号组件,建议使用方法三
Vue.component('account',{
template:'#account',
data:function(){
//与vue对象不同的是组件中的data是一个function,
//所以要这么写
return {
message:'账户组件'
}
},
methods:{
login:function(){
alert("Hello VueJs")
}
}
})
模板的事件写在对应的模板中
全局组件引用了一个在html中定义的组件模板account
<!--组件模板的定义 template和script定义都可以但是建议使用template-->
<template id="account">
<div>
{{message}}
<a href="#" @click.prevent="login">登陆</a> |
<a href="#">注册</a>
</div>
</template>
也可以使用script
定义但是建议使用template
标签
<script type="x-template" id="account">
<div>
<a href="#">登陆</a> |
<a href="#">注册</a>
</div>
</script>
值得注意的是,所有子元素必须使用一个共同的根标签包围,如div
7.3 局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
在这些情况下,你可以通过一个普通的 JavaScript 对象来定义组件:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
然后在 components
选项中定义你想要使用的组件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
或者是在组件中定义子组件
//定义一个账号组件
Vue.component('account',{
template:'<div><h1>账号组件</h1><login></login></div>',
//在账号组件中定义一个登陆子组件
components:{
'login':{
template:'<h2>登陆子组件</h2>'
}
}
})
在组件中定义的子组件必须在父组件中使用如上面的
<div><h1>账号组件</h1><login></login></div>
对于 components
对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
7.4 组件的动态切换
首先注册两个组件,login和regist
Vue.component('login',{
template:'<h1>登陆页面</h1>'
})
Vue.component('regist',{
template:'<h1>注册页面</h1>'
})
<div id="app">
<a href="#" @click.prevent="cname = 'login'">登陆</a> |
<a href="#" @click.prevent="cname = 'regist'">注册</a>
<!-- 利用component标签中的:is参数来进行组件的切换 -->
<component :is="cname"></component>
</div>
组件的切换使用component
标签的is
属性
new Vue({
el:'#app',
data:{
cname:'login'
}
})
只要控制is的值即可控制组件的显示,如上通过点击事件改变cname
的值来切换组件
7.5 父组件与子组件传值
父组件向子组件传值
- 定义组件
<template id="subEle">
<div>
{{name}}
</div>
</template>
new Vue({
el:'#app',
data:{
name:'张三'
},
components:{
'subelement':{
template:'#subEle',
props:['name']//负责接收父组件传入的值
}
}
})
在组件中有一个props属性在其中定义变量负责接收父组件传递过来的值
然后在组件模板中使用插值表达式接收{{name}}
- 父组件如何向子组件传递值?
通过将子组件中负责接收父组件传入值得变量name
绑定到组件上传入值即可
<div id="app">
<subelement :name="name"></subelement>
</div>
子组件向父组件传值
new Vue({
el:'#app',
data:{
name:'张三'
},
methods:{
getdata:function(data){
alert(data)
}
},
components:{
'subelement':{
template:'#subEle',
//props:['name']//负责接收父组件传入的值
methods:{
sendData:function(){
//将hello传值给父组件
this.$emit('send','Hello VueJs')
}
}
}
}
})
如上所示:在子组件中写一个方法sendData
用于向父组件发送值,内部使用this.$emit
方法向父组件发送一个事件用于传递值,key是事件名称,值就是呀发送的数据。
当点击子组件中定义的按钮时触发sendData
事件向父组件传值
<template id="subEle">
<button type="button" @click="sendData">点击传值</button>
</template>
而这个父组件我们可以将Vue对象的实例视为一个根组件,将数据传递给Vue实例。
使用组件并传递值
<div id="app">
<subelement v-on:send="getdata"></subelement>
</div>
当点击子组件的按钮时调用子组件中定义的方法sendData
触发一个方法向父组件发送一个send
事件,而send事件绑定了一个getdata
方法用于获取子组件传递过来的值
methods:{
getdata:function(data){
alert(data)
}
}