vue.js基础知识篇:组件详解
Posted 陈蒙的技术空间
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue.js基础知识篇:组件详解相关的知识,希望对你有一定的参考价值。
第11章:组件详解
组件是Vue.js最推崇也最强大的功能之一,核心目标是可重用性。
我们把组件代码按照template、style、script的拆分方式,放置到对应的.vue文件中。
1.注册
Vue.js的组件注册分为全局注册和局部注册。
全局注册使用Vue.component方法。第一个参数是组件名字,第二个参数是组件的构造函数,要么是function,要么是object。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <didi-component></didi-component> <en-component></en-component> </div> <script src="js/vue.js"></script> <script> //第二个参数传入object的情况 Vue.component("didi-component",{ template:"<div>A custom component!</div>" }); //第二个参数传入function的情况,它是一个组件构造器 var ENcomponent=Vue.extend({ template:"<div>A 2rd components</div>" }); //注册 Vue.component("en-component",ENcomponent); //创建根实例 new Vue({ el:"#app" }) </script> </body> </html>
显示效果
局部注册,以vue实例选项components或者组件构造器即Vue.extend函数的components选项。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <didi-component></didi-component> </div> <script src="js/vue.js"></script> <script> var Parent=Vue.extend({ template:"<p>这里是父组件的内容</p><br/><child></child>", components:{ "child":{ template:"<div>我是子组件的内容</div>" } } }) new Vue({ el:"#app", components:{ "didi-component":Parent } }) </script> </body> </html>
显示效果
2.数据传递
组件作为一个app(项目)的组成部分,总是要涉及到组件通信。组件通信属于数据传递的范畴,数据传递一共有3种方式:
props、组件通信、slot。
(1)props属性
首先区别一下props和data和propsData。props作用于父子组件之间的数据传递,data组件或者vue实例化时经常使用,propsData用来在组件初始化后覆盖props中的属性。接下来是如何使用props属性。
第一种方式,字面量语法
直接在组件的html代码中传入普通的字符串,在组件内部使用props属性。注意:html不区分大小写,名字为camelCase的属性会转化为短横线隔开(kebab-case)。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <hello-component msg="hello"></hello-component> <vivian my-data="3.1415"></vivian> </div> <script src="js/vue.js"></script> <script> Vue.component("hello-component",{ props:["msg"], template:"<span>{{msg}},front-end!</span>" }); Vue.component("vivian",{ props:["myData"], template:"<div>{{myData}}</div>", replace:true }) new Vue({ el:"#app" }) </script> </body> </html>
第二种,动态语法
下面的例子从父组件向子组件传递属性,每当父组件的数据变化时,该变化也会传导给子组件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <vivi-props></vivi-props> </div> <script src="js/vue.js"></script> <script> var Child=Vue.extend({ props:["viviProps"], //传给子组件的属性名称 template:"<div>{{viviProps}}</div>", //既然在props属性上定义了,那么就可以在模板里使用了 replace:true }); var Parent=Vue.extend({ template:"<p>我是父组件的内容</p><br/><child :vivi-props=\'hello\'></child>", data:function(){ return {"hello":"hello"} }, //动态绑定的属性的值由父组件的data来定义 components:{ "child":Child } }) new Vue({ el:"#app", components:{ "vivi-props":Parent } }); </script> </body> </html>
第三种方式,使用.sync和.once修饰符。
默认或者使用.once修饰符是父组件到子组件的单向绑定。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <input type="text" v-model="info.name"/> <child v-bind:msg.once="info"></child> <!--把根实例的info数据属性传递给子组件child的msg属性--> </div> <script src="js/vue.js"></script> <script> new Vue({ el:"#app", data:{ info:{ name:"顺风车" } }, components:{ "child":{ props:["msg"], template:"<div>{{msg.name}}</div>" } } }) </script> </body> </html>
.sync修饰符能做到双向绑定。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> 父组件: <input v-model="val"><br/> 子组件: <test :test.sync="val"></test> </div> <script src="js/vue.js"></script> <script> var vm = new Vue({ el: \'#app\', data: { val: 1 }, components: { "test": { props: [\'test\'], template: "<input v-model=\'test\'/>" } } }); </script> </body> </html>
显示结果
第4种方式,prop验证。
我们把自己的组件给别人使用,那么要求使用者能够根据prop提供的对象正确使用。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> 父组件: <input v-model="val"><br/> 子组件: <test :test="val"></test> </div> <script src="js/vue.js"></script> <script> var vm = new Vue({ el: \'#app\', data: { val: 1 }, components:{ test:{ props: { test: { twoWay: true } //我们希望组件的使用者通过双向绑定来使用这个组件。 }, //把根实例的val属性传递给test属性。 template: "<input v-model=\'test\'/>" } } }); </script> </body> </html>
我们看到这个代码 <test :test="val"></test> 会抛出错误如下:
那么正确的使用应该是如下,加上.sync修饰词,以满足twoWay:true的要求。
第5种方式,prop转换函数,coerce函数。可以理解为prop属性值的过滤器。
(2)组件通信
尽管this.$parent和this.$children(属性)可以访问父/子组件的数据,根实例的后代可以通过this.$root访问根实例,但这种方式应该尽量避免。
首先,因为父子组件紧密的耦合,只看父组件却很难理解父组件的状态,因为它能被任意的修改。再次,子组件要使用父组件的数据,应当避免直接依赖,尽量显式的使用props属性。
我们的方案是通过作用域传递事件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <template id="child-template"> <input v-model="msg"> <button v-on:click="notify">Dispatch Event</button> <!--子组件绑定了notify函数--> </template> <div id="events-example"> <p>Message:{{messages|json}}</p> <child></child> </div> </div> <script src="js/vue.js"></script> <script> Vue.component("child",{ template:"#child-template", data:function(){ return {msg:"hello"} }, methods:{ notify:function(){ if(this.msg.trim()){ this.$dispatch("child-msg",this.msg); this.msg=""; } //notify函数的功能是把msg属性的值dispatch到child-msg事件上,它会沿着父作用域的链冒泡 } } }); var parent=new Vue({ el:"#events-example", data:{ messages:[] }, events:{ "child-msg":function(msg){ this.messages.push(msg); } //接收到child-msg事件后,那么执行push方法 } }) var vm = new Vue({ el: \'#app\' }); </script> </body> </html>
接下来是在子组件v-on监听,更加简洁的代码。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"Vue 基础篇二