vue组件总结(三)
一、什么是组件
组件(component)是Vue最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码,根据项目需求,抽象出一些组件,每个组件里包含了展现、功能和样式。每个页面,根据自己的需要,使用不同的组件来拼接页面。这种开发模式使得前端页面易于扩展,且灵活性高,而且组件之间也实现了解耦。
在Vue里,一个组件本质上是一个拥有预定义选项的一个Vue实例。组件是一个自定义元素或称为一个模块,包括所需的模板、逻辑和样式。在HTML模板中,组件以一个自定义标签的形式存在,起到占位符的功能。通过Vue.js的声明式渲染后,占位符将会被替换为实际的内容。
二、注册组件
组件注册包括全局注册和局部注册两种
- 调用
Vue.component()
注册组件时,组件的注册是全局的,这意味着该组件可以在任意Vue示例下使用。(全局注册的行为必须在根Vue实例创建之前发生) - 如果不需要全局注册,或者是让组件使用在其它组件内,可以用选项对象的components属性实现局部注册。(局部注册组件在子组件中不可用)
【全局组件】要注册一个全局组件,可以使用Vue.component(tagName,option),组件在注册之后,便可以在父实例的模块中以自定义元素<my-component></my-component>的形式使用,实例如下所示:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>全局组件</title> 6 <script src="../node_modules/vue/dist/vue.js"></script> 7 <style type="text/css"> 8 .container{ 9 width: 200px; 10 height: 300px; 11 border: 2px solid blue; 12 } 13 .container h2{ 14 font-size: 30px; 15 font-style: normal; 16 } 17 </style> 18 </head> 19 <body> 20 <div id="app"> 21 <!--使用组件,全局组件可以多次使用--> 22 <my-component></my-component> 23 </div> 24 <div id="app2"> 25 <!--使用组件,全局组件可以多次使用--> 26 <my-component></my-component> 27 <my-component2></my-component2> 28 </div> 29 <!--定义组件的视图--> 30 <template id="demo3"> 31 <h1 style="color:red">我是选项模板3</h1> 32 </template> 33 <!--定义组件的视图--> 34 <script type="x-template" id="demo4"> 35 <div class="container"> 36 <h1 style="color:red">我是script标签模板4</h1> 37 <h2>我是script标签模板</h2> 38 </div> 39 </script> 40 41 <script> 42 //全局注册组件,全局组件可以多次使用 43 Vue.component("my-component",{ 44 template:"#demo3" 45 }); 46 //全局注册组件,全局组件可以多次使用 47 Vue.component("my-component2",{ 48 template:"#demo4" 49 }); 50 var vm1 = new Vue({ 51 el: "#app" 52 }); 53 var vm2 = new Vue({ 54 el: "#app2" 55 }) 56 </script> 57 </body> 58 </html
运行效果如下所示:
【局部注册】通过使用组件实例选项component注册,可以使组件仅在另一个实例或者组件的作用域中可用,实例如下所示:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>局部组件</title> 6 <script src="../node_modules/vue/dist/vue.js"></script> 7 <style type="text/css"> 8 .container{ 9 width: 200px; 10 height: 300px; 11 border: 2px solid blue; 12 } 13 .container h2{ 14 font-size: 30px; 15 font-style: normal; 16 } 17 </style> 18 </head> 19 <body> 20 21 <template id="demo1"> 22 <h1 style="color:red">我是局部组件的布局模板1</h1> 23 </template> 24 25 <script type="x-template" id="demo2"> 26 <div class="container"> 27 <h1 style="color:red">我是script标签构建的布局模板</h1> 28 <h2>我是script标签模板</h2> 29 </div> 30 31 </script> 32 33 <div id="app1"> 34 <my-component1></my-component1> 35 <my-component2></my-component2> 36 </div> 37 <div id="app2"> 38 <!--无法在app2这里使用,因为是子组件是在app2中局部注册的--> 39 <my-component1></my-component1> 40 <my-component2></my-component2> 41 </div> 42 <script> 43 //子组件1 44 var child1 = { 45 template:"#demo1" 46 }; 47 //子组件2 48 var child2 = { 49 template:"#demo2" 50 }; 51 var vm1 = new Vue({ 52 el: "#app1", 53 components:{ 54 //注册子组件,<my-component1>和<my-component2>只能在app1使用 55 "my-component1":child1, 56 "my-component2":child2 57 } 58 }); 59 var vm2 = new Vue({ 60 el: "#app2" 61 }) 62 </script> 63 </body> 64 </html>
运行效果如下所示:
三、组件之间传值
3.1. 父组件向子组件传值
-
子组件在props中创建一个属性,用以接收父组件传过来的值
-
在父组件中注册子组件;
-
在子组件标签中添加子组件props中创建的属性;
-
把需要传给子组件的值赋给该属性
实例如下所示:
父组件:
1 <template> 2 <!-- 父组件 --> 3 <div id="app"> 4 父组件: 5 <input type="text" v-model="name"> 6 <!-- 引入子组件 --> 7 <child :inputName="name"></child> 8 </div> 9 </template> 10 11 <script type="text/ecmascript-6"> 12 import child from './child' 13 export default { 14 components: { 15 child 16 }, 17 data () { 18 return { 19 name: '' 20 } 21 } 22 } 23 </script> 24 25 <style lang="stylus" rel="stylesheet/stylus" scoped> 26 27 </style>
子组件:
1 <template> 2 <div> 3 <!--子组件--> 4 子组件: 5 <span>{{inputName}}</span> 6 </div> 7 </template> 8 9 <script type="text/ecmascript-6"> 10 export default { 11 /* 接受父组件 */ 12 props: { 13 inputName: String, 14 required: true 15 } 16 17 } 18 </script> 19 20 <style lang="stylus" rel="stylesheet/stylus" scoped> 21 22 </style>
运行效果如下所示:
3.2.子组件向父组件传值
-
子组件中需要以某种方式(如点击事件)的方法来触发一个自定义的事件;
- 将需要传的值作为$emit的第二个参数,该值将作为实参传给响应事件的方法;
3.在父组件中注册子组件并在子组件标签上绑定自定义事件的监听。
实例如下所示:
子组件:
1 <template> 2 <div id="app"> 3 子组件: 4 <span>{{childValue}}</span> 5 <!-- 定义一个子组件传值的方法 --> 6 <input type="button" value="点击触发" @click="childClick"> 7 </div> 8 </template> 9 10 <script type="text/ecmascript-6"> 11 export default { 12 data () { 13 return { 14 childValue: '我是子组件的数据' 15 } 16 }, 17 methods: { 18 childClick () { 19 console.log('childClick') 20 // childByValue是在父组件on监听的方法 21 // 第二个参数this.childValue是需要传的值 22 this.$emit('childByValue', this.childValue) 23 } 24 } 25 } 26 </script> 27 28 <style lang="stylus" rel="stylesheet/stylus" scoped> 29 30 </style>
父组件:
<template> <div> 父组件: <span>{{name}}</span> <br> <br> <!-- 引入子组件 定义一个on的方法监听子组件的状态--> <child-component v-on:childByValue="childByValue"></child-component> </div> </template> <script type="text/ecmascript-6"> import childComponent from './childComponent' export default { components: { childComponent }, data () { return { name: '' } }, methods: { childByValue: function (childValue) { // childValue就是子组件传过来的值 this.name = childValue console.log(this.name) } } } </script> <style lang="stylus" rel="stylesheet/stylus" scoped> </style>
运行效果如下所示: