一、 发送AJAX请求
1. 简介
vue本身不支持发送AJAX请求,需要使用vue-resource、axios等插件实现
axios是一个基于Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对vue-resource进行更新和维护
参考:GitHub上搜索axios,查看API文档
2. 使用axios发送AJAX请求
2.1 安装axios并引入
npm install axios -S
也可直接下载axios.min.js文件
2.2 基本用法
axios([options])
axios.get(url[,options]);
传参方式:
1.通过url传参
2.通过params选项传参
axios.post(url,data,[options]);
axios默认发送数据时,数据格式是Request Payload,并非我们常用的Form Data格式,
所以参数必须要以键值对形式传递,不能以json形式传参
传参方式:
1.自己拼接为键值对
2.使用transformRequest,在请求发送前将请求数据进行转换
3.如果使用模块化开发,可以使用qs模块进行转换
axios本身并不支持发送跨域的请求,没有提供相应的API,作者也暂没计划在axios添加支持发送跨域请求,所以只能使用第三方库
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>发送AJAX请求</title> <script src="js/vue.js"></script> <script src="js/axios.min.js"></script> <script src="js/vue-resource.min.js"></script> <script> window.onload=function(){ new Vue({ el:'#itany', data:{ user:{ // name:'alice', // age:19 }, uid:'' }, methods:{ send(){ axios({ method:'get', url:'user.jsonaaa' }).then(function(resp){ console.log(resp.data); }).catch(resp => { // console.log(resp); console.log('请求失败:'+resp.status+','+resp.statusText); }); }, sendGet(){ // axios.get('server.php?name=tom&age=23') axios.get('server.php',{ params:{ name:'alice', age:19 } }) .then(resp => { console.log(resp.data); }).catch(err => { console.log('请求失败:'+err.status+','+err.statusText); }); }, sendPost(){ // axios.post('server.php',{ // name:'alice', // age:19 // }) // axios.post('server.php','name=alice&age=20&') //方式1 axios.post('server.php',this.user,{ transformRequest:[ function(data){ let params=''; for(let index in data){ params+=index+'='+data[index]+'&'; } return params; } ] }) .then(resp => { console.log(resp.data); }).catch(err => { console.log('请求失败:'+err.status+','+err.statusText); }); }, getUserById(uid){ axios.get(`https://api.github.com/users/${uid}`) .then(resp => { // console.log(resp.data); this.user=resp.data; }); }, sendJSONP(){ //https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word=a this.$http.jsonp('https://sug.so.360.cn/suggest',{ params:{ word:'a' } }).then(resp => { console.log(resp.data.s); }); }, sendJSONP2(){ //https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=a&json=1&p=3&sid=1420_21118_17001_21931_23632_22072&req=2&csor=1&cb=jQuery110208075694879886905_1498805938134&_=1498805938138 this.$http.jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',{ params:{ wd:'a' }, jsonp:'cb' //百度使用的jsonp参数名为cb,所以需要修改 }).then(resp => { console.log(resp.data.s); }); } } }); } </script> </head> <body> <div id="itany"> <button @click="send">发送AJAX请求</button> <button @click="sendGet">GET方式发送AJAX请求</button> <button @click="sendPost">POST方式发送AJAX请求</button> <hr> <br> GitHub ID: <input type="text" v-model="uid"> <button @click="getUserById(uid)">获取指定GitHub账户信息并显示</button> <br> 姓名:{{user.name}} <br> 头像:<img :src="user.avatar_url" alt=""> <hr> <button @click="sendJSONP">向360搜索发送JSONP请求</button> <button @click="sendJSONP2">向百度搜索发送JSONP请求</button> </div> </body> </html>
3. 使用vue-resource发送跨域请求
3.1 安装vue-resource并引入
cnpm install vue-resource -S
3.2 基本用法
使用this.$http发送请求
this.$http.get(url, [options])
this.$http.head(url, [options])
this.$http.delete(url, [options])
this.$http.jsonp(url, [options])
this.$http.post(url, [body], [options])
this.$http.put(url, [body], [options])
this.$http.patch(url, [body], [options])
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>发送AJAX请求</title> <style> .current{ background-color:#ccc; } </style> <script src="js/vue.js"></script> <script src="js/vue-resource.min.js"></script> <script> window.onload=function(){ new Vue({ el:'#itany', data:{ keyword:'', myData:[], now:-1 //当前选中项的索引 }, methods:{ getData(e){ //如果按方向键上、下,则不发请求 if(e.keyCode==38||e.keyCode==40) return; this.$http.jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',{ params:{ wd:this.keyword }, jsonp:'cb' }).then(resp => { this.myData=resp.data.s; }); }, changeDown(){ this.now++; this.keyword=this.myData[this.now]; if(this.now==this.myData.length){ this.now=-1; } }, changeUp(){ this.now--; this.keyword=this.myData[this.now]; if(this.now==-2){ this.now=this.myData.length-1; } } } }); } </script> </head> <body> <div id="itany"> <input type="text" v-model="keyword" @keyup="getData($event)" @keydown.down="changeDown" @keydown.up.prevent="changeUp"> <ul> <li v-for="(value,index) in myData" :class="{current:index==now}"> {{value}} </li> </ul> <p v-show="myData.length==0">暂无数据....</p> </div> </body> </html>
4. 练习
百度搜索列表
课后作业:
1.只显示4条
2.回车后在新页面中显示搜索结果
二、Vue生命周期
vue实例从创建到销毁的过程,称为生命周期,共有八个阶段
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue生命周期</title> <script src="js/vue.js"></script> <script> window.onload=function(){ let vm=new Vue({ el:'#itany', data:{ msg:'welcome to itany' }, methods:{ update(){ this.msg='欢迎来到南京网博!'; }, destroy(){ // this.$destroy(); vm.$destroy(); } }, beforeCreate(){ alert('组件实例刚刚创建,还未进行数据观测和事件配置'); }, created(){ //常用!!! alert('实例已经创建完成,并且已经进行数据观测和事件配置'); }, beforeMount(){ alert('模板编译之前,还没挂载'); }, mounted(){ //常用!!! alert('模板编译之后,已经挂载,此时才会渲染页面,才能看到页面上数据的展示'); }, beforeUpdate(){ alert('组件更新之前'); }, updated(){ alert('组件更新之后'); }, beforeDestroy(){ alert('组件销毁之前'); }, destroyed(){ alert('组件销毁之后'); } }); } </script> </head> <body> <div id="itany"> {{msg}} <br> <button @click="update">更新数据</button> <button @click="destroy">销毁组件</button> </div> </body> </html>
三、计算属性
1. 基本用法
计算属性也是用来存储数据,但具有以下几个特点:
a.数据可以进行逻辑处理操作
b.对计算属性中的数据进行监视
2.计算属性 vs 方法
将计算属性的get函数定义为一个方法也可以实现类似的功能
区别:
a.计算属性是基于它的依赖进行更新的,只有在相关依赖发生改变时才能更新变化
b.计算属性是缓存的,只要相关依赖没有改变,多次访问计算属性得到的值是之前缓存的计算结果,不会多次执行
3. get和set
计算属性由两部分组成:get和set,分别用来获取计算属性和设置计算属性
默认只有get,如果需要set,要自己添加
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>计算属性</title> <script src="js/vue.js"></script> </head> <body> <div id="itany"> <!-- 1.基本用法 --> <h2>{{msg}}</h2> <h2>{{msg2}}</h2> <!-- 对数据处理再显示 --> <h2>{{msg.split(' ').reverse().join(' ')}}</h2> <h2>{{reverseMsg}}</h2> <button @click="change">修改值</button> <!-- 2.计算属性 vs 方法 --> <!-- <h2>{{num1}}</h2> <h2>{{num2}}</h2> <h2>{{getNum2()}}</h2> --> <button onclick="fn()">测试</button> <!-- 3.get和set --> <h2>{{num2}}</h2> <button @click="change2">修改计算属性</button> </div> <script> var vm=new Vue({ el:'#itany', data:{ //普通属性 msg:'welcome to itany', num1:8 }, computed:{ //计算属性 msg2:function(){ //该函数必须有返回值,用来获取属性,称为get函数 return '欢迎来到南京网博'; }, reverseMsg:function(){ //可以包含逻辑处理操作,同时reverseMsg依赖于msg return this.msg.split(' ').reverse().join(' '); }, num2:{ get:function(){ console.log('num2:'+new Date()); return this.num1-1; }, set:function(val){ // console.log('修改num2值'); // this.num2=val; this.num1=111; } } }, methods:{ change(){ // this.msg='i love you'; this.num1=666; }, getNum2(){ console.log(new Date()); return this.num1-1; }, change2(){ this.num2=111; } } }); function fn(){ setInterval(function(){ // console.log(vm.num2); console.log(vm.getNum2()); },1000); } </script> </body> </html>
四、 vue实例的属性和方法
1. 属性
vm.$el
vm.$data
vm.$options
vm.$refs
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue实例的属性和方法</title> <script src="js/vue.js"></script> </head> <body> <div id="itany"> {{msg}} <h2 ref="hello">你好</h2> <p ref="world">世界</p> <hr> <h1 ref="title">标题:{{name}}</h1> </div> <script> /*var vm=new Vue({ // el:'#itany', data:{ msg:'welcome to itany' }, name:'tom', age:24, show:function(){ console.log('show'); } });*/ /** * 属性 */ //vm.属性名 获取data中的属性 // console.log(vm.msg); //vm.$el 获取vue实例关联的元素 // console.log(vm.$el); //DOM对象 // vm.$el.style.color='red'; //vm.$data //获取数据对象data // console.log(vm.$data); // console.log(vm.$data.msg); //vm.$options //获取自定义属性 // console.log(vm.$options.name); // console.log(vm.$options.age); // vm.$options.show(); //vm.$refs 获取所有添加ref属性的元素 // console.log(vm.$refs); // console.log(vm.$refs.hello); //DOM对象 // vm.$refs.hello.style.color='blue'; /** * 方法 */ //vm.$mount() 手动挂载vue实例 // vm.$mount('#itany'); var vm=new Vue({ data:{ msg:'欢迎来到南京网博', name:'tom' } }).$mount('#itany'); //vm.$destroy() 销毁实例 // vm.$destroy(); // vm.$nextTick(callback) 在DOM更新完成后再执行回调函数,一般在修改数据之后使用该方法,以便获取更新后的DOM //修改数据 vm.name='汤姆'; //DOM还没更新完,Vue实现响应式并不是数据发生改变之后DOM立即变化,需要按一定的策略进行DOM更新,需要时间!! // console.log(vm.$refs.title.textContent); vm.$nextTick(function(){ //DOM更新完成,更新完成后再执行此代码 console.log(vm.$refs.title.textContent); }); </script> </body> </html>
2. 方法
vm.$mount()
vm.$destroy()
vm.$nextTick(callback)
vm.$set(object,key,value)
vm.$delete(object,key)
vm.$watch(data,callback[,options])
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加和删除属性:$set、$delete</title> <script src="js/vue.js"></script> </head> <body> <div id="itany"> <button @click="doUpdate">修改属性</button> <button @click="doAdd">添加属性</button> <button @click="doDelete">删除属性</button> <hr> <h2>{{user.name}}</h2> <h2>{{user.age}}</h2> </div> <script> var vm=new Vue({ el:'#itany', data:{ user:{ id:1001, name:'tom' } }, methods:{ doUpdate(){ this.user.name='汤姆' }, doAdd(){ // this.user.age=25; //通过普通方式为对象添加属性时vue无法实时监视到 // this.$set(this.user,'age',18); //通过vue实例的$set方法为对象添加属性,可以实时监视 // Vue.set(this.user,'age',22); if(this.user.age){ this.user.age++; }else{ Vue.set(this.user,'age',1); } // console.log(this.user); }, doDelete(){ if(this.user.age){ // delete this.user.age; //无效 Vue.delete(this.user,'age'); } } } }); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>监视数据的变化:$watch</title> <script src="js/vue.js"></script> </head> <body> <div id="itany"> <input type="text" v-model="name"> <h3>{{name}}</h3> <hr> <input type="text" v-model="age"> <h3>{{age}}</h3> <hr> <input type="text" v-model="user.name"> <h3>{{user.name}}</h3> </div> <script> var vm=new Vue({ el:'#itany', data:{ name:'tom', age:23, user:{ id:1001, name:'alice' } }, watch:{ //方式2:使用vue实例提供的watch选项 age:(newValue,oldValue) => { console.log('age被修改啦,原值:'+oldValue+',新值:'+newValue); }, user:{ handler:(newValue,oldValue) => { console.log('user被修改啦,原值:'+oldValue.name+',新值:'+newValue.name); }, deep:true //深度监视,当对象中的属性发生变化时也会监视 } } }); //方式1:使用vue实例提供的$watch()方法 vm.$watch('name',function(newValue,oldValue){ console.log('name被修改啦,原值:'+oldValue+',新值:'+newValue); }); </script> </body> </html>
五、自定义指令
分类:全局指令、局部指令
1. 自定义全局指令
使用全局方法Vue.directive(指令ID,定义对象)
2. 自定义局部指令
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>自定义指令</title> <script src="js/vue.js"></script> </head> <body> <div id="itany"> <!-- <h3 v-hello>{{msg}}</h3> --> <button @click="change">更新数据</button> <h3 v-world:wbs17022.hehe.haha="username">{{msg}}</h3> <!-- <p v-world>网博,专业的前端培训</p> --> <!-- <h3 v-wbs>网博</h3> --> <input type="text" v-model="msg" v-focus> </div> <script> /** * 自定义全局指令 * 注:使用指令时必须在指名名称前加前缀v-,即v-指令名称 */ Vue.directive('hello',{ bind(){ //常用!! alert('指令第一次绑定到元素上时调用,只调用一次,可执行初始化操作'); }, inserted(){ alert('被绑定元素插入到DOM中时调用'); }, update(){ alert('被绑定元素所在模板更新时调用'); }, componentUpdated(){ alert('被绑定元素所在模板完成一次更新周期时调用'); }, unbind(){ alert('指令与元素解绑时调用,只调用一次'); } }); //钩子函数的参数 Vue.directive('world',{ bind(el,binding){ // console.log(el); //指令所绑定的元素,DOM对象 // el.style.color='red'; console.log(binding); //name } }); //传入一个简单的函数,bind和update时调用 Vue.directive('wbs',function(){ alert('wbs17022'); }); var vm=new Vue({ el:'#itany', data:{ msg:'welcome to itany', username:'alice' }, methods:{ change(){ this.msg='欢迎来到南京网博' } }, directives:{ //自定义局部指令 focus:{ //当被绑定元素插入到DOM中时获取焦点 inserted(el){ el.focus(); } } } }); </script> </body> </html>
3. 练习
拖动页面中的元素
onmouseover onmouseout
onmousedown onmousemove onmouseup
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>练习:自定义指令</title> <script src="js/vue.js"></script> <style> #itany div{ width: 100px; height: 100px; position:absolute; } #itany .hello{ background-color:red; top:0; left:0; } #itany .world{ background-color:blue; top:0; right:0; } </style> </head> <body> <div id="itany"> <div class="hello" v-drag>itany</div> <div class="world" v-drag>网博</div> </div> <script> Vue.directive('drag',function(el){ el.onmousedown=function(e){ //获取鼠标点击处分别与div左边和上边的距离:鼠标位置-div位置 var disX=e.clientX-el.offsetLeft; var disY=e.clientY-el.offsetTop; // console.log(disX,disY); //包含在onmousedown里面,表示点击后才移动,为防止鼠标移出div,使用document.onmousemove document.onmousemove=function(e){ //获取移动后div的位置:鼠标位置-disX/disY var l=e.clientX-disX; var t=e.clientY-disY; el.style.left=l+'px'; el.style.top=t+'px'; } //停止移动 document.onmouseup=function(e){ document.onmousemove=null; document.onmouseup=null; } } }); var vm=new Vue({ el:'#itany', data:{ msg:'welcome to itany', username:'alice' }, methods:{ change(){ this.msg='欢迎来到南京网博' } } }); </script> </body> </html>
六、过渡(动画)
1. 简介
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果
本质上还是使用CSS3动画:transition、animation
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动画</title> <script src="js/vue.js"></script> <style> p{ width: 300px; height: 300px; background-color:red; } .fade-enter-active,.fade-leave-active{ transition:all 3s ease; } .fade-enter-active{ opacity:1; width:300px; height:300px; } .fade-leave-active{ opacity:0; width:50px; height:50px; } /* .fade-enter需要放在.fade-enter-active的后面 */ .fade-enter{ opacity:0; width: 100px; height: 100px; } </style> </head> <body> <div id="itany"> <button @click="flag=!flag">点我</button> <transition name="fade" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" @before-leave="beforeLeave" @leave="leave" @after-leave="afterLeave" > <p v-show="flag">网博</p> </transition> </div> <script> var vm=new Vue({ el:'#itany', data:{ flag:false }, methods:{ beforeEnter(el){ // alert('动画进入之前'); }, enter(){ // alert('动画进入'); }, afterEnter(el){ // alert('动画进入之后'); el.style.background='blue'; }, beforeLeave(){ // alert('动画即将之前'); }, leave(){ // alert('动画离开'); }, afterLeave(el){ // alert('动画离开之后'); el.style.background='red'; } } }); </script> </body> </html>
2. 基本用法
使用transition组件,将要执行动画的元素包含在该组件内
<transition>
运动的元素
</transition>
过滤的CSS类名:6个
3. 钩子函数
8个
4. 结合第三方动画库animate..css一起使用
<transition enter-active-class="animated fadeInLeft" leave-active-class="animated fadeOutRight">
<p v-show="flag">网博</p>
</transition>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动画</title> <link rel="stylesheet" href="css/animate.css"> <script src="js/vue.js"></script> <style> p{ width: 300px; height: 300px; background-color:red; margin:0 auto; } </style> </head> <body> <div id="itany"> <button @click="flag=!flag">点我</button> <transition enter-active-class="animated fadeInLeft" leave-active-class="animated fadeOutRight"> <p v-show="flag">网博</p> </transition> </div> <script> var vm=new Vue({ el:'#itany', data:{ flag:false } }); </script> </body> </html>
5. 多元素动画
<transition-group>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>多元素动画</title> <link rel="stylesheet" href="css/animate.css"> <script src="js/vue.js"></script> <style> p{ width: 100px; height: 100px; background-color:red; margin:20px auto; } </style> </head> <body> <div id="itany"> <button @click="flag=!flag">点我</button> <transition-group enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight"> <p v-show="flag" :key="1">itany</p> <p v-show="flag" :key="2">网博</p> </transition-group> </div> <script> var vm=new Vue({ el:'#itany', data:{ flag:false } }); </script> </body> </html>
6. 练习
多元素动画
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>练习:多元素动画</title> <link rel="stylesheet" href="css/animate.css"> <script src="js/vue.js"></script> <style> p{ width: 100px; height: 100px; background-color:red; margin:20px auto; } </style> </head> <body> <div id="itany"> <input type="text" v-model="name"> <transition-group enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight"> <p v-for="(v,k) in arr2" :key="k"> {{v}} </p> </transition-group> </div> <script> var vm=new Vue({ el:'#itany', data:{ flag:true, arr:['tom','jack','mike','alice','alex','mark'], name:'' }, computed:{ arr2:function(){ var temp=[]; this.arr.forEach(val => { if(val.includes(this.name)){ temp.push(val); } }); return temp; } } }); </script> </body> </html>