定义vue组件
创建全局组件
第一种方式1 2 3 4 5 6 7 8 9 10 11 var com1 = Vue .extend ({ template :'<h3>这是使用Vue.extend创建的组件</h3>' }) Vue .component ('myCom1' ,com1)
第二种方式
1 2 3 4 5 Vue .component ('myCom2' ,{ template :'<div><h3>这是使用Vue.component创建的组件</h3></div>' })
1 2 3 4 5 6 7 8 9 <div id ="app" > <my-com3 > </my-com3 > </div > <template id ="tmp1" > <div > <h1 > 这是通过template 元素在外部定义的组件元素,这个方式,有代码的指示提示和高亮</h1 > <h4 > 好用,不错!</h4 > </div > </template >
1 2 3 4 5 6 7 8 9 10 11 Vue .component ('myCom3' ,{ template :'#tmp1' }) var vm = new Vue ({ el :'#app' , data :{ }, methods :{}, })
使用vue实例的render方法渲染组件(替换app里所有内容)
1 2 3 4 5 6 7 8 9 10 11 12 13 var login = { template : '<h1>登录组件</h1>' } var vm = new Vue ({ el :'#app' , data :{}, methods :{}, render : function (createElements ){ return createElements (login) } })
创建组件使用components
定义私有组 1 2 3 4 5 6 7 8 <div id ="app-2" > <login > </login > </div > <template id ="login" > <div > <label > 用户名:</label > <input type ="text" name ="" > <br > <label > 密码:</label > <input type ="text" name ="" > <br > <button type ="button" > 登录</button > </div > </template >
1 2 3 4 5 6 7 8 9 10 11 12 var vm2 = new Vue ({ el :'#app-2' , data :{}, methods :{}, directives :{}, components :{ login :{ template :'#login' } }, filters :{} })
组件中的data 注册一个定时器组件案例 拿计时器案例讲:如果按照全局组件声明一个对象dataObj,count
的值会相互影响,导致同一值
1 2 3 4 5 6 7 8 9 10 11 12 var dataObj ={count :0 }Vue .component ('counter' ,{ template : '#tmp_count' , data : function ( ){ return dataObj } methods :{ increament :function ( ){ this .count ++ } } })
结果
正确定义方法 1 2 3 4 5 6 7 8 9 10 11 <div id ="app" > <counter > </counter > <counter > </counter > <counter > </counter > </div > <template id ="tmp_count" > <div > <input type ="button" name ="" value ="+1" @click ="increament" > <h3 > {{count}}</h3 > </div > </template >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Vue .component ('counter' ,{ template : '#tmp_count' , data : function ( ){ return { count :0 } }, methods :{ increament :function ( ){ this .count ++ } } })
结果
演示
实现不同组件的切换 利用v-if & v-else 实现注册和登录切换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <div id ="app" > <a href ="" @click.prevent ="flag=true" > 登录</a > <a href ="" @click.prevent ="flag=false" > 注册</a > <login v-if ="flag" > </login > <register v-else ="flag" > </register > </div > <template id ="login" > <div > <label > 用户名:</label > <input type ="text" name ="" > <br > <label > 密码:</label > <input type ="text" name ="" > <br > <button type ="button" > 登录</button > </div > </template > <template id ="register" > <div > <label > 用户名:</label > <input type ="text" name ="" > <br > <label > 密码:</label > <input type ="text" name ="" > <br > <label > 确认密码:</label > <input type ="text" name ="" > <br > <button type ="button" > 注册</button > </div > </template >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Vue .component ('login' ,{ template :'#login' }) Vue .component ('register' ,{ template :'#register' }) var vm = new Vue ({ el :'#app' , data :{ flag :true }, methods :{} })
效果演示
利用vue提供的component 实现组件切换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <div id ="app" > <a href ="" @click.prevent ="component_name='login'" > 登录</a > <a href ="" @click.prevent ="component_name='register'" > 注册</a > <component :is ="component_name" > </component > </div > <template id ="login" > <div > <label > 用户名:</label > <input type ="text" name ="" > <br > <label > 密码:</label > <input type ="text" name ="" > <br > <button type ="button" > 登录</button > </div > </template > <template id ="register" > <div > <label > 用户名:</label > <input type ="text" name ="" > <br > <label > 密码:</label > <input type ="text" name ="" > <br > <label > 确认密码:</label > <input type ="text" name ="" > <br > <button type ="button" > 注册</button > </div > </template >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Vue .component ('login' ,{ template :'#login' }) Vue .component ('register' ,{ template :'#register' }) var vm = new Vue ({ el :'#app' , data :{ component_name : 'login' } })
结果与第一种完全相同
总结 目前,当前学习了几个vue提供的标签 component
,template
,transition
组件动画过度 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <style > .v-enter , .v-leave { opacity :0 ; transform : translateX (150px ); } .v-enter-active , .v-leave-active { transition :all 0.5s ease } </style > <transition mode ="out-in" > <component :is ="component_name" > </component > </transition >
演示:
父组件向子组件传值或方法
传值【案例:com1】: 通过定义props属性绑定
传方法【案例:com2】:this.$emit(‘组件定义的方法’,option)
1 2 3 4 5 6 7 8 9 10 11 12 <div id ="app" > <com1 :parentmsg ="msg" > </com1 > <com2 @func ="show" > </com2 > </div > <template id ="tmp1" > <div > <h3 > 这是一个子组件</h3 > <button type ="button" @click ="myclick" > 这是一个子组件按钮,点击触发父组件传递来的func方法</button > </div > </template >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 var com2 = Vue .component ('com2' ,{ template :'#tmp1' , data ( ){ return { msg :'儿子:我有钱了,给爸爸200块钱拿去买烟' } }, methods :{ myclick :function ( ){ this .$emit('func' ,123 ,456 ,this .msg ) } } }) var vm = new Vue ({ el :'#app' , data :{ msg : '爸爸这里有100块钱,儿子你要不要?' , datamsgForSon : null }, components :{ com1 :{ data ( ){ return { title :'123' , content :'小名' } }, template :'<h1>这是子组件{{parentmsg}}</h1>' , props :['parentmsg' ] } }, methods :{ show :function (data,data2,data3 ){ console .log ('这是调用了子组件show方法' +data+data2+data3) this .datamsgForSon = data3 } } })
演示地址 父->子 方法和数据,然后把子组件数据绑定到父data中去
组件案例:【评论列表】 1 2 3 <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 .subtitle { width : 300px ; height : auto; } .b { display : block; width : 6px ; height : auto; background : skyblue; } .subtitle h3 { width : 300px ; margin : 0 ; padding :0 ; position : relative; left : 18px ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <div id ="app" > <div class ="container" > <div class ="jumbotron" > <cmt-box @func ="loadComments" > </cmt-box > </div > <div class ="subtitle" > <span class ="b" > <h3 > 评论区</h3 > </span > </div > <hr > <div class ="media" > <li v-for ="item in list" :key ="item.id" > <div class ="media-left media-top" > <img src ="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3342714247,4238880061&fm=15&gp=0.jpg" class ="media-object" style ="width: 60px" > </div > <div class ="media-body" > <h4 class ="media-heading" > 评论人:{{item.user}} <span style ="font-size: 12px;color: #999" > {{item.id | dateFormat}}</span > </h4 > <p > {{item.content}}</p > </div > </li > </div > </div > </div > <template id ="tmp1" > <div > <div class ="form-group" > <label > 评论人:</label > <input type ="text" v-model ="user" class ="form-control" v-focus > </div > <div class ="form-group" > <label > 评论内容:</label > <textarea class ="form-control" v-model ="content" @keyup.enter ="postComment" > </textarea > </div > <div class ="form-group" > <input type ="button" class ="btn btn-primary" value ="发表评论" @click ="postComment" > </div > </div > </template >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 var commentBox ={ template :'#tmp1' , data ( ){ return { user :'' , content :'' } }, methods :{ postComment :function ( ){ var comment ={id : Date .now (),user : this .user ,content : this .content } var list = JSON .parse (localStorage .getItem ('cmts' ) || '[]' ) list.unshift (comment) console .log (list) localStorage .setItem ('cmts' ,JSON .stringify (list)) this .$emit('func' ) this .user = this .content ='' } } } var vm = new Vue ({ el :'#app' , data :{ list :[ {id :Date .now (),user :'李白' ,content :'大河之水天上来,奔流到海不复回' } ] }, methods :{ loadComments :function ( ){ var list = JSON .parse (localStorage .getItem ('cmts' ) || '[]' ) this .list = list } }, filters :{ dateFormat :function (dataStr,pattern ){ var dt = new Date (dataStr) var y = dt.getFullYear () var m = (dt.getMonth ()+1 ).toString ().padStart (2 ,'0' ) var d = (dt.getDate ()).toString ().padStart (2 ,'0' ) if (pattern && pattern.toLowerCase ()==='yyyy-mm-dd' ) { return `${y} -${m} -${d} ` } else { var hh = (dt.getHours ()).toString ().padStart (2 ,'0' ) var mm = (dt.getMinutes ()).toString ().padStart (2 ,'0' ) var ss = (dt.getSeconds ()).toString ().padStart (2 ,'0' ) return `${y} -${m} -${d} ${hh} :${mm} :${ss} ` } } }, components :{ 'cmt-box' :commentBox }, directives :{ 'focus' :{ bind :function (el ){ }, inserted :function (el ){ el.focus () }, update : function ( ){ } } }, created ( ){ this .loadComments () } })
演示链接 演示地址
使用ref获取DOM元素和组件引用 1 2 3 4 5 6 <div id ="app" > <input type ="button" name ="" value ="获取元素" @click ="getElement" > <h1 id ="myh3" ref ="myh3" > 我是需要调用的DOM元素</h1 > <hr > <login ref ="mylogin" > </login > </div >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 var login = { template :'<h1>登录组件</h1>' , data ( ){ return { msg :'son msg' } }, methods :{ show :function ( ){ console .log ('调用了子组件的show 方法' ) } } } var vm = new Vue ({ el :'#app' , data :{ }, methods :{ getElement :function ( ){ console .log (this .$refs .myh3 .innerText ) console .log (this .$refs .mylogin .msg ) this .$refs .mylogin .show () } }, components :{ login } })
演示 ref获取dom+ref获取组件方法,data