## 一、 发送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添加支持发送跨域请求,所以只能使用第三方库
### 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])
### 4. 练习
百度搜索列表
课后作业:
1.只显示4条
2.回车后在新页面中显示搜索结果
## 二、Vue生命周期
vue实例从创建到销毁的过程,称为生命周期,共有八个阶段
## 三、计算属性
### 1. 基本用法
计算属性也是用来存储数据,但具有以下几个特点:
a.数据可以进行逻辑处理操作
b.对计算属性中的数据进行监视
### 2.计算属性 vs 方法
将计算属性的get函数定义为一个方法也可以实现类似的功能
区别:
a.计算属性是基于它的依赖进行更新的,只有在相关依赖发生改变时才能更新变化
b.计算属性是缓存的,只要相关依赖没有改变,多次访问计算属性得到的值是之前缓存的计算结果,不会多次执行
### 3. get和set
计算属性由两部分组成:get和set,分别用来获取计算属性和设置计算属性
默认只有get,如果需要set,要自己添加
## 四、 vue实例的属性和方法
### 1. 属性
vm.$el
vm.$data
vm.$options
vm.$refs
### 2. 方法
vm.$mount()
vm.$destroy()
vm.$nextTick(callback)
vm.$set(object,key,value)
vm.$delete(object,key)
vm.$watch(data,callback[,options])
## 五、自定义指令
分类:全局指令、局部指令
### 1. 自定义全局指令
使用全局方法Vue.directive(指令ID,定义对象)
### 2. 自定义局部指令
### 3. 练习
拖动页面中的元素
onmouseover onmouseout
onmousedown onmousemove onmouseup
## 六、过渡(动画)
### 1. 简介
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果
本质上还是使用CSS3动画:transition、animation
### 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>
### 5. 多元素动画
<transition-group>
### 6. 练习
多元素动画
<!DOCTYPE html>
<html>
<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:'#itan',
data:{
user:{
name:'alice',
age:19
},
uid:''
},
methods:{
send(){
axios({
methods:'get',
url:'user.json'
}).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);
});
},
// 使用transformRequest,在请求发送前将请求数据进行转换
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="itan">
<button @click="send">发送AJAX请求</button>
<button @click="sendGet">GET方式发送AJAX请求</button>
<button @click="sendPost">POST方式发送AJAX请求</button>
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>
<hr>
<br>
</div>
</body>
</html>
<!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>
<!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>
<!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=250;
}
}
},
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>
<!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>
<!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>
<!DOCTYPE html>
<html>
<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 ma an shan',
username:'alice'
},
methods:{
change(){
this.msg='欢迎来到马鞍山'
}
},
deactivated:{//自定义局部命令
focus:{
//当被绑定元素插入到Dom 中时 获取焦点
inserted(el){
el.focus();
}
}
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<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="word" 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>
<!DOCTYPE html>
<html>
<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>
<!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>
<!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>
<!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>