Vue 学习笔记之七组件的使用

991

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)
        }
    }