1 导入vue: 2 <script src="vue.min.js"></script> 3 创建vm实例 4 var vm=new Vue({ 5 el:'#app',//指定要控制的元素 6 data:{}, 7 methods:{} 8 }) 9 在id为app的div里
一、指令学习
1.v-cloak、v-text、v-bind、v-html、v-on
1 <div id="app"> 2 <h2>1.v-cloak、-text、-bind、-HTML、-on指令</h2> 3 <p>{{msg}}</p> 4 <!--使用 v-cloak 能够解决 插值表达式闪烁的问题 ,还能对值拼接--> 5 <p v-cloak>v-cloak:+++++++++++{{msg}}----------</p> 6 <!--使用v-text没有闪烁问题,覆盖元素中的原本内容,--> 7 <p v-text="msg">v-text:======================</p> 8 9 <!--使用v-html:将msg解析为HTML格式,也会覆盖原本内容--> 10 <div>{{msg2}}</div> 11 <div v-text="msg2"></div> 12 <div v-html="msg2">111111</div> 13 14 <!--使用v-bind:vue提供的用于绑定属性的指令 简写为:,还可以拼接字符--> 15 <input type="button" value="v-bind指令" v-bind:title="mytitle +',我是拼接的'"> 16 17 <!--使用v-on:绑定事件机制 简写为@--> 18 <input type="button" value="v-on指令" v-on:click="show"> 19 <input type="button" value="v-on指令:mouseover" @mouseover="show2"> 20 <br><br><br> 21 </div>
2.事件修饰符 :.stop .prevent .capture .self .once
1 <h2>2.事件修饰符</h2> 2 <div class="inner" @click="divHandler"> 3 4 <input type="button" value="戳它" @click.once="btnHandler"><br> 5 <!--默认:先btn的后div的--> 6 <!-- 内层加入.stop后,没有触发外层div --> 7 8 <a href="http://www.baidu.com" @click.prevent="linkclick">百度一下,你就知道</a> 9 <!-- 链接加入.prevent,阻止默认行为 --> 10 11 <!-- 外层使用.capture, 捕获机制->顺序为:先div后btn .capture加在外层--> 12 13 <!-- 外层使用.self,实现只有点击当前元素才会触发事件处理函数 --> 14 15 <!-- 使用.once,当前元素只触发一次 --> 16 17 </div> 18 <div class="outer" @click="div2Handler"> 19 <div class="inner" @click.self="divHandler"> 20 <input type="button" value="戳一下" @click="btnHandler"> 21 <!-- 默认顺序:btn inner outer --> 22 <!-- .self只会阻止自己身上的冒泡,btn outer --> 23 </div> 24 </div>
3.v-model实现数据双向绑定
1 <h2>3.v-model实现表单数据双向绑定</h3> 2 <!-- v-bind:只能实现数据的单向绑定,从M自动绑定到V --> 3 <!-- <input type="text" v-bind:value="msg3"> --> 4 <input type="text" v-bind:value="msg3" v-model:value="msg3"> 5 <!-- v-model :实现表单元素和model中数据的双向绑定,只能运用在表单元素中 6 input(radio,text,address,email...)select、CheckBox、textarea等 7 -->
4.v-for 循环遍历与迭代数字
1 <h2>4.v-for循环遍历普通数组与对象</h3> 2 <!-- <p>{{list[0]}}</p><p>{{list[2]}}</p><p>{{list[3]}}</p> --> 3 <!-- <p v-for="item in list">{{item}}</p> --> 4 <!-- 注意:空格 --> 5 <p v-for="(user,i) in list">Id:{{user.id}} --- 名字:{{user.name}} --- 索引:{{i}}</p> 6 <p v-for="(val,key) in user">值:{{val}} --- 键:{{key}} </p> 7 <p v-for="(val,key,i) in user">值:{{val}} --- 键:{{key}} --- 索引:{{i}}</p> 8 9 <h3>4.1 v-for迭代数字</h3> 10 <!-- 从1开始迭代 --> 11 <p v-for="count in 4">这是第{{count}}次循环</p> 12 <!-- 2.20+以后, --> 13 <h4>魔道祖师</h4> 14 <div> 15 <label> 16 Id: 17 <input type="text" v-model="id"> 18 </label> 19 <label > 20 Name: 22 <input type="text" v-model="name"> 23 </label> 24 25 <input type="button" value="添加" @click="add"> 26 27 </div> 28 <!-- 注意:v-for循环的时候,key属性只能使用number获取string --> 29 <!-- 注意:key 使用时,必须使用v-bind属性绑定的的形式 --> 30 <!-- 在组件中,使用v-for循环时,或者在一些特殊情况中,如果v-for有问题,得为它指定唯一的字符串/数字 类型 :key值 --> 31 <p v-for="item in list1" :key="item.id"> 32 <input type="checkbox" > 33 {{item.id}} --- {{item.name}} 34 </p>
5.v-show与v-if
1 <h2>5. v-show与v-if</h3> 2 3 <input type="button" @click="flag=!flag" value="toggle"> 4 <!-- v-if:每次都会重新删除或创建元素 , 5 有较高的切换性能消耗,频繁切换情况不要用,用v-show--> 6 <h3 v-if="flag">这是v-if控制的元素</h3> 7 <!-- v-show:每次不会重新进行DOM的删除和创建操作,只是切换了元素的display:none样式 , 8 有较高的初始渲染消耗,如果元素可能永远不会被显示出来被用户看到,用v-if--> 9 <h3 v-show="flag">这是v-show控制的元素</h3>
6.键盘修饰符
1 <h2>6. 键值修饰符</h2> 2 <!-- 使用时为:@keyup.xxx="function" --> 3 <li>.enter</li> 4 <li>.tab</li> 5 <li>.delete</li> 6 <li>.esc</li> 7 <li>.space</li> 8 <li>.up</li> 9 <li>.down</li> 10 <li>.right</li> 11 <li>.left</li> 12 <li>.keycode(数字)</li>
<!-- 测试自定义键盘修饰符 -->
<input type="text" v-model="name" @keyup.f2="add">
// 自定义全局修饰符
Vue.config.keyCodes.f2=113;
二、vue中的样式
1.内联样式-style
1 <div id="app"> 2 <!-- 对象就是无序的键值对的集合, 对象中有横线的不能省略单引号 --> 3 <h1 :style="{color:'red','font-weight':'200'}">这是一个h1</h1> 4 <h1 :style="styleObj">这是一个h1</h1> 5 <h1 :style=[styleObj,styleObj2]>这是一个h1</h1> 6 7 </div> 8 9 <script> 10 var vm=new Vue({ 11 el:'#app', 12 data:{ 13 styleObj:{color:'red','font-weight':'200'}, 14 styleObj2:{'font-style':'italic'} 15 }, 16 methods:{} 17 }) 18 </script>
2.class样式
1 <head><style> 2 .red{ 3 color: red; 4 } 5 .thin{ 6 font-weight: 200; 7 } 8 .italic{ 9 font-style: italic; 10 } 11 .active{ 12 letter-spacing: 0.5em; 13 } 14 .change{ 15 color:green; 16 } 17 </style> 18 </head> 19 <body> 20 <div id="app"> 21 <!-- 以前的使用方式 --> 22 <h1 class="red thin">大大无法想象</h1> 23 <!-- 第一种使用方式,直接传递一个数组,注意:这里的class得用v-bind绑定 --> 24 <h1 :class="['thin','italic']">很大,无法想象!!!</h1> 25 <!-- 在数组中使用三元表达式 --> 26 <h1 :class="['thin','italic',!flag?'active':'']">很大!!!</h1> 27 <!-- 在数组中使用对象来代替三元表达式提高可读性 --> 28 <h1 :class="['thin','italic',{'change':flag}]">很大!!!</h1> 29 <!-- 对象的属性是类名,可带引号也可不带,属性的值是一个标识符 --> 30 <!-- <h1 :class="{ red:true,thin:true,italic:false}">很大!!!</h1> --> 31 <h1 :class="classObj">很大!!!</h1> 32 33 </div> 34 35 <script> 36 var vm=new Vue({ 37 el:'#app', 38 data:{ 39 flag:true, 40 classObj:{ red:false,thin:true,italic:false,change:true} 41 }, 42 methds:{} 43 }) 44 </script>
三、过滤器filter
过滤器的定义语法:
Vue.filter('过滤器的名称',function(){});// 过滤器中的function第一个参数,永远都是过滤器(管道符前面)传递过来的数据
1 <div id="app"> 4 <p v-html='msg'></p> 5 6 <!-- <p>{{ msg | msgFormat }}</p> --> 7 <!-- <p>{{ msg | msgFormat(' *****') }}</p> --> 8 <p>{{ msg | msgFormat('夷陵老祖',' *****','魏无羡') }}</p> 9 </div> 10 <script> 11 12 //定义一个全局过滤器:msgFormat 13 Vue.filter('msgFormat',function(msg,arg,arg2,arg3){ 14 //字符串的 replace方法,第一个参数,除了可写一个字符串外,还可以定义正则 15 return msg.replace(/<br>/g,arg+arg2+arg3);//将换行符换成三个参数相连的样子 16 }); 17 18 var vm=new Vue({ 19 el:'#app', 20 data:{ 21 msg:'魔道祖师:'+'<br>'+'<br>' 22 }, 23 methods:{}, 24 }) 25 </script>
四、vue-resource
1 <head> 2 <meta charset="UTF-8"> 3 <title>Document</title> 4 <script src="../lib/vue.js"></script> 5 <!--1. 注意:vue-resource依赖于Vue,注意先后顺序 --> 6 <!-- this.$http. --> 7 <script src="../lib/vue-resource.js"></script> 8 </head> 9 <body> 10 <div id="app"> 11 <input type="button" value="Get请求" @click="getInfo"> 12 <input type="button" value="Post请求" @click="postInfo"> 13 <input type="button" value="Jsonp请求" @click="jsonpInfo"> 14 </div> 15 <script> 16 var vm=new Vue({ 17 el:'#app', 18 data:{ 19 20 }, 21 methods:{ 22 getInfo(){//发起get请求 23 // 当发起get请求之后,通过 .then来设置成功的回调函数 24 this.$http.get('http://www.liulongbin.top:3005/api/getlunbo').then(function(result){ 25 console.log(result) 26 // 通过 result.body 拿到服务器返回的数据 27 }); 28 // this.$http.jsonp("http://vue.studyit.io/api/getlunbo").then(result => { 29 // console.log(result.body); 30 // }); 31 }, 32 postInfo(){ 33 // 手动发起的表单请求默认没有表单格式,有的服务器处理不了 34 // 通过post的第三个参数,设置,提交内容为普通表单数据格式 35 this.$http.post('http://www.liulongbin.top:3005/api/post',{},{emulateJSON:true}).then(result=>{ 36 console.log(result.body) 37 }) 38 }, 39 jsonpInfo(){//发起jsonp请求 40 this.$http.jsonp('http://www.liulongbin.top:3005/api/jsonp').then(result=>{ 41 console.log(result.body) 42 }) 43 } 44 } 45 }) 46 </script>
六、生命周期函数
beforeCreate()、created()、beforeMount()、mounted()、beforeUpdate()
1 <div id="app"> 2 <input type="button" value="修改msg" @click="msg='NO'"> 3 <h3 id="h3">{{msg}}</h3> 4 </div> 5 6 <script> 7 8 var vm=new Vue({ 9 el:'#app', 10 data:{ 11 msg:'----ok', 12 }, 13 methods:{ 14 show(){ 15 console.log('执行了show方法') 16 } 17 }, 18 beforeCreate() {//遇到第一个生命周期函数,表示示例被完全创建出来之前会执行它 19 console.log('beforeCreate:'+this.msg) 20 // this.show() is not a function 21 // 在beforeCreate()生命周期函数执行的时候,data 和 methods 中的数据都还没有被初始化 22 }, 23 created() {//遇到的第二个生命周期函数 24 console.log('created:'+this.msg), 25 this.show() 26 // 在created函数中,data 和 methods都已被初始化好了 27 // 如果要调用methods里的方法,最早在created里执行 28 29 }, 30 beforeMount() {//遇到的第三个生命周期函数,表示模板已经在内存中编辑完成了,但尚未把 模板 渲染到页面中 31 var a= document.getElementById("h3").innerText 32 console.log('beforeMount:'+a) 33 // 在beforeMount函数执行的时候,页面中的元素还没有被真正替换过来,只有之前写的一些模板字符串 34 }, 35 mounted() {//遇到的第四个生命周期函数,表示内存中的模板已经真实的挂载到页面中,用户已经可以看到 渲染好的页面了 36 var a= document.getElementById("h3").innerText 37 console.log('mounted:'+a) 38 // 注意:mounted 是实例创建期间最后一个生命周期函数,当执行完mounted就表示,实例已经完全被创建好了, 39 // 此时如果没有其他操作的话 这个实例静静的躺在内存中 40 }, 41 // 接下来是运行中的两个事件 42 beforeUpdate() {//这时候 表示 我们的界面还没被更新 43 console.log('beforeUpdate:界面上元素的内容'+document.getElementById('h3').innerText)//无效果, 44 //加button试试 --可以看出来了 45 console.log('data 中的 msg是'+this.msg) 46 // 结论: 47 // 当执行beforeUpdate的时候,页面中显示的数据还是旧的,此时 data数据是最新的,页面尚未和data保持同步 48 }, 49 }) 50 //结果:beforeCreate:undefined
created:----ok
执行了show方法
beforeMount:{{msg}}
mounted:----ok
点击按钮之后打印新增:
beforeUpdate:界面上元素的内容----ok
data 中的 msg是NO 51 </script>
七、动画
1.不使用动画
1 <div id="app"> 2 <input type="button"value="toogle" @click="flag=!flag"> 3 <!-- 需求:点击按钮,让h3显示,再次点击,隐藏 --> 4 <h3 v-if="flag">春风吹不倒,我的杨柳腰</h3> 5 </div> 6 <script> 7 var vm=new Vue({ 8 el:'#app', 9 data:{flag:false}, 10 }) 11 </script>
2.使用过渡类名实现
1 <!-- 自定义两组样式,来控制transition内部的元素实现动画 --> 2 <style> 3 .v-enter, 4 /* .vue-enter【这是一个时间点】是进入之前元素的起始状态,此时还没有开始进入 */ 5 .v-leave-to{ 6 /* 是动画离开之后,离开的终止状态,此时,元素动画已经结束了 */ 7 opacity: 0; 8 transform: translateX(80px); 9 } 10 11 .v-enter-active, 12 /* [入场动画的时间段]*/ 13 .v-leave-active{ 14 /* [离场动画的时间段] */ 15 transition: all 0.4s ease; 16 } 17 </style> 18 </head> 19 <body> 20 <div id="app"> 21 <input type="button"value="toogle" @click="flag=!flag"> 22 <!-- 需求:点击按钮,让h3显示,再次点击,隐藏 --> 23 <transition> 24 <h3 v-if="flag">春风吹不倒,我的杨柳腰</h3> 25 </transition> 26 27 <!-- 1.使用transition元素,把需要被动控制的元素,包裹起来 --> 28 <!-- transition 是Vue官方提供的 --> 29 </div>
3.使用第三方类:animate.css
1 <link rel="stylesheet" href="../lib/animate.css"> 2 <!-- 入场用bounceIn 离场bounceOut --> 3 </head> 4 <body> 5 <div id="app"> 6 <input type="button"value="toogle" @click="flag=!flag"> 7 8 <!-- 使用:duration="毫秒值"来设置入场离场时的动画时长 --> 9 <transition enter-active-class="bounceIn" leave-active-class="bounceOut":duration="400"> 10 <h3 v-if="flag">春风吹不倒,我的杨柳腰</h3> 11 </transition> 12 13 <hr> 14 <input type="button"value="toogle1" @click="flag1=!flag1"> 15 <!-- 使用:duration="{enter:,leave:}"设置出入场时间 --> 16 <transition 17 enter-active-class="bounceIn" 18 leave-active-class="bounceOut" 19 :duration="{enter:00,leave:400}"> 20 <h3 v-if="flag1">春风吹不倒,我的杨柳腰</h3> 21 </transition>
4.修改v-前缀
1 <style> 2 .my-enter, 3 .my-leave-to{ 4 opacity: 0; 5 transform: translatey(80px); 6 } 7 .my-enter-active, 8 .my-leave-active{ 9 transition: all 0.4s ease; 10 } 11 </style> 12 </head> 13 <body> 14 <div id="app"> 15 <input type="button"value="toogle2" @click="flag2=!flag2"> 16 <transition name="my"> 17 <h4 v-if="flag2">月儿在手中开呀怀儿笑,云儿在那眼前睡得早</h4> 18 </transition> 19 </div>
5.使用钩子函数模拟小球动画
1 <style> 2 .ball{ 3 width:15px; 4 height:15px; 5 border-radius: 50%; 6 background-color:red; 7 } 8 </style> 9 </head> 10 <body> 11 <div id="app"> 12 <input type="button" value="快到碗里来" @click="flag=!flag"> 13 14 <transition 15 @before-enter="beforeEnter" 16 @enter="enter" 17 @after-enter="afterEnter"> 18 <div class="ball" v-show="flag"></div> 19 </transition> 20 21 </div> 22 <script> 23 24 var vm=new Vue({ 25 el:'#app', 26 data:{ 27 flag:false, 28 }, 29 methods:{ 30 // 注意:动画钩子函数的第一个参数:el表示 要执行的动画的那个DOM元素,是个原生JS DOM对象 31 // el是通过docum.getElementByID(''),方法获取到的原生JS对象 32 beforeEnter(el){//表示动画入场之前,此时动画尚未开始, 33 // 可以在这里设置元素开始动画开始之前的起始样式 34 el.style.transform="translate(0,0)"//设置小球开始动画之前的起始位置 35 }, 36 enter(el,done){ 37 //这句话没有实际作用,不写没动画效果 38 el.offsetWidth//强制动画刷新 39 // 表示动画开始之后的样式,这里可以设置小球完成动画之后的结束状态 40 el.style.transform="translate(150px,450px)" 41 el.style.transition='all 1s ease' 42 43 // 立马消失?这里的done就是afterEnter函数,即,done为afterEnter函数的引用 44 done() 45 }, 46 afterEnter(el){//动画完成之后 47 // el.style.transform="translate()" 48 // console.log("执行完毕!") 49 this.flag=!this.flag 50 } 51 }, 52 }) 53 </script>
6.列表的动画
1 <script src="../lib/vue.js"></script> 2 <link rel="stylesheet" href="../lib/animate.css"> 3 <style> 4 li{ 5 border:1px solid #999; 6 margin: 5px; 7 line-height: 35px; 8 padding-left: 5px; 9 font-size: 12px; 10 11 width:100% 12 /* 解决设置absolute后,宽度的变化 */ 13 } 14 li:hover{ 15 background-color:pink; 16 transition: all 0.4s ease; 17 /* 悬停时,背景过渡 */ 18 } 19 /* 固定组合,4个,实现进入时渐变,离开时渐变 */ 20 .v-enter, 21 .v-leave-to{ 22 opacity: 0; 23 transform: translateY(80px); 24 } 25 .v-enter-active, 26 .v-leave-active{ 27 transition: all 1s ease; 28 } 29 30 /* 自编样式 前一个元素离开时,让剩下的渐变移动 ,与.v-leave-active:position为absolute一起使用*/ 31 .v-move{ 32 transition:all 1s ease; 33 } 34 /* absolute弊端:元素离开时宽度后发生变化, 35 解决:设置其宽为100%即可 */ 36 .v-leave-active{ 37 position: absolute; 38 } 39 </style> 40 </head> 41 <body> 42 <div id="app"> 43 <div> 44 <label for=""> 45 Id: 46 <input type="text" v-model="id"> 47 </label> 48 <label for=""> 49 Name: 50 <input type="text" v-model="name"> 51 </label> 52 53 <input type="button" value="添加" @click="add"> 54 </div> 55 <!-- <ul> --> 56 <!-- 在使用列表过渡的时候,如果需要过渡的元素,是通过v-for循环渲染出来的,不能使用transition包裹 57 需要使用transitionGroup --> 58 <!-- 给 transition-group添加appear,实现页面刚展示出来的时候的入场动画 --> 59 <!-- tag标签,指明将transition渲染为什么标签,不指定默认渲染为span --> 60 <transition-group appear tag="ul"> 61 <!-- 要为v-for循环创建的元素设置动画,必须为每个元素设置 :key属性 --> 62 <!-- <li v-for="item in list" :key="item.id" @click="del(i)"> --> 63 <li v-for="(item,i) in list" :key="item.id" @click="del(i)"> 64 <!-- 移除:@click 增加i元素--> 65 {{item.id}} ---{{item.name}} 66 </li> 67 </transition-group> 68 <!-- </ul> --> 69 </div> 70 71 <script> 72 var vm=new Vue({ 73 el:'#app', 74 data:{ 75 id:'', 76 name:'', 77 list:[ 78 {id:1,name:'魏无羡'}, 79 {id:2,name:'蓝忘机'}, 80 {id:3,name:'江澄'}, 81 {id:4,name:'金子轩'}, 83 ] 84 }, 85 methods:{ 86 add(){ 87 this.list.push({id:this.id,name:this.name}) 88 }, 89 del(i){ 90 this.list.splice(i,1) 91 } 92 } 94 }) 95 </script>
八、组件
1,组件之data和method
1 <div id="app"> 2 <mycom1></mycom1> 3 </div> 4 5 <script> 6 // 1.组件可以有自己的data数据 7 // 2.组件的 data 和实例的 data 有点不一样,实例中的data可以为一个对象,但是组件中的必须是一个方法 8 // 3.组件中的 data 除了必须为一个方法外,这个方法内部,还必须返回一个对象才行 9 // 4.组件中的 data 数据,使用方式和实例中的 data 使用方式完全一样 10 Vue.component('mycom1',{ 11 template:'<h3>这是全局组件</h3>', 12 data:function(){ 13 return{ 14 msg:'这是组件中的data定义的数据' 15 } 16 } 17 })
1 //组件的data必须是一个function 2 <div id="app"> 3 <count></count> 4 <hr> 5 <count></count> 6 <hr> 7 <count></count> 8 </div> 9 <template id="tmpl"> 10 <div> 11 <input type="button" @click="increment" value="加"> 12 <h3>{{count}}</h3> 13 </div> 14 </template> 15 16 <script> 17 var dataObj={count:0} 18 //计数器组件,身上有个按钮,每当点击按钮,让 data 中的 count 值 + 1 19 Vue.component('count',{ 20 template:'#tmpl', 21 // data:function(){ //data是一个function 22 data(){ 23 // return dataObj //使用多个组件时,数据一样 24 return {count:0} //使用多个组件时,不关联 25 }, 26 methods:{ //methods是一个对象 27 increment(){ 28 this.count+=1 29 } 30 } 31 })
</script>
2.组件之创建组件的方式 - 前4个外部定义
1)使用Vue.extend:
1 <div id="app"> 2 <!-- 如果要使用组件,直接把组件名称,以HTML标签的形式引入页面即可 --> 3 <!-- <myCom1></myCom1> 错误的--> 5 <my-com1></my-com1> //1 6 <mycom1></mycom1> //2 7 </div> 8 // 1.分两步 9 //1.1 使用vue.extend来创建全局vue组件 10 var com1= Vue.extend({ 11 template:'<h3>这是使用Vue.extend 创建的组件</h3>'//通过template属性,指定了组件要展示的HTML结构 12 }) 13 // 1.2 使用Vue.components('组件的名称',创建出来的组件模板对象) 14 Vue.component('myCom1',com1) 15 // 使用Vue.component定义全局组件时,若使用驼峰,则引用时大写改小写两单词之间用“——”链接 16 // 否则,直接写 17 18 // 2.一步解决 19 Vue.component('mycom1',Vue.extend({ 20 template:'<h3>外部定义一:这是Vue.component里Vue.extend创建的组件</h3>' 21 }))
定义组件的时候,全局:Vue.component('组件名称',{})
组件模板几种方式的创建,通过Vue.component吧组件模板电对象,注册为一个全局的vue组件,同时为这个组件起来一个名称,
在页面以标签显示 引入组件
2)Vue.component('组件名称',{})
1 // 第二种 2 Vue.component('mycom2',{ 3 // 注意:不论是哪种方式创建出来的组件,组件的template属性的模板内容,必须有且只有一个唯一的根元素 4 template:'<div><h3>外部定义二、这是使用Vue.component 创建的组件</h3> <span> 我是第二种方式里的其他标签</span></div>' 5 })
3)Vue.component('组件名称',{tamplate:'#tmpl'})
1 <!-- 在被控制的#App外面 使用template元素定义组件的模板结构 依旧遵循唯一根元素--> 2 <template id="temp1"> 3 <div> 4 <h3>外部定义三:这是通过 template 元素,在外部定义的组件结构,这个方式,有代码的只能提示和高亮</h3> 5 <h4>好用,不错</h4> 6 </div> 7 </template> 8 9 // 第三种 10 Vue.component('mycom3',{ 11 template:'#temp1' 12 })
4) Vue.component('组件名称',对象)
1 // 第四种 2 var abc={ //通过对象 字面量的形式,定义了一个组件模板对象 3 template:'<h3>外包定义四、这是用对象承接了template组件,</h3>' 4 } 5 Vue.component('mycom4',abc)
5)内部定义
1 // 内部定义第二种 2 var register={ 3 template:'<h3>内部定义二:这是用对象承接的template</h3>' 4 } 5 var vm2=new Vue({ 6 el:'#app2', 7 data:{}, 8 methods:{}, 9 filters:{}, 10 directives:{}, 11 components:{//定义内部私有组件 12 //1.内部定义第一种 13 login:{ 14 // template:'<h3>这是私有的 login 组件</h3>' 15 template:'#templ2' 16 }, 17 // '组件名称':组件模板 18 // 2.1内部定义第二种 19 // register 20 // 2.2内部定义第二种 21 'register':register//同上一个作用 22 }, 23 }) 24 </script>
3.组件之ref获取DOM元素和组件引用
1 <div id="app"> 2 <input type="button" value="获取元素" @click="getElement" ref="mybtn"> 3 <h3 id="myh3" ref="myh3">纵然与世无争 道不同义在心中,怎奈侠肝义胆,却成一场空</h3> 4 <hr> 5 <login ref="mylogin"></login> 6 </div> 7 <script> 8 // 登录组件 9 var login={ 10 template:'<input type="button" value="登录组件">', 11 data(){ 12 return{ 13 msg:'son msg' 14 } 15 }, 16 methods: { 17 show(){ 18 console.log("调用了子组件的方法") 19 } 20 }, 21 } 22 var vm=new Vue({ 23 el:'#app', 24 methods:{ 25 getElement(){ 26 // console.log(document.getElementById('myh3')) //值为h3 27 // console.log(document.getElementById('myh3').innerHTML)//值为h3的内容
// console.log(document.getElementById('myh3').innerText)//值为h3的内容 28 // ref :reference引用 获取DOM结点 29 console.log(this.$refs.myh3.innerText) //myh3的内容 30 console.log(this.$refs.mybtn.innerHTML+'我是button的') //我是button的 31 console.log(this.$refs.mylogin.msg) //son msg 32 console.log(this.$refs.mylogin.show()) //结果:调用了子组件的方法->执行了show方法 33 // 结果 undefined -> 打印语句里调用的方法没返回值 34 } 35 }, 36 components:{ 37 login 38 } 39 }) 40 </script>
4.组件之组件切换
1 <h3>第一种切换方式</h3> 2 <a href="" @click.prevent="flag=true">登录</a> 3 <a href="" @click.prevent="flag=false">注册</a> 4 5 <login v-if="flag"></login> 6 <register v-else="flag"></register> 7 <hr>
1 <h3>第二种切换方式</h3> 2 <a href="" @click.prevent="comName='login'">登录</a> 3 <a href="" @click.prevent="comName='register'">注册</a> 4 5 <!-- vue提供了component,来展示对应名称的组件 --> 6 <!-- component是一个占位符,:is属性,指定要展示的组件的名称 --> 7 <!-- <component :is="componentId"></component> --> 8 <component :is="comName"></component> 9 10 <!-- 总结:当前学习的vue提供的标签: 11 component、template、transition、transition-group --> 12 <hr>
var vm=new Vue({
el:'#app',
data:{
flag:false,
comName:'register',//当前 component 中的 :is 绑定的组件的名称
},
methods:{}
})
1 <h3>实现切换动画</h3> 2 <a href="" @click.prevent="comName='login'">登录</a> 3 <a href="" @click.prevent="comName='register'">注册</a> 4 5 <!--通过 mode属性:out-in 设置组件切换时候的模式--> 6 <transition mode="out-in"> 7 <component :is="comName"></component> 8 </transition>
5.组件之父组件向子组件传值
1 <div id="app"> 2 <!-- 值:消息,props与data --> 3 <!--父组件可以在引用子组件的时候,通过属性绑定的形式(v-bind)的形式,把需要传递给子组件的数据,传过去 --> 4 <com1 v-bind:parentmsg="msg"></com1> 5 <div>
1 var vm=new Vue({ 2 el:'#app', 3 data:{ 4 msg:'123 - 父组件中的数据', 5 datamsgFromson:null, 6 }, 7 methods:{ 8 show(data){ 9 console.log('调用了父组件身上的show方法 --- '+data) 10 this.datamsgFromson=data 11 }, 12 }, 13 components:{ 14 com1:{ // 子组件中默认无法访问父组件中,data 上的数据、methods 里的方法,如下 15 // template:'<h3>这是子组件 ---{{msg}}</h3>' //获取不到msg 16 template:'<h3 @click="change">这是子组件 ---{{parentmsg}}</h3>',//获取不到parentmsg 17 18 props:['parentmsg'],//把父组件传递过来的parentmsg属性,现在props数组中,定义一下,才能使用 19 // 注意:组件中的所有 props 中的数据,都是通过父组件传递给了子组件 20 // props中的数据都是只读的, 21 22 data(){ //子组件中的data数据并不是通过父组件传递的,而是自己私有的 23 // data里的数据都是可读可写的 24 return { 25 title:'666', 26 content:'qqq', 27 } 28 }, 29 filters:{}, 30 directives:{}, 31 components:{}, 32 methods: { 33 change(){ //给template里的标签添加绑定事件 34 this.parentmsg="被修改了" 35 } 36 }, 37 },
com2:com2 //传递方法
38 } 39 }) 40 </script>
1 <div id="app"> 2 <!-- 值:methods --> 3 <!-- 父组件向子组件传递方法,使用的是事件绑定机制(v-on)当自定义了一个事件属性之后,子组件就能够通过某些方式来调用 方法 --> 4 <!-- <com2 v-on:fun="show"></com2> --> 5 <!-- 传参1 --> 6 <!-- <com2 @fun="show('哈哈')"></com2> --> 7 <!-- 未传参1 --> 8 <com2 @fun="show"></com2> 9 </div>
1 <template id="tmpl2"> 2 <div> 3 <h3>这是 子组件2</h3> 4 <input type="button"value="子组件中的按钮,点击触发父组件传递过来的方法" @click="myclick"> 5 </div> 6 </template> 7 8 9 <script> 10 //另一种 11 var com2={ 12 template:'#tmpl2', 13 data(){ 14 return{ 15 sonmsg:{name:'小头儿子',age:6} 16 } 17 }, 18 19 methods: { 20 myclick(){ 21 // console.log('1111') 22 // 当点击子组件按钮时,如何拿到父组件传递过来的func方法,并调用 23 //未传参2 24 // this.$emit('fun') 25 // 传参2 26 this.$emit('fun','哈哈') 27 // emit:英文原义- 触发、调用、发射 28 this.$emit('fun',this.sonmsg) 29 } 30 }, 31 }
九、路由
1.路由的基本使用
<!-- 1.安装路由模块 -->
<script src="../lib/vue-router.js"></script>
1 // 2. 创建一路由对象,当导入vue-router包后,在window全局对象中,就有了一个路由的构造函数,叫做VueRouter 2 //在new 路由对象时,可以为构造函数,传递一个配置对象 3 var routerObj=new VueRouter({ 4 // route //这个配置对象中的route表示 【路由配置规则】 5 routes:[ //路由配置规则 6 // 每个路由规则都是一个对象,这个对象身上有两个必须的属性, 7 // 属性1:path - 监听那个路由连接地址 8 // 属性2:component - 表示,如果路由是前面匹配到的path,则展示component属性对应的那个组件, 9 // 值为组件模板对象,不是引用名称 10 {path:'/',redirect:'/login'}, //这里的 redirect 完全是两码事 11 {path:'/login',component:login}, 12 {path:'/register',component:register} 14 ],
})
// 此处login为组件的模板对象
var login={
template:'<h3>登录组件</h3>'
}
//此处login为组件名称,不是对象,不能放到路由里,应选择上面的
Vue.component('login',{
template:'<h3>登录组件yaya</h3>'
});
var register={
template:'<h3>注册组件</h3>'
}
<div id="app">
<!-- router-link:默认渲染为a标签 -->
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<!-- 这是vue-router 提供的元素,专门用来当做占位符的,将来路由规则、匹配到的组件,就会展示到这个router-view中
可视router-view为占位符 -->
<router-view></router-view>
</div>
1 var vm=new Vue({ 2 el:'#app', 3 data:{}, 4 methods:{}, 5 router:routerObj //将路由规则对象注册到vm实例上,用来监听URL变化,然后展示组件 6 7 })
2.路由之修改样式:
1 <transition mode="out-in"> 2 <router-view></router-view> 3 </transition>
一般样式如下:
.v-enter,
.v-leave-to{
opacity: 0;
transform:translateX(150px);
}
.v-enter-active,
.v-leave-active{
transition: all 0.5s ease;
}
/* 修改样式第一种:修改自带的类样式 */
.router-link-active{
color:red;
font-weight: 800;
/* font-style: italic; */
font-size: 20px;
text-decoration: underline;
background-color: green;
}
/* 修改样式第二种,自定义样式,传给linkActiveClass */
.myactive{
color:green;
font-weight: 400;
background-color: pink;
}
//增加linkActiveClass如下:
var routerObj=new VueRouter({
routes:[ //路由配置规则
{path:'/',redirect:'/login'}, //这里的 redirect 完全是两码事
{path:'/login',component:login},
{path:'/register',component:register}
],
// 修改样式第二种:通过linkActiveClass设置样式
linkActiveClass:'myactive'
})
3.路由的嵌套
1 <div id="app"> 2 <router-link to="/account">Account</router-link> 3 <router-view></router-view> 4 </div> 5 6 <template id="tmpl"> 7 <div> 8 <h3>这是Account组件</h3> 9 <router-link to="/account/login">登录</router-link> 10 <router-link to="/account/register">注册</router-link> 11 12 <!-- 放置子路由组件的位置 --> 13 <router-view></router-view> 14 </div> 15 </template> 16 17 <script> 18 // 组件的模板对象 19 var account={ 20 template:'#tmpl' 21 } 22 var register={ 23 template:'<h4>注册组件</h4>' 24 } 25 var login={ 26 template:'<h4>登录组件</h4>' 27 } 28 var router=new VueRouter({ 29 routes:[ 30 { path:'/account', 31 component: account, 32 children:[ //children:子路由,子路由的path前面不用带斜线,否则永远以根路径开始请求,不方便用户立即URL地址 33 {path:'login',component:login}, 34 {path:'register',component:register} 35 ], 36 }, 37 ] 38 }) 39 40 var vm=new Vue({ 41 el:'#app', 42 data:{}, 43 methods:{}, 44 router, 45 }) 46 </script>
4.路由之使用命名规则实现经典布局
1 <style> 2 .header{ 3 background-color: orange; 4 height:80px; 5 } 6 .left{ 7 background-color:lightgreen; 8 flex:2 9 } 10 .main{ 11 background-color: lightpink; 12 flex:8; 13 } 14 .container{ 15 display: flex; 16 height: 600px; 17 } 18 h2{ 19 margin:0; 20 /* padding:0; */ 21 font-size: 16px; 22 } 23 html,body{ 24 margin:0; 25 padding:0; 26 } 27 </style> 28 </head> 29 <body> 30 <div id="app"> 31 <router-view></router-view> 32 <div class="container"> 33 <router-view name='left'></router-view> 34 <router-view name="main"></router-view> 35 </div> 36 </div> 37 38 <script> 39 // 模板 40 var header={ 41 template:'<h2 class="header">Header头部区</h2>' 42 } 43 var leftBox={ 44 template:'<h2 class="left">侧边栏区域</h2>' 45 } 46 var mainBox={ 47 template:'<h2 class="main">主题、体区域</h2>' 48 } 49 50 // 创建路由对象 51 var router = new VueRouter({ 52 routes:[ 53 { 54 // {path:'/left',component:leftBox}, 55 // {path:'/main',component:mainBox} 56 path:'/',components:{ 57 'default':header, 58 'left':leftBox, 59 'main':mainBox 60 } 61 }, 62 ] 63 }) 64 var vm=new Vue({ 65 el:'#app', 66 data:{}, 67 methods:{}, 68 router 69 }) 70 </script>
十、vuex
1 //项目入口 ---main.js文件 2 3 // console.log('ok') 4 import Vue from '../node_modules/vue/dist/vue.js' 5 // 1.运行cnpm i vue-x -S 6 // 2。导入vuex 7 import Vuex from "vuex" 8 // 3.注册vuex到vue中 9 Vue.use(Vuex) 10 // 4.new Vuex.Store()实例,得到一个数据仓储对象 11 var store=new Vuex.Store({ 12 state:{ 13 count:0 14 // 如果在组件中想要访问,store中的数据,只能通过this.$store.state.名称 15 // 16 }, 17 // 注意:操作store中的state值,通过调用mutations提供的方法, 18 // 子组件想要调用mutation中的方法,只能使用this.$store.commit('方法名') 19 // mutations的参数列表中,最多支持两个参数,参数1:state状态,参数2:通过commit传递过来的值 20 mutations:{ 21 increment(state){ 22 state.count++; 23 }, 24 subtract(state,obj){ 25 // console.log(obj); 26 state.count-=(obj.c+obj.d); 27 }, 28 29 }, 30 getters:{ 31 // 注意:这里的getters,只负责对外提供数据,不负责修改数据,修改state中的数据,找mutations 32 optCount:function(state){ 33 return '当前最新的count值是:'+state.count 34 } 35 } 36 }) 37 38 39 import app from './app.vue' 40 41 var vm=new Vue({ 42 el:'#app', 43 render:c=>c(app), 44 //5.将vuex创建的store挂载到vm实例上 45 store:store 46 // 只要挂载到了vm上,可以全局使用了 47 })
组件一使用:
1 <template> 2 <div> 3 <input type="button" value="减少" @click="del"> 4 <input type="button" value="增加" @click="add"> 5 <input type="text" v-model="this.$store.state.count"> 6 </div> 7 </template> 8 <script> 9 export default { 10 methods:{ 11 add(){ 12 // this.$store.state.count++; 13 // 不符合vuex的设计概念 14 this.$store.commit('increment'); 15 }, 16 del(){ 17 // this.$store.state.count--; 18 this.$store.commit('subtract',{c:3,d:4}); 19 } 20 } 21 } 22 </script>
组件二使用:
1 <template> 2 <div> 3 <!-- <h3>当前数量为:{{this.$store.state.count}}</h3> --> 4 <h3>{{this.$store.getters.optCount}}</h3> 5 6 </div> 7 </template> 8 <script> 9 export default { 10 11 } 12 </script>