Vue学习:基础精讲
Vue学习:基础精讲
一、Vue实例
new Vue创建Vue实例,el代表Vue接管的DOM的所有显示,data里面用于存放数据,由于Vue接管了app部分,所以会对DOM里面的语法进行分析,发现运用了{{}}插值表达式,就会去data里面寻找对应的数据,利用这个数据替换掉这个插值表达式
同时Vue也可以分析出DOM所绑定的事件,所以当点击DOM元素的时候,就会去Vue实例寻找对应的方法
程序的入口便是从Vue实例开始执行,Vue就是一个根实例,Vue中的每一个组件也是一个Vue实例,当我们创建一个组件的时候,Vue的底层也会将它编译成一个Vue的实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<div v-on:click="handleClick">
{{message}}
</div>
<item></item>
</div>
</body>
<script>
//组件也是Vue实例
Vue.component('item',{
template:'<div>hello world</div>'
})
var vm = new Vue({
//接管的DOM
el:'#app',
//数据,实例属性,引用的时候便是$data
data:{
message:'Derrick'
},
//方法
methods:{
handleClick:function(){
alert("hello")
}
}
})
</script>
</html>
二、实例生命周期钩子
- 将el外部的HTML作为template编译:当Vue实例没有template模板的时候,会把el接管部分作为模板来进行渲染
- 将template编译到渲染函数中:当Vue实例有template模板的时候,就会利用template模板去渲染
- 虚拟DOM重新渲染并应用更新:当数据改变时执行
//没有指定template
<div id="app">
hello Derri
</div>
<script>
var vm = new Vue({
el:"#app",
...
//指定template
<div id="app">
</div>
<script>
var vm = new Vue({
el:"#app",
template:"<div> Derri </div>",
...
//以上两者渲染效果一样
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
</div>
</body>
<script>
//生命周期函数就是Vue实例在某一个时间点会自动执行的函数
var vm = new Vue({
el:"#app",
template:"<div> Derri </div>",
//自动执行
beforeCreate:function(){
console.log("beforeCreate")
},
//自动执行
created:function(){
console.log("created")
},
//页面渲染之前,模板和数据相结合准备挂载到页面之前
beforeMount:function(){
console.log("beforeMount");
console.log(this.$el);
},
//页面挂载之后
mounted:function(){
console.log("mounted");
console.log(this.$el);
},
//当组件销毁的时候才会开始执行,利用vm.$destroy()
beforeDestory:function(){
console.log("beforeDestory");
},
destoryed:function(){
console.log("destoryed");
},
//数据改变还没被渲染之前
beforeUpdate:function(){
console.log("beforeUpdate");
},
//数据改变并且渲染之后
updated:function(){
console.log("updated");
}
})
</script>
</html>
三、Vue模板语法
- 插值表达式:{{XXX}}
- v-text:v-text=”XXX“,当我们看到Vue指令跟着一个值的时候,值便不再是字符串而是js表达式,这里v-text是让div里面的inner-text的内容变成name里面数据的内容
- v-html:v-html=”XXX“,这里v-html是让div里面的inner-html的内容变成name里面数据的内容,与name进行数据绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
{{name + ' Jessica'}}
<!--v后面的双引号都是js表达式,所以可以进行字符串拼接-->
<div v-text="name + ' Jessica'"></div>
<div v-html="name"></div>
</div>
</body>
<script>
//生命周期函数就是Vue实例在某一个时间点会自动执行的函数
var vm = new Vue({
el:"#app",
data:{
name:"Derrick"
}
})
</script>
</html>
四、计算属性,方法和侦听器
4.1 计算属性
computed计算属性,下面的fullName便是计算而来,计算属性具有一定的缓存机制,例如这里的firstName与lastName不改变的话,就不会再次计算,由于age不属于计算范围,所以改变的时候不会再次计算,当改变firstName的时候才会再次计算
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
{{fullName}}
{{age}}
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
firstName:"Derrick",
lastName:"Xu",
age:28
},
//计算属性
computed:{
//fullName是经过计算得来的,
fullName:function(){
console.log("进行计算");
return this.firstName+" "+this.lastName;
}
}
})
</script>
</html>
4.2 方法
methods方法属性,也可以实现4.1中拼接fullName的功能,但是性能比计算属性较差,因为fullName没有改变的之后依旧需要重新调用方法,没有缓存机制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!--由于是方法,需要加上()-->
{{fullName()}}
{{age}}
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
firstName:"Derrick",
lastName:"Xu",
age:28
},
//方法,同样可以实现fullName功能
methods:{
fullName:function(){
return this.firstName+" "+this.lastName
}
}
})
</script>
</html>
4.3 侦听器
侦听器,当firstName或者lastName改变的时候重新给fullName赋值,当在控制台改变age的时候是不会调用侦听器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!--由于是方法,需要加上()-->
{{fullName()}}
{{age}}
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
firstName:"Derrick",
lastName:"Xu",
fullName:"Derrick Xu",
age:28
},
//侦听器,当firstName或者lastName改变的时候重新给fullName赋值
watch:{
firstName:function(){
this.fullName = this.firstName+" "+this.lastName
},
lastName:function(){
this.fullName = this.firstName+" "+this.lastName
}
}
})
</script>
</html>
4.4 计算属性的getter和setter
computed计算属性,将fullName定义成一个对象,插值表达式去读取fullName的时候会转到fullName的get方法,set方法用于设置属性值,接收外部传递过来的value
当在控制台设置fullName的时候,将接收到的value拆分赋值给firstName跟lastName,由于计算属性具有一定的缓存机制,firstName跟lastName改变了,所以会重新计算fullName
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
{{fullName}}
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
firstName:"Derrick",
lastName:"Xu",
},
computed:{
//将fullName写成一个对象
fullName:{
//插值表达式去读取fullName的时候会转到fullName的get方法
get:function(){
return this.firstName+" "+this.lastName;
},
//设置属性值,接收外部传递过来的value
set:function(value){
//拆分value为数组
var arr = value.split(" ");
this.firstName = arr[0];
this.lastName = arr[1];
console.log(value);
}
}
}
})
</script>
</html>
五、样式绑定
前提说明:点击Hello World变成红色,再次点击变回原色
5.1 class对象绑定:借助class与对象的形式来做样式与数据的绑定
:class="{activated: isActivated}说明div需要有个class,名字为activated,class是否起作用取决于isActivated
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
<style>
.activated{
color:red;
}
</style>
</head>
<body>
<div id="app">
<!--说明div需要有个class,名字为activated,class是否起作用取决于isActivated-->
<div @click="handleDivClick"
:class="{activated: isActivated}">
Hello world
</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
isActivated:false
},
methods:{
handleDivClick:function(){
//改变isActivated的值,决定activated class是否显示
this.isActivated = !this.isActivated;
}
}
})
</script>
</html>
5.2 class对象绑定:借助class与数组的形式来做样式与数据的绑定
class="[activated]"说明div需要有个class,class取值显示的内容为activated里面的内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
<style>
.activated{
color:red;
}
</style>
</head>
<body>
<div id="app">
<!--说明div需要有个class,class显示的内容为activated里面的内容-->
<div @click="handleDivClick"
:class="[activated]">
Hello world
</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
activated:""
},
methods:{
handleDivClick:function(){
//将变量设置为activated,所以class的值便会取到这个activated字符串作为class的名字
if(this.activated === "activated"){
this.activated ="";
}else{
this.activated = "activated";
}
}
}
})
</script>
</html>
5.3 style
:style=“styleObj"使用的是对象,这里说明让div有样式,样式是颜色是红色。:style=”[styleObj]"使用的是数组,说明div的style由数组里面的对象决定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!--使用对象-->
<div :style="styleObj" @click="handleDivClick">
Hello world
</div>
<!--使用数组-->
<div :style="[styleObj,{fontSize:'20px'}]" @click="handleDivClick">
Hello world
</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
//说明让div有样式,样式是颜色是红色
styleObj:{
color:"black"
}
},
methods:{
handleDivClick:function(){
this.styleObj.color = this.styleObj.color==="black" ? "red" : "black";
}
}
})
</script>
</html>
六、条件渲染
v-if="XXX"后面接的依旧是js表达式,条件软件便是通过v-if结合js表达式返回值去决定一个标签是否显示与存在,v-show类似于v-if,两者都可以控制标签是否显示,但是有区别,当都为false的时候,v-show依旧会渲染到页面上,但是display设置成了none
6.1 v-if与v-show
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<div v-if="show">{{message}}</div>
<div v-show="show">{{message}}</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
show:false,
message:"Hello Derrick"
}
})
</script>
</html>
6.2 v-if的复杂使用
v-if可以与v-else结合一起使用,但是中间不能被其他标签隔开
6.2.1 if-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!---->
<div v-if="show">{{message1}}</div>
<div v-else=>{{message2}}</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
show:false,
message1:"Hello Derrick",
message2:"Hello Jessica"
}
})
</script>
</html>
6.2.2 if-elseif-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<div v-if="show === 'a'">This is a</div>
<div v-else-if="show === 'b'">This is b</div>
<div v-else>This is others</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
show:"a"
}
})
</script>
</html>
6.2.3 DOM元素复用问题
一开始show为false,显示的是邮箱名,输入完之后去控制台修改show为true,显示用户名,但是input框没有清空,这是vue会尽量让DOM元素复用,这时候需要给input加入key属性,让vue知道这是唯一的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Derrick</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<div v-if="show">
用户名:<input/>
<!--加入key值-->
用户名:<input key="username"/>
</div>
<div v-else>
邮箱名:<input/>
<!--加入key值-->
邮箱名:<input key="email"/>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
show:false,
}
})
</script>
</html>
七、列表渲染
7.1 简单的列表渲染
7.1.1 循环item
<body>
<div id="app">
<div v-for="item of list">
{{item}}
</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
list:[
"1",
"2",
"3",
"4"
]
}
})
</script>
7.1.2 循环item、index
<body>
<div id="app">
<div v-for="(item,index) of list">
{{item}} ---- {{index}}
</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
list:[
"1",
"2",
"3",
"4"
]
}
})
</script>
7.2 引入key值,数据模拟数据库
key尽量使用唯一的,但是不建议使用index,一般使用后台数据库返回的id,使用key值可以提高性能,用v-for更新已渲染的元素列表的时候,会使用就地复用的策略。这就是说列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改了就重新渲染,不然就复用之前的元素
<body>
<div id="app">
<div v-for="(item,index) of list"
:key="item.id">
{{item.text}} ---- {{index}}
</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
list:[
{
id:"1",
text:"hello"
},
{
id:"2",
text:"Derrick"
},
{
id:"3",
text:"Jessica"
}
]
}
})
</script>
7.3 往List添加新数据
不建议使用下标的添加,数据会添加成功,但是页面不会更新数据,vue提供了7个操作列表的方法:pop是删除数据最后一项,push往数组添加一条数据,shift删除数组第一项,unshift往数组第一项增加一些内容,splice用于截取数组,sort对数组进行排序,reverse对数组进行取反
7.3.1 利用下标改变页面不会刷新
7.3.2 splice,从数组第一项开始操作,删除一项,并添加一项
所以7.3.1中的Derrick被删除,从第一项这里添加新的数据
7.3.3 通过改变引用来改变数据
7.4 模板占位符包裹元素循环
template模板占位符可以帮我们包裹元素用于循环,但是它不会被渲染到页面上
<body>
<div id="app">
<template v-for="(item,index) of list"
:key="item.id">
<div>
{{item.text}} ---- {{index}}
</div>
<span>
{{item.text}}
</span>
</template>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
list:[
{
id:"1",
text:"hello"
},
{
id:"2",
text:"Derrick"
},
{
id:"3",
text:"Jessica"
}
]
}
})
</script>
7.5 对象循环
7.5.1 普通例子
<body>
<div id="app">
<div v-for="(item,key,index) of userInfo">
{{item}}---{{key}}---{{index}}
</div>
</div>
</body>
<script>
var vm = new Vue({
el:"#app",
data:{
userInfo:{
name:"Derrick",
age:"22",
gender:"male",
salary:"student"
}
}
})
</script>
7.5.2 改变对象数据
在控制台改变对象属性值的时候,会实时更新
7.5.3 往对象插入数据
插入属性键值对的时候页面不会实时刷新
7.5.4 改变引用弥补7.5.3问题
八、Vue中set方法
8.1 对象中的set
set方法是Vue全局的方法,同时也是vue的实例方法,利用set方法弥补7.5.3问题
8.2 数据中的set
例子中说明是将第一项的值改为5,将第二项的值改为10